I try to implement a way to trigger the open-database-method from a plugin.
I can call host.MainWindow.OpenDatabase()
I also have access to the DocumentManager for the LockIOC: host.MainWindow.DocumentManager.ActiveDocument.LockedIoc
But then KeePass checks if the database was opened successfully: if(pd.IsOpen)
{
ds.LockedIoc = new IOConnectionInfo(); // Clear lock
RestoreWindowState(pd);
}
Now I clear the LockedIoc --> no problem.
But RestoreWindowState() for the selected database is a private method. I could copy it to my plugin, but in this private method are other private methods and so on.
Is there an easy way to trigger the event of unlocking a database?
Thank you.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'd recommend first using host.MainWindow.OpenDatabase to unlock/open the database, then search for the correct PwDocument object in host.MainWindow.DocumentManager.Documents, test whether the database has been opened successfully (by doc.Database.IsOpen), and if so, call host.MainWindow.MakeDocumentActive(doc) (this will among other things restore the window state).
Of course the last step should only be performed if the database is expected to be activated. If it's acceptable that the database is opened in the background, simply do not call MakeDocumentActive; KeePass will restore the window state when the user switches to the database's tab.
Please do not modify the LockedIoc property in a plugin.
Best regards,
Dominik
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
My code currently looks like this:
if (!host.Database.IsOpen)
{
host.MainWindow.OpenDatabase(host.MainWindow.DocumentManager.ActiveDocument.LockedIoc, null, false);
}
But then I get the following error message.
I think it's because of the attribute LockedIoc which I need to define in OpenDatabase :-/
When I try to set ioConnection to null nothing happens and I'm no longer able to unlock the database manually.
See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.
** Exception Text **
System.InvalidOperationException: DragDrop registration did not succeed. ---> System.Threading.ThreadStateException: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.
at System.Windows.Forms.Control.SetAcceptDrops(Boolean accept)
--- End of inner exception stack trace ---
at System.Windows.Forms.Control.SetAcceptDrops(Boolean accept)
at System.Windows.Forms.Control.set_AllowDrop(Boolean value)
at KeePass.UI.SecureEdit.Attach(TextBox tbPasswordBox, EventHandler evTextChanged, Boolean bHidePassword)
at KeePass.Forms.KeyPromptForm.OnFormLoad(Object sender, EventArgs e)
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
** JIT Debugging **
To enable just-in-time (JIT) debugging, the .config file for this
application or computer (machine.config) must have the
jitDebugging value set in the system.windows.forms section.
The application must also be compiled with debugging
enabled.
When JIT debugging is enabled, any unhandled exception
will be sent to the JIT debugger registered on the computer
rather than be handled by this dialog box.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The exception indicates a threading problem. Make sure your code is running on the main window thread. If you're running on a different thread, e.g. put the code into a method and call this method using host.MainWindow.Invoke (to run it on the main window thread).
Best regards,
Dominik
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
When the invoke is called it starts blinking in the background.
Is it also possible to bring it into foreground, even if it's minimized to tray?
I already tried to call host.MainWindow.BringToFront(), but doesn't work.
Also the open-dialog doesn't blink if KeePass is minimized and OpenDatabase() is called.
Last edit: lspcity 2013-03-24
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You can restore the KeePass window (from tray or from taskbar) by calling host.MainWindow.EnsureVisibleForegroundWindow(true, true).
Note this might trigger an automatic unlock, thus you might want to run your other code after the window restoration.
If the window does not come to the foreground when calling EnsureVisibleForegroundWindow, Windows has prevented it, e.g. in order to not disturb the user when he's working in a different window; the KeePass window then just blinks in the taskbar.
Best regards,
Dominik
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Some weeks ago I also tried the function EnsureVisibleForegroundWinodw and I got an error. Now I understand "why" and "how" I can call it correctly: With host.MainWindow.Invoke()!
Thank you.
Now it works great :-)
By the way, it's for unlocking the database when requesting credentials with KeePassHttp
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry for the late reply; for some reason I didn't get a notification e-mail for your post.
You can test whether the master key dialog is displayed by
bool bKpf = ((KeePass.UI.GlobalWindowManager.TopWindow as KeyPromptForm) != null);
One disadvantage of this approach is that when the user e.g. opens the key file browser dialog (from the master key dialog) on the secure desktop, the above code will evaluate to false, because the master key dialog is only the second-topmost window.
Thus I would instead recommend to test whether no sub-dialog is opened at all.
I try to implement a way to trigger the open-database-method from a plugin.
I can call host.MainWindow.OpenDatabase()
I also have access to the DocumentManager for the LockIOC: host.MainWindow.DocumentManager.ActiveDocument.LockedIoc
But then KeePass checks if the database was opened successfully:
if(pd.IsOpen)
{
ds.LockedIoc = new IOConnectionInfo(); // Clear lock
RestoreWindowState(pd);
}
Now I clear the LockedIoc --> no problem.
But RestoreWindowState() for the selected database is a private method. I could copy it to my plugin, but in this private method are other private methods and so on.
Is there an easy way to trigger the event of unlocking a database?
Thank you.
I'd recommend first using host.MainWindow.OpenDatabase to unlock/open the database, then search for the correct PwDocument object in host.MainWindow.DocumentManager.Documents, test whether the database has been opened successfully (by doc.Database.IsOpen), and if so, call host.MainWindow.MakeDocumentActive(doc) (this will among other things restore the window state).
Of course the last step should only be performed if the database is expected to be activated. If it's acceptable that the database is opened in the background, simply do not call MakeDocumentActive; KeePass will restore the window state when the user switches to the database's tab.
Please do not modify the LockedIoc property in a plugin.
Best regards,
Dominik
Thank you for your fast reply.
My code currently looks like this:
if (!host.Database.IsOpen)
{
host.MainWindow.OpenDatabase(host.MainWindow.DocumentManager.ActiveDocument.LockedIoc, null, false);
}
But then I get the following error message.
I think it's because of the attribute LockedIoc which I need to define in OpenDatabase :-/
When I try to set ioConnection to null nothing happens and I'm no longer able to unlock the database manually.
See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.
** Exception Text **
System.InvalidOperationException: DragDrop registration did not succeed. ---> System.Threading.ThreadStateException: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.
at System.Windows.Forms.Control.SetAcceptDrops(Boolean accept)
--- End of inner exception stack trace ---
at System.Windows.Forms.Control.SetAcceptDrops(Boolean accept)
at System.Windows.Forms.Control.set_AllowDrop(Boolean value)
at KeePass.UI.SecureEdit.Attach(TextBox tbPasswordBox, EventHandler evTextChanged, Boolean bHidePassword)
at KeePass.Forms.KeyPromptForm.OnFormLoad(Object sender, EventArgs e)
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
** Loaded Assemblies **
mscorlib
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.18034 built by: FX45RTMGDR
CodeBase: file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/mscorlib.dll
----------------------------------------
KeePass
Assembly Version: 2.21.0.21106
Win32 Version: 2.21.0.0
CodeBase: file:///p:/dev/C%23/keepasshttp/%23portable/KeePass.exe
----------------------------------------
System.Windows.Forms
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.18036 built by: FX45RTMGDR
CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System.Drawing
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.18021 built by: FX45RTMGDR
CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Drawing/v4.0_4.0.0.0b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.18034 built by: FX45RTMGDR
CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System/v4.0_4.0.0.0b77a5c561934e089/System.dll
----------------------------------------
System.Xml
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.18034 built by: FX45RTMGDR
CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Xml/v4.0_4.0.0.0b77a5c561934e089/System.Xml.dll
----------------------------------------
System.Configuration
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.17929 built by: FX45RTMREL
CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Configuration/v4.0_4.0.0.0b03f5f7f11d50a3a/System.Configuration.dll
----------------------------------------
KeePassHttp
Assembly Version: 2.21.0.0
Win32 Version: 1.1.4.0
CodeBase: file:///C:/Users/Lukas/AppData/Local/KeePass/PluginCache/9hMAAnVEAN07yfCTJyni/KeePassHttp.dll
----------------------------------------
System.Security
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.18021 built by: FX45RTMGDR
CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Security/v4.0_4.0.0.0b03f5f7f11d50a3a/System.Security.dll
----------------------------------------
Newtonsoft.Json
Assembly Version: 3.5.0.0
Win32 Version: 3.5.0.0
CodeBase: file:///C:/Users/Lukas/AppData/Local/KeePass/PluginCache/9hMAAnVEAN07yfCTJyni/Newtonsoft.Json.DLL
----------------------------------------
** JIT Debugging **
To enable just-in-time (JIT) debugging, the .config file for this
application or computer (machine.config) must have the
jitDebugging value set in the system.windows.forms section.
The application must also be compiled with debugging
enabled.
For example:
<configuration>
<system.windows.forms jitDebugging="true"/>
</configuration>
When JIT debugging is enabled, any unhandled exception
will be sent to the JIT debugger registered on the computer
rather than be handled by this dialog box.
Your code looks good to me.
The exception indicates a threading problem. Make sure your code is running on the main window thread. If you're running on a different thread, e.g. put the code into a method and call this method using host.MainWindow.Invoke (to run it on the main window thread).
Best regards,
Dominik
Wow, great!
That works pefectly. Thank you!
One more improvement:
When the invoke is called it starts blinking in the background.
Is it also possible to bring it into foreground, even if it's minimized to tray?
I already tried to call host.MainWindow.BringToFront(), but doesn't work.
Also the open-dialog doesn't blink if KeePass is minimized and OpenDatabase() is called.
Last edit: lspcity 2013-03-24
You can restore the KeePass window (from tray or from taskbar) by calling host.MainWindow.EnsureVisibleForegroundWindow(true, true).
Note this might trigger an automatic unlock, thus you might want to run your other code after the window restoration.
If the window does not come to the foreground when calling EnsureVisibleForegroundWindow, Windows has prevented it, e.g. in order to not disturb the user when he's working in a different window; the KeePass window then just blinks in the taskbar.
Best regards,
Dominik
Some weeks ago I also tried the function EnsureVisibleForegroundWinodw and I got an error. Now I understand "why" and "how" I can call it correctly: With host.MainWindow.Invoke()!
Thank you.
Now it works great :-)
By the way, it's for unlocking the database when requesting credentials with KeePassHttp
Is it possible to determine whether the OpenDatabase-Dialog is already visible or was already triggered?
Situation 1: KeePass is restored and automatically triggers an unlock --> if this fails, I trigger it again
Situation 2: KeePass already shows the unlock dialog --> I trigger it again and a second (!) dialog will be shown
My code is the following:
Last edit: lspcity 2013-03-29
Any suggestions?
Dominik may be able to help.
cheers, Paul
Sorry for the late reply; for some reason I didn't get a notification e-mail for your post.
You can test whether the master key dialog is displayed by
One disadvantage of this approach is that when the user e.g. opens the key file browser dialog (from the master key dialog) on the secure desktop, the above code will evaluate to false, because the master key dialog is only the second-topmost window.
Thus I would instead recommend to test whether no sub-dialog is opened at all.
Best regards,
Dominik
Thank you!
The last one works very well for me.
Best regards
Lukas