I like KeePass, it’s a good solution to the password problem. It’s free and you retain control over your database. The KeePass auto type feature works perfectly for sites that have a single page login process but it does sometimes have problems with financial sites that have multi-page logins. These can require information on later pages that isn’t known beforehand. With those sites, I don’t set up autotype past the first page, it’s too much trouble and for some sites, impossible. Not the fault of KeePass though.
This leaves the problem when a site asks for random characters from your twenty plus digit password or memorable information for which I also use multi-digit generated passwords. Counting digits is not easy.
To that end, I’ve written a small plug in that displays a simple dialog which allows read only access to individual characters from the user name and password fields plus your user defined fields. The dialog is shown below:
The dialog is opened by selecting the Field Chooser... menu item on an entries context menu or the Entry drop down menu.
As this was the first KeePass plug in that I’ve created, I've written up some points that I learnt from a Windows perspective. It may be old news to some but this, along with the existing documentation would have saved me some time and quite a lot of head scratching.
The KeePass web site has brief introduction to writing a plug in here.
Most of the documentation consists of the source code for KeePass sample plug ins and the KeePass application source code located at the bottom of the downloads page. A good place to start would be to download one of the samples, build it, install it and see how it works. Or maybe this one of course.
There are also a lot of other third party plug ins, some with GIT repositories you can examine.
Creating a New Visual Studio Project
Creating a library project following the naming convention for name spaces, classes and DLL is logical. Less obvious is that the assembly product name in AssemblyInfo.cs must be:
KeePass uses it as a quick sanity check before loading a DLL. It is mentioned in the documentation but I managed to miss it. I’ve chosen to set the target framework to .NET Framework 4. See below for the reason.
The Visual Studio solution for this plug in builds a DLL and then, via a post build event calls a batch file build_plgx.bat which creates the PLGX file.
A PLGX file consists of header information followed by a gzip archive of the source files and project, but also anything else that’s lying around in the source directory tree. Rather than delete stuff that isn’t required, the batch file creates a new directory, copies the minimum required files into it, builds the PLGX file then deletes the new directory. I've updated the .gitignore file to take this into account.
DLL vs PLGX
When Visual Studio builds the plug in DLL, it uses the latest Roslyn csc compiler. This can compile the latest C# language features assuming that your MS build tools are up to date. Even for projects that target .NET Framework 2.0, if you use C# 7 language features, the DLL will build, be loaded by KeePass and work as long as the required NET framework is installed.
This isn’t the case with PLGX files. When KeePass first loads a PLGX file, it decompresses the source files into a temporary directory. It then compiles them using the legacy
System.CodeDom.Compiler framework feature. That uses an old version of csc that used to be shipped with the .NET framework. The last version shipped was with .NET framework 4.0 and it can only compile C# language features up to C# 5.
If your DLL works but the PLGX fails to load, it may be that you are using an unsupported language feature. The C# language feature history can be found here.
Strictly speaking, if you want your PLGX plug in to work with all KeePass installs, you should only use C# 2 language features because that may be all that the installed csc compiler understands.
I don’t have a virtual machine with just .NET 2.0 on it lying around so I’ve chosen to only support installs where .NET 4.0 is available. It's possible to set the minimum .NET version to be used when KeePass first loads the PLGX file and compiles it using a command line argument to the PLGX build:
Similarly, it's possible to specify the minimum version of KeePass that can be used as well. KeePass is backwardly compatible but new features will probably give compilation errors if the version of KeePass used to compile the PLGX is earlier than the first version with the new feature in. For this plug in, I've used the
Plugin.GetMenuItem() feature which was added to KeePass in version 2.41. If you try to compile the PLGX file with KeePass 2.40, the compilation will fail and the plug in won't be loaded. To specify the minimum version, add another command line argument:
An archive of KeePass version release notes can be found here.
I'm going to release a PLGX version of this plug in. I'd prefer to let KeePass know beforehand that the plug in cannot be loaded rather than hoping KeePass copes with failure gracefully. KeePass may also be able to show an informative error message to the user at plug in load time.
If you haven't debugged plug ins before, the easiest way in Visual Studio is to specify a debug Start Action which starts KeePass as an external program.
It's probably more convenient to use the KeePass.exe which is copied to the \bin\Debug directory during the build. KeePass will still load your DLL because it checks both its own directory for plug ins as well as the standard plugins directory. Setting up the Start Action is simple:
- Build the debug target first to copy KeePass.exe to the \bin\Debug directory
- Select [project name] Properties... from the Project menu
- Select the Debug tab and click the Start External Program radio button
- Click the Browse button and select KeePass.exe in the \bin\Debug directory
- Add break points in the code...
Now when you hit the Start button on the Visual Studio tool bar, the project will be rebuilt and KeePass will start with the debugger attached to it automatically. If a break point is hit, the debugger will open just as if the plug in was a standalone program. This method allows break points in your
Plugin.Initialize() function to work because the debugger is attached before any plug ins are loaded.
The alternative would be to use the Attach to Process debugging feature where you have to manually attach the debugger to the running KeePass process, but by that time, your plug in will already have been initialized.
It doesn’t take long to get up to speed on writing plug ins. There is a learning curve but there are enough examples and documentation to make it straight forward. Good luck.
At the time of writing, the current version of KeePass is 2.42.1.
Maybe, you'll find my plug in useful as well.
- 28th May, 2019: Initial version