如何将 COM dll 捆绑到便携式应用程序中?
How to bundle COM dlls into a portable app?
我需要编写一个程序,使用一些 COM 对象,从 python comtypes 包访问。我使用 clsid and/or progid 来创建和使用它们。这些对象由第三方提供,通常使用普通安装程序(setup.exe 或 MSI 文件)安装。
让我们假设这些 DLL 文件拥有允许我将它们与我的程序一起发布的许可证。是否可以将这些 DLL 文件加载到内存中,并从便携式应用程序中使用它们而无需实际注册?或者,我可以从我的程序中注册它们吗?
一个相关的问题是:如何确定创建给定 COM 对象所需的 DLL 文件链? (除了反复试验。)
背景:实际上,有多个库,主要问题是我不希望用户在启动实际程序之前 运行 4 个不同的安装程序。这对普通用户来说太难了。
你在这里问了很多问题。有很多方法可以完成您想要完成的事情,而且很难回答如此广泛的问题。如果您对如何做某件事有具体问题,请针对这些问题开始新帖子。
话虽如此,我会尽力为您提供一些信息,以帮助您弄清楚 need/want 应该做什么。
是否可以在不注册的情况下使用 COM DLL?
是的。有多种方法,具体取决于 COM DLL 的需要和您使用的平台。但是,有些选项并不总是有效,而其他选项则非常具有挑战性。
DllGetClassObject
- In some cases, depending on the COM object you're trying to load, you can just load the DLL, call the DllGetClassObject
function directly, and use the returned IClassFactory
to create your object. This is the easiest way -- if it works. If the class you create requires that the DLL be registered (maybe it does a CoCreateInstance
内部,或者它可能需要代理支持),这对你不起作用。要确定这是否可行,要么反复试验,要么您必须询问 COM DLL 的开发人员。
- Registration-free COM - 这就是 .NET 中的做法。我不确定你是否可以在 Python.
中轻松地做这样的事情
- CoRegisterClassObject - 如果您要创建自己的免注册 COM 实现,此功能将至关重要。我相信这是 Microsoft 免注册 COM 的基本实现细节。但是,请注意,这将是一件 非常 具有挑战性的事情,并且需要对 COM 非常 有很好的理解。
你能从你的程序中注册一个 COM DLL 吗?
是的。有几种方法。但是,您可能会 运行 此处遇到安全问题——通常,COM 组件会在 HKEY_LOCAL_MACHINE
中自行注册,并且您通常需要管理员权限才能在此处写入。一些 COM components/installers 被设计为在 HKEY_CURRENT_USER
中注册自己,这将绕过安全问题。但是,您可能无法控制组件在何处注册自身,即使您这样做了,在 HKEY_CURRENT_USER
中注册也不是一个完美的解决方案。
regsvr32.exe
- 一种选择是以编程方式调用 DLL 上的 regsvr32.exe
。
DllRegisterServer
or DllInstall
- If a COM DLL can be registered with regsvr32.exe
, then it has at least one of these functions exported. You can load the DLL manually and call these functions just like regsvr32.exe
does. DllInstall
is less common than DllRegisterServer
. If DllInstall
is present, it may give you the option of installing in HKEY_CURRENT_USER
. If not, you have to just do whatever DllRegisterServer
可以,因为您无法为该功能提供任何选项。
- 自己编写注册表值 -- 如果您能找出所有需要的注册表设置,就没有什么可以阻止您手动将它们放入注册表。这将解决
HKEY_LOCAL_MACHINE
/HKEY_CURRENT_USER
问题——您可以将它们写在任何您喜欢的地方(但 HKEY_LOCAL_MACHINE
仍然可能需要管理员权限)。
regedit.exe
- 另一种自己编写注册表值的方法是将它们存储在 .reg
文件中并调用 regedit.exe
合并它们。
如何确定 DLL 的依赖关系?
理想情况下,该 DLL 的开发人员知道并且可以告诉您。只有这样才能真正做到万无一失。
- 对于 COM 依赖项,除了询问开发人员或反复试验之外,可能无法通过任何其他方式解决这个问题。这是因为 COM 依赖项的存在可能仅仅是因为 DLL 中的一些代码只是调用
CoCreateInstance
来创建一些第三方 COM 对象,并且由于这只是在源代码中表达的东西,所以没有元数据将帮助您找到这些依赖项的 DLL。
- 以上内容也适用于任何动态加载的依赖项。例如,如果某些代码只是直接调用
LoadLibrary
,则您无法从外部确定依赖关系。
- 对于静态加载的依赖项,您可以使用 Dependency Walker 等工具。请注意,您将看到的许多依赖项都是系统依赖项——例如,您不想包括 user32.dll 和 kernel32.dll,因为它们是随 Windows.[= 一起安装的77=]
如何安装第三方依赖?
如果您确切知道要写入哪些文件、将它们写入何处以及需要应用哪些注册表设置(等),您可以自己完成所有这些工作。对于某些依赖项,将第三方安装程序包含在安装程序中并静默执行会更容易。正是出于这个原因,许多安装程序支持静默模式。一个很好的例子是 Visual C++ 运行time (msvcrt*.dll)——许多应用程序需要这种依赖性,许多安装程序只是将 Microsoft 的安装程序作为其分发的一部分,而主安装程序只是调用辅助安装程序静默。
我需要编写一个程序,使用一些 COM 对象,从 python comtypes 包访问。我使用 clsid and/or progid 来创建和使用它们。这些对象由第三方提供,通常使用普通安装程序(setup.exe 或 MSI 文件)安装。
让我们假设这些 DLL 文件拥有允许我将它们与我的程序一起发布的许可证。是否可以将这些 DLL 文件加载到内存中,并从便携式应用程序中使用它们而无需实际注册?或者,我可以从我的程序中注册它们吗?
一个相关的问题是:如何确定创建给定 COM 对象所需的 DLL 文件链? (除了反复试验。)
背景:实际上,有多个库,主要问题是我不希望用户在启动实际程序之前 运行 4 个不同的安装程序。这对普通用户来说太难了。
你在这里问了很多问题。有很多方法可以完成您想要完成的事情,而且很难回答如此广泛的问题。如果您对如何做某件事有具体问题,请针对这些问题开始新帖子。
话虽如此,我会尽力为您提供一些信息,以帮助您弄清楚 need/want 应该做什么。
是否可以在不注册的情况下使用 COM DLL?
是的。有多种方法,具体取决于 COM DLL 的需要和您使用的平台。但是,有些选项并不总是有效,而其他选项则非常具有挑战性。
DllGetClassObject
- In some cases, depending on the COM object you're trying to load, you can just load the DLL, call theDllGetClassObject
function directly, and use the returnedIClassFactory
to create your object. This is the easiest way -- if it works. If the class you create requires that the DLL be registered (maybe it does aCoCreateInstance
内部,或者它可能需要代理支持),这对你不起作用。要确定这是否可行,要么反复试验,要么您必须询问 COM DLL 的开发人员。- Registration-free COM - 这就是 .NET 中的做法。我不确定你是否可以在 Python. 中轻松地做这样的事情
- CoRegisterClassObject - 如果您要创建自己的免注册 COM 实现,此功能将至关重要。我相信这是 Microsoft 免注册 COM 的基本实现细节。但是,请注意,这将是一件 非常 具有挑战性的事情,并且需要对 COM 非常 有很好的理解。
你能从你的程序中注册一个 COM DLL 吗?
是的。有几种方法。但是,您可能会 运行 此处遇到安全问题——通常,COM 组件会在 HKEY_LOCAL_MACHINE
中自行注册,并且您通常需要管理员权限才能在此处写入。一些 COM components/installers 被设计为在 HKEY_CURRENT_USER
中注册自己,这将绕过安全问题。但是,您可能无法控制组件在何处注册自身,即使您这样做了,在 HKEY_CURRENT_USER
中注册也不是一个完美的解决方案。
regsvr32.exe
- 一种选择是以编程方式调用 DLL 上的regsvr32.exe
。DllRegisterServer
orDllInstall
- If a COM DLL can be registered withregsvr32.exe
, then it has at least one of these functions exported. You can load the DLL manually and call these functions just likeregsvr32.exe
does.DllInstall
is less common thanDllRegisterServer
. IfDllInstall
is present, it may give you the option of installing inHKEY_CURRENT_USER
. If not, you have to just do whateverDllRegisterServer
可以,因为您无法为该功能提供任何选项。- 自己编写注册表值 -- 如果您能找出所有需要的注册表设置,就没有什么可以阻止您手动将它们放入注册表。这将解决
HKEY_LOCAL_MACHINE
/HKEY_CURRENT_USER
问题——您可以将它们写在任何您喜欢的地方(但HKEY_LOCAL_MACHINE
仍然可能需要管理员权限)。 regedit.exe
- 另一种自己编写注册表值的方法是将它们存储在.reg
文件中并调用regedit.exe
合并它们。
如何确定 DLL 的依赖关系?
理想情况下,该 DLL 的开发人员知道并且可以告诉您。只有这样才能真正做到万无一失。
- 对于 COM 依赖项,除了询问开发人员或反复试验之外,可能无法通过任何其他方式解决这个问题。这是因为 COM 依赖项的存在可能仅仅是因为 DLL 中的一些代码只是调用
CoCreateInstance
来创建一些第三方 COM 对象,并且由于这只是在源代码中表达的东西,所以没有元数据将帮助您找到这些依赖项的 DLL。 - 以上内容也适用于任何动态加载的依赖项。例如,如果某些代码只是直接调用
LoadLibrary
,则您无法从外部确定依赖关系。 - 对于静态加载的依赖项,您可以使用 Dependency Walker 等工具。请注意,您将看到的许多依赖项都是系统依赖项——例如,您不想包括 user32.dll 和 kernel32.dll,因为它们是随 Windows.[= 一起安装的77=]
如何安装第三方依赖?
如果您确切知道要写入哪些文件、将它们写入何处以及需要应用哪些注册表设置(等),您可以自己完成所有这些工作。对于某些依赖项,将第三方安装程序包含在安装程序中并静默执行会更容易。正是出于这个原因,许多安装程序支持静默模式。一个很好的例子是 Visual C++ 运行time (msvcrt*.dll)——许多应用程序需要这种依赖性,许多安装程序只是将 Microsoft 的安装程序作为其分发的一部分,而主安装程序只是调用辅助安装程序静默。