KeePass
密码管理器




Package

如何为KeePass 2.x开发插件


  要求

在开始开发KeePass插件之前,您需要满足以下先决条件:

  • 最新的便携式KeePass ZIP包。您可以从 KeePass网站获取
  • AC#(≥2.0)开发IDE(例如Microsoft Visual Studio或 SharpDevelop)。

信息  循序渐进的教程

启动您喜欢的IDE并创建一个新的C#类库项目(对于.NET Framework,而不是.NET Standard / Core)。在本教程中,我们正在开发的示例插件被调用SimplePlugin。您现在需要做的第一件事是添加对KeePass 的引用:转到引用对话框并选择KeePass.exe文件(来自便携式ZIP包)。当你添加引用,命名空间KeePass和 KeePassLib应该可用。

重要的是您引用官方KeePass.exe,而不是开发快照或自己的构建,因为否则您的插件将与官方KeePass构建不兼容。

所有KeePass插件都需要从基础KeePass插件类派生(PluginKeePass.Plugins命名空间中)。通过重写此类的方法和属性,您可以自定义插件的行为。

最小插件看起来像这样:

使用系统;
使用 System.Collections.Generic;

使用 KeePass.Plugins;

命名空间 SimplePlugin
{
	public sealed class  SimplePluginExtPlugin
	{
		private  IPluginHost m_host = null ;

		public override bool Initialize(IPluginHost host)
		{
			if(host == null返回false ;
			m_host = host;
			返回true ;
		}
	}
}

您可以在KeePass插件网页上找到这个简单插件的完整文档和扩展版本。

这个插件什么都不做,但它已经显示了一些重要的约定,所有插件都必须遵循:

  • 命名空间必须像没有扩展名的DLL文件一样命名。我们的DLL文件已命名SimplePlugin.dll,因此必须调用命名空间SimplePlugin
  • 主插件类(KeePass在加载插件时将实例化)必须与命名空间加“Ext”完全相同。在这种情况下:“SimplePlugin”+“Ext”=“SimplePluginExt”。
  • 主插件类必须从KeePass.Plugins.Plugin 基类派生。

Initialize函数是最重要的函数,您可能总是会覆盖它。在此函数中,您将获得KeePass内部的IPluginHost接口:接口参考。通过此界面,您可以访问KeePass主菜单,当前打开的数据库等。Initialize在KeePass加载插件后立即调用该函数。所有初始化都应该在这个方法中完成(不是在你的插件类的构造函数中!)。如果您成功初始化了所有内容,则必须返回true。如果您返回false,KeePass将立即卸载您的插件。

您经常需要的第二个功能是Terminate 方法:

public override void Terminate()
{
}

在KeePass卸载插件之前不久调用此函数。你无法中止这个过程(这只是一个通知,也是你清理所有已用资源的最后机会等)。从此方法返回后,KeePass可以立即卸载您的插件。强烈建议释放此方法中的所有资源(不在插件类的析构函数中!)。

我们差不多完成了!我们现在需要告诉KeePass我们的文件是一个KeePass插件。这是通过编辑 文件的版本信息块来完成的。打开文件版本编辑对话框(在Visual Studio 2005中:右键单击项目名称→ “属性” →按钮“装配信息”)。除产品名称字段外,可以自由分配所有字段(有关更多信息,请参阅插件约定)。此字段必须设置为“ KeePass Plugin”(不带引号)。

而已!现在尝试编译您的插件并将生成的DLL文件复制到KeePass目录中。如果你启动KeePass并转到插件对话框,你应该在加载的插件列表中看到你的插件。

信息  提供菜单项

许多插件在诸如“工具”菜单,条目上下文菜单等显着位置提供菜单项(子项目,如有必要)。这样的菜单项可以通过覆盖GetMenuItem插件类的方法(源自的方法)提供给KeePass 。所述Plugin基类)。在这种方法中,插件可以构造并返回一个ToolStripMenuItem,然后KeePass将在适当的位置显示。

用户应该能够将菜单项与您的插件相关联。通常,插件将菜单项的文本设置为插件的名称或以插件名称开头的字符串。例如,想要仅提供一个菜单项(用于访问插件选项)的插件“Abcd”可以将菜单项的文本设置为“Abcd选项”。如果插件支持多个命令,请将菜单项的文本设置为插件名称(例如“Abcd”),并为每个命令添加子项。

GetMenuItem方法应始终构造并返回一个新的ToolStripMenuItem。不要为了以后的目的缓存菜单项或其任何子项(KeePass可以GetMenuItem多次调用该方法并在多个位置显示菜单项;如果您的插件将缓存菜单项,尝试在多个位置显示它将导致问题,因为一个ToolStripMenuItem只能有一个父项)。如果要更新子项的状态(如禁用某些项或显示复选标记),可以在匿名方法中执行此操作,该方法处理DropDownOpening 返回的菜单项的事件(这样您就不需要记住菜单项引用手动地)。

KeePass获取返回的菜单项(及其子项)的所有权。插件不应在任何菜单本身中添加或删除该项目; KeePass会这样做。

如果您的插件未在PluginMenuType参数指定的位置提供菜单项t,请返回null

例:

public override  ToolStripMenuItem GetMenuItem(PluginMenuType t)
{
	// 
	如果(t == PluginMenuType .Main)提供主要位置的菜单项
	{
		ToolStripMenuItem tsmi = new  ToolStripMenuItem();
		tsmi.Text = “Abcd选项” ;
		tsmi.Click + = this .OnOptionsClicked;
		返回 tsmi;
	}

	return null ; //其他位置没有菜单项
}

private void OnOptionsClicked(对象发送者,EventArgs e)
{
	//单击菜单项时调用 
}

信息  插件约定

文件版本信息块:

KeePass使用文件版本信息块来检测DLL文件是否是KeePass插件,并从中检索信息以显示在插件对话框中。字段使用如下:

  • 标题:应包含插件的全名。
  • 描述:应包含插件的简短描述(不超过5行)。
  • 公司:应包含插件的作者姓名。
  • 产品名称:必须设置为"KeePass Plugin"(不带引号)。
  • 版权: KeePass不使用; 可以通过插件自由分配。
  • 商标: KeePass不使用; 可以通过插件自由分配。
  • 程序集版本:应设置为插件的版本。
  • 文件版本:应设置为插件的版本。您可以自行决定如何对插件构建进行版本控制,但它应该是允许版本比较的方案(通过比较版本组件)。千万不能使用星号在构建时创建一个版本号。
  • GUID: KeePass不使用; 可以通过插件自由分配。

名称,名称空间和类名称:

如果要使用名称“KeePass”作为插件名称的一部分,请直接添加/附加非数字前缀/后缀。例如,“KeePassSync”没问题,但“KeePass Sync”没有。

命名空间必须像没有扩展名的DLL文件一样命名。例如,如果DLL文件已命名SecretImporter.dll,则必须调用该命名空间SecretImporter

插件类必须命名为命名空间加“Ext”。对于SecretImporter插件,这将是SecretImporterExt

交换  更新检查

KeePass的更新检查≥2.​​18也可以检查插件更新。更新检查支持是可选的; 插件不必支持更新检查。

为了支持更新检查,插件开发人员需要执行以下操作:

  • 提供版本信息文件。 当最终用户调用更新检查时,KeePass会下载版本信息文件,该文件指定一个或多个插件的当前版本号。每个插件作者都拥有一个自己的版本信息文件。下面详细描述版本信息文件的格式。
  • 让KeePass知道。 为了能够检查插件的版本,KeePass必须知道您的版本信息文件所在的位置。要让KeePass知道,请覆盖UpdateUrl插件类(派生自派生类)的字符串属性,Plugin以返回版本信息文件的完整绝对URL。这应该是一个https://URL(为了向后兼容,KeePass也支持http:// 和ftp://,但出于安全原因https:// 应该使用)。

插件开发人员每次发布新版本的插件时都必须更新其版本信息文件。

版本信息文件格式。

  • 该文件是一个简单的文本文件。必须使用UTF-8编码而不使用字节顺序标记(KeePass≥2.21支持版本信息文件中的UTF-8 BOM,但为了与KeePass <2.21兼容,建议不要使用BOM)。支持所有行结尾。
  • 文件的第一行必须以您选择的分隔符开头。分隔符可以是任何字符,但不得出现在插件名称和版本中。建议是’ :‘。
  • 以下每行指定一个插件名称及其当前可用的版本,由标题行中指定的分隔符分隔。
  • 作为插件名称,必须指定插件版本信息块中“标题”字段的值。对于托管插件,这是使用AssemblyTitleassembly属性指定的值 。
  • 作为版本号,必须指定插件的版本信息块中的文件版本的值。对于托管插件,这是使用AssemblyFileVersionassembly属性指定的值 。.0可以删除尾随(例如,指定1.3而不是1.3.0.0)。
  • 该文件必须以仅包含分隔符的行结束。
  • 您可以选择使用GZip压缩您的版本信息文件(注意这与Zip不同)。然后文件名必须以“ .gz” 结尾。

例。假设您正在开发两个插件:MyPlugin1 (版本1.5)和MyPlugin2(版本1.13.2.17)。然后您的版本信息文件可能如下所示:


MyPlugin1:1.5
MyPlugin2:1.13.2.17

如果您开发了多个插件,建议创建一个版本信息文件,列出此文件中的所有插件,并在所有插件中指定文件的URL。当KeePass检查更新时,它只会下载您的版本信息文件一次。这减少了网络流量,并且比分别下载每个插件的版本信息文件更快。

签名。自KeePass 2.34起,您可以选择使用RSA / SHA-512对版本信息文件进行数字签名。

  • 例如,可以生成RSA密钥对,如下所示:
    使用RSACryptoServiceProvider rsa = new  RSACryptoServiceProvider(4096))
    {
    	rsa.PersistKeyInCsp = false ;
    	Console .WriteLine(“私钥:” + rsa.ToXmlString(true));
    	Console .WriteLine(“公钥:” + rsa.ToXmlString(false));
    }

    RSACryptoServiceProvider KeePass 支持所有支持的密钥长度(最高为.NET 4.5,8位步长为384到16384位)。我们建议至少2048位; 主版本信息文件(包含KeePass版本)使用4096位。

  • 为了告诉KeePass仅在可以使用特定公钥验证时接受特定版本信息文件,您的插件必须调用该 UpdateCheckEx.SetFileSigKey 方法以将指定的URL与指定的公钥相关联。公钥必须是RSACryptoServiceProvider.ToXmlString方法返回的格式的XML字符串 。不要将私钥存储在插件中,只能存储公钥。
  • 要对无符号版本信息文件进行签名,请使用SHA-512,UTF-8编码在页眉和页脚行之间散列所有修剪过的非空行,每行以'\n' (不"\r\n")终止。使用私钥对哈希进行签名(如果您正在使用RSACryptoServiceProvider:使用其FromXmlString方法加载私钥,然后使用该方法计算签名SignData)。使用Base64对哈希进行编码,并将其附加到版本信息文件的第一行。

信息  KeePass 2.x插件可以用非托管C ++编写吗?

是的,不是。您可以在非托管C ++中编写插件的逻辑(可以使用本机Win32 API)。但是,您必须为插件提供托管接口,即您必须导出从Plugin基类派生的托管类,如本教程中所述。此外,需要托管C ++来修改KeePass内部(条目,组,主窗口……)。

由于兼容性原因,强烈建议用C#而不是C ++开发插件(在本机插件的情况下,需要单独的32位和64位版本;本机插件不能在类Unix系统上运行;等等。 )。

信息  PLGX文件

PLGX是KeePass≥2.09的可选插件文件格式。插件源代码文件可以打包到PLGX文件中,而不是将插件编译成DLL文件,KeePass会在加载时自行编译插件。

PLGX方法的一个优点是强大的兼容性检测。对于DLL插件,当插件尝试调用/访问方法/类时,运行时检测到不兼容性(由KeePass中的API更改引起),而不是在加载时。因此,检测到不兼容性可能会导致KeePass崩溃。相反,当使用PLGX格式时,在加载时立即检测到不兼容性:如果出现问题,编译过程将失败,并且KeePass可以向用户显示信息性插件不兼容消息。对于DLL插件,KeePass执行自己的兼容性检查,但不检测所有不兼容性; PLGX在这里远胜一筹。

PLGX方法的另一个优点是与自定义KeePass构建的兼容性。DLL插件引用了官方的KeePass构建,除非KeePass中的更改破坏了插件,该插件还兼容所有使用相同程序集签名密钥(强名称)编译的未来KeePass构建。这适用于所有操作系统。特别是,一个不使用任何Windows特定功能的DLL插件在Linux上使用官方便携式ZIP包中的KeePass构建工作正常。但是,一些Linux软件包从源代码编译KeePass; 此类构建根本不签名或使用不同的程序集签名密钥签名,因此与DLL插件不兼容。相比之下,PLGX插件与自定义KeePass构建兼容,

对于用户来说,安装DLL插件的过程与PLGX插件完全相同; 两者都需要复制到’Plugins’文件夹中。

比较。

DLL PLGX
兼容性检查 没有 只有弱点。 是 强大。
与自定义版本的兼容性(Linux) 没有 部分,见上文。 是
Authenticode签名支持 是 没有
没有对用户系统进行编译 是 没有
没有插件缓存 是 没有

因此,两种格式都有其独特的优点和缺点; 没有“最佳”格式。

双包装。 您可以在一个软件包中将插件作为DLL和PLGX发送(例如,在一个文件夹中为“SecretImporter.dll”和“SecretImporter.plgx”)。KeePass将加载最合适的文件(如果KeePass已经使用官方程序集签名密钥签名,它将加载DLL,否则加载PLGX)。如果KeePass加载DLL,则忽略PLGX,这尤其意味着仅执行弱兼容性检查(即,PLGX确保的强兼容性检测丢失)。因此,双包继承了DLL的缺点,也不是“最佳”解决方案。

建议。 在任何情况下,创建一个PLGX文件(以确保与所有KeePass构建兼容)。如果您认为DLL的优点超过了未检测到的兼容性问题的风险,则另外以DLL形式提供插件。

创建PLGX文件。 通过KeePass.exe 使用--plgx-create命令行选项调用,可以从插件源创建PLGX文件。如果你另外传递一个路径到插件源目录(没有终止分隔符),KeePass将使用这个; 否则它将显示一个文件夹浏览器对话框,允许您选择目录。如果要使用命令行传递目录位置,请确保指定完整的绝对路径 – 相对路径不起作用。

为了保持PLGX文件的大小,建议您在编译PLGX之前清理插件源目录。删除所有不必要的二进制文件(bin 和obj目录中的文件); 特别是,删除您自己编译的任何插件程序集DLL。IDE的临时文件(如.suo.user文件)也可以删除。

PLGX功能。

  • 可扩展的,面向对象的文件格式。
  • 压缩支持(使用GZip压缩数据文件)。
  • .csproj支持。KeePass从.csproj插件源文件中检索编译插件程序集所需的所有信息。
  • 嵌入式资源支持。
  • 引用的.NET程序集支持。从.csproj文件中读取参考信息。
  • 引用的自定义程序集支持。如果第三方程序集位于插件源代码目录(或其任何子目录)中,则支持插件所需的第三方程序集(对DLL的引用)。
  • ResX支持。.resx文件自动编译为二进制.resources文件。
  • PLGX缓存。PLGX文件编译一次,生成的程序集存储在缓存中。对于以后的所有KeePass启动,不需要编译。
  • PLGX缓存维护。可以在KeePass插件对话框中看到PLGX缓存的大小。此处,缓存也可以标记为清除(下次启动KeePass时将清除缓存)。默认情况下,支持并启用从缓存中自动删除旧文件的选项。

PLGX限制。

  • 目前只支持C#(不支持Visual Basic或任何其他.NET语言)。
  • 不支持链接的资源(在不同的程序集中)。
  • 不支持对其他项目的依赖关系(重新组织项目以使用自定义程序集引用)。

定义先决条件。可以任选地指定最小KeePass的版本,最小安装了.NET Framework,操作系统和使用该指针的最小尺寸(86对64) , , --plgx-prereq-kp: 和 命令行选项。如果未满足其中一个插件先决条件,KeePass会向最终用户显示详细的错误消息(而不是通用插件不兼容消息)。构建示例:--plgx-prereq-net:--plgx-prereq-os:--plgx-prereq-ptr:
KeePass.exe --plgx-create C:\YourPluginDir --plgx-prereq-kp:2.09 --plgx-prereq-net:3.5

有效的操作系统值是WindowsUnix。在未知的操作系统上运行时,KeePass默认为Windows。指针大小(检查x86与x64)以字节为单位指定; 例如,要仅允许在x64上运行,请指定--plgx-prereq-ptr:8

构建命令。 (可选)您可以使用--plgx-build-pre:和 指定预构建和后构建命令--plgx-build-post:。这些命令嵌入在PLGX文件中,并在最终用户系统上编译插件时执行。

在构建命令中,占位符{PLGX_TEMP_DIR} 指定将文件提取到的临时目录(包括终止分隔符)。在post-build命令中,{PLGX_CACHE_DIR} 由插件的缓存目录(包括终止分隔符)替换,生成的程序集存储在该目录中。

例如,这些构建命令可用于将其他文件复制到缓存目录中。例:
KeePass.exe --plgx-create C:\YourPluginDir --plgx-build-post:"cmd /c COPY """{PLGX_TEMP_DIR}MyFile.txt""" """{PLGX_CACHE_DIR}MyFile.txt""""

为了在命令行上指定引号字符,必须使用三个引号进行编码SHELLEXECUTEINFO。因此,上面的命令行实际上会将构建后的命令嵌入 cmd /c COPY "{PLGX_TEMP_DIR}MyFile.txt" "{PLGX_CACHE_DIR}MyFile.txt" 到PLGX中,这是正确的。强烈建议使用引号包围PLGX占位符的路径,否则如果路径包含空格字符(经常发生),命令将无法正确运行。

如果需要运行多个命令,请将它们写入批处理文件并执行(带cmd)。如果您需要执行更复杂的构建任务,请编写自己的构建可执行文件并使用构建命令运行它(通常将目录位置作为参数传递给构建可执行文件很有用),例如:
KeePass.exe --plgx-create C:\YourPluginDir --plgx-build-post:"{PLGX_TEMP_DIR}MyBuild.exe {PLGX_TEMP_DIR} {PLGX_CACHE_DIR}"

PLGX调试。 当--debug传递命令行选项并且PLGX插件无法编译时,所有尝试过的编译器的输出都将保存到临时文件中。

上一页:
下一页:


沪ICP备19023926号-2 Copyright © 2003-2019 Dominik Reichl, [联系我们 / 版本说明] [团队 & 隐私政策]