Registering a CPP dll into COM after installation using Wix Msi installer(使用 Wix Msi 安装程序安装后将 CPP dll 注册到 COM)
问题描述
我正在尝试在 Msi 安装期间将 CPP 库注册到 COM.
我搜索了很多,在这里找到了很多解决方案,但我的代码没有任何效果.不知道有没有直接的方法.我曾尝试将自定义操作与直接 ExeCommand 和批处理脚本一起使用.
这是带有批处理脚本的代码.
<SetProperty Id="Register" Value=""[INSTALLDIR]ScriptsRegister.bat""之后=CostFinalize"/><CustomAction Id="Register" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" Impersonate="no"/><SetProperty Id="Unregister" Value=""[INSTALLDIR]ScriptsUnRegister.bat""之后=CostFinalize"/><CustomAction Id="Unregister" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" Impersonate="no"/>
使用此代码,安装不会显示任何错误,但 dll 未注册.安装后,如果我单独运行批处理脚本,则它会被注册.
注册.bat
cd "C:WindowsSystem32"
regsvr32 "C:Program Files (x86)ABCAbc.dll"
ping -n 15 127.0.0.1 >nul:
取消注册.bat
cd "C:WindowsSystem32"
regsvr32/u "C:Program Files (x86)ABCAbc.dll"
ping -n 15 127.0.0.1 >nul:
使用带有 ExeCommand 的自定义操作,它会显示错误,例如缺少某些 dll 依赖项.执行命令代码如下.
<CustomAction Id="Register" Directory="INSTALLDIR" Execute="deferred" Impersonate="no"ExeCommand="[WindowsFolder]System32
egsvr32 "[INSTALLDIR]Abc.dll""返回=检查"/><CustomAction Id="Unregister" Directory="INSTALLDIR" Execute="deferred" Impersonate="no"ExeCommand="[WindowsFolder]System32
egsvr32/u "[INSTALLDIR]Abc.dll""返回=检查"/>
下面给出了这两种情况的安装顺序.
<Custom Action="Register" Before="InstallFinalize" >未安装</Custom><Custom Action="Unregister" Before="RemoveFiles">已安装且未升级PRODUCTCODE</Custom></InstallExecuteSequence>
在这两种情况下,我都认为它以提升的权限运行.
这是我大部分时间遇到的错误.
编辑
dll 的依赖 walker 视图如下所示.
我还添加了我使用的 heat 命令.我已将此添加到预构建事件以生成组件.之后在产品文件中添加了这个组件.
调用 "$(WIX)binheat.exe" 文件 "dllPathAbc.dll" -dr "INSTALLDIR" -srd -gg -sfrag -suid -out "$(SolutionDir)InstallerComRegisterComponent.wxs"
生成的文件是这样的.
<片段><DirectoryRef Id="INSTALLDIR"><Component Id="Abc.dll" Guid="*"><File Id="Abc.dll" KeyPath="yes" Source="SourceDirAbc.dll"/></组件></DirectoryRef></片段>
这里的 SourceDir 路径让我很困惑.我已经在 heat 命令中添加了确切的路径,即使它生成了这个 SourceDir.
简短的总结回答
您需要停止使用批处理文件和自定义操作进行 COM 注册(不可靠),而是使用 WiX 工具包中的 heat.exe 工具提取 COM 注册信息在编译时将 COM 注册添加到您的 MSI 数据库中.
64 位二进制文件有一些复杂性,请参阅下面的详细信息.幸运的是,根据上面显示的安装目录,您似乎正在处理 32 位组件.
在这种特殊情况下,它有助于在部署后在 COM 文件上运行 heat.exe,当所有依赖项都就位"以便 COM 文件正确加载时.这些答案中有很多调试通信"——我将把它留在未来,但首先尝试这个简单的解决方案.或者试试下面描述的新依赖工具Dependencies.exe".
<小时>长而详细的答案
在我尝试回答这个问题之前(这似乎围绕着缺少依赖项或在你的批处理文件中做了一些奇怪的事情),我想澄清一些为您提供有关 COM 注册最佳实践的信息.
<块引用>注意:屏幕截图似乎表明您的批处理文件中发生了一些奇怪的事情,但缺少依赖项仍然可能是一个问题.
自行注册被认为有害
不应使用自注册来注册 COM 文件.以下是对这种情况的说明:
当您的 dll(或任何文件类型,例如 OCX)从您的设置的安装位置运行时,您很可能会发现类似的错误.regsvr32.exe找不到需要的依赖文件,注册失败.
有一些报告的缺失依赖项并不重要 - 我想这与 Dependency Walker 工具的年龄有关 - 据我所知,它最近没有更新.查找您识别为您自己的依赖文件或核心系统文件的文件,而不是您从未听说过的非常长的 dll 文件名.请记住,某些 dll 具有加载所需的依赖语言 dll.例如 MMUtilities.dll 需要 MmUtilitiesEnglish.dll 或同一文件夹中存在的其他语言 dll 才能正确加载.
上述文件的一些示例误报依赖:API-MS-WIN-CORE-RTLSUPPORT-L1-1-0.DLL
,API-MS-WIN-CORE-PROCESSTHREADS-L1-1-0.DLL
、API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL
等...很多.我相信,但我不确定,这些误报的根本原因集中在安装到 WinSxS 文件夹的并行组件问题上,但这是另一个讨论 - 只是提一下.
更新:我刚刚再次检查了这一点,上面看到的大多数误报依赖显然是API-sets - 在 Dependency Walker 创建很久之后引入的 Windows 功能,因此该工具没有正确处理.
正如链接的答案所示(请阅读上面的链接),现在还有一个用 C# 重写 Dependency Walker,称为Dependencies",可在此处获得:https://github.com/lucasg/Dependencies(我在撰写本文时未经测试,将进行测试很快).
<小时>另外快速提及:如果您有一个可执行文件要检查(而不是 dll、ocx 等...),您可以通过 Profile => 启动它.开始分析...
菜单条目,然后您还将看到隐藏的运行时依赖项"未在二进制导入表中指定(其中指定了依赖项/导入).您需要真正使用所有对话框中的所有功能来练习应用程序,以确保获得所有此类依赖项.
dependency walker 网页调用这些隐藏依赖显式依赖(动态或运行时依赖)和系统钩子依赖(注入依赖).有关详细信息,请参阅上面的链接.
Heat.exe 提取
一旦确定了使 WiX heat.exe 提取工作丢失的文件,您可以将有问题的文件放在 COM dll 的旁边",以便在加载过程中找到它们.您可以使用 regsvr32.exe 测试运行以查看注册是否正确完成.当您像这样手动运行注册时,应该没有错误消息.记得从提升的命令提示符运行注册.
其他几个stackoverflow答案解释了如何使用heat.exe - 我已经很久没有使用它了:如何运行heat.exe并在wix中注册一个dll.这是来自 WiX 人员自己的 heat.exe 的官方文档.它可能是一个有点吓人的工具 - 它有很多功能.
以其最简单的形式(对于路径或本地文件夹中具有所有可用依赖项的普通 32 位 COM 文件),您可以运行此 heat.exe 命令行以生成名为 YourFileName.wxs 的输出 WiX 源文件
包含所有必需的 COM 注册表数据.
heat.exe 文件 YourFileName.ocx -o YourFileName.wxs
几年前我写了一个答案,展示了如何将导出的 WiX 注册表数据合并到您的主要 WiX 源中:如何在 Wix(命令行)中引用热量输出(wxs).我相信这是对程序的准确描述,但出于某种原因,有人对答案投了反对票.请试一试,看看它是否适合您.
<块引用>重要提示!:heat.exe 尚未正确处理 64 位 COM 二进制文件(2017 年 12 月).
我获悉 WiX 扩展包(非免费)可处理 64 位二进制文件并提供若干其他功能.我想我可以链接到它(我不隶属于 FireGiant):https://www.firegiant.com/wix/wep-documentation/harvesting/.不知何故,人们需要了解这些事情,但我不确定链接的 stackoverflow 礼仪.
您的二进制文件是 64 位的吗?(从您的安装文件夹中看起来不是这样,但我为可能找到它的其他人添加了这个).对于 64 位组件,我想我们已经绕了一圈,不得不建议您要么使用上述扩展包功能,要么尝试 按照此处的说明将文件设置为自注册.我讨厌这种自行注册的解决方案",但目前我想不出任何其他快速修复方法(无论如何我都不会推荐).我会再检查一次.在进行此自注册修复"之前,请务必检查最新的 WiX 版本以查看 64 位问题是否已修复.这至少比尝试使用自定义操作和批处理文件注册要好(永远不要尝试 - MSI 的复杂自定义操作顺序、模拟/提升、调节、安装模式与静默和交互式安装模式相关的潜在问题太多了,而不是提到安全软件的潜在干扰,不胜枚举).
<小时>一些链接:
- 你好吗在 WiX 3 中注册一个 Win32 COM DLL 文件?
- 无法使用 WiX 注册 DLL
- 使用wix执行REGSVR32的功能
- Heat.exe 无法收获来自 64 位 COM DLL 的类型库信息
- 热.exe:64 位 .dll 无法转换为 64 位 .msi
I am trying to register a CPP library into COM during the Msi installation.
I have searched a lot and found many solutions in here, but nothing is working in my code. I don't know is there any direct method for this. I have tried using Custom Action with direct ExeCommand and with a batch script.
Here is the code with batch script.
<SetProperty Id="Register" Value=""[INSTALLDIR]ScriptsRegister.bat"" After="CostFinalize"/>
<CustomAction Id="Register" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" Impersonate="no"/>
<SetProperty Id="Unregister" Value=""[INSTALLDIR]ScriptsUnRegister.bat"" After="CostFinalize"/>
<CustomAction Id="Unregister" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" Impersonate="no"/>
Using this code, installation does not show any error, but dll is not getting registered. After installation if I ran the batch script separately then it gets registered.
Register.bat
cd "C:WindowsSystem32"
regsvr32 "C:Program Files (x86)ABCAbc.dll"
ping -n 15 127.0.0.1 >nul:
Unregister.bat
cd "C:WindowsSystem32"
regsvr32 /u "C:Program Files (x86)ABCAbc.dll"
ping -n 15 127.0.0.1 >nul:
With Custom Action with ExeCommand it shows error like some dll dependency missing. ExeCommand code is given below.
<CustomAction Id="Register" Directory="INSTALLDIR" Execute="deferred" Impersonate="no"
ExeCommand="[WindowsFolder]System32
egsvr32 "[INSTALLDIR]Abc.dll"" Return="check" />
<CustomAction Id="Unregister" Directory="INSTALLDIR" Execute="deferred" Impersonate="no"
ExeCommand="[WindowsFolder]System32
egsvr32 /u "[INSTALLDIR]Abc.dll"" Return="check" />
And InstallSequencefor both the cases is given below.
<InstallExecuteSequence>
<Custom Action="Register" Before="InstallFinalize" >NOT Installed</Custom>
<Custom Action="Unregister" Before="RemoveFiles">Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
</InstallExecuteSequence>
In both the case I think it is running with elevated privileges.
This is the error I get most of the time.
Edit
Dependency walker view of the dll is shown below.
Also I am adding the heat command I used. I have added this to prebuild event to generate the component. After that added this component in product file.
call "$(WIX)binheat.exe" file "dllPathAbc.dll" -dr "INSTALLDIR" -srd -gg -sfrag -suid -out "$(SolutionDir)InstallerComRegisterComponent.wxs"
And the generated file is look like this.
<Fragment>
<DirectoryRef Id="INSTALLDIR">
<Component Id="Abc.dll" Guid="*">
<File Id="Abc.dll" KeyPath="yes" Source="SourceDirAbc.dll" />
</Component>
</DirectoryRef>
</Fragment>
Here this SourceDir path is confusing me.I have added the exact path in heat command even then it generates this SourceDir.
Short, Summary Answer
You need to stop using batch files and custom actions for COM registration (unreliable) and rather extract the COM registration information using the heat.exe tool from the WiX toolkit to add the COM registration to your MSI database at compile time.
There are some complications for 64-bit binaries, see details below. Fortunately it looks like you are dealing with a 32-bit component based on your installation directory shown above.
In this particular case it helped to run heat.exe on the COM file after deployment when all dependencies were "in place" for the COM file to load properly. There is a lot of "debugging communication" in these answers - I'll leave it all in place for the future, but try this simple solution first. And perhaps try the new dependency tool "Dependencies.exe" described below.
Long, Detailed Answer
Before I try to answer the question (which seems to revolve around missing dependencies or something weird being done in your batch file), I want to clear up a few things for you with regards to best practice for COM registration.
Note: the screenshot seems to indicate something weird going on in your batch file, but missing dependencies could still be an issue.
Self-registration Considered Harmful
Self-registration should not be used to register COM files. Here is a description of why this is the case: MSI register dll - Self-Registration considered harmful. There is good news, however, doing things as intended via built-in MSI mechanisms will be both easier and more reliable once you set it up properly.
There is a way to self-register files during installation without using custom actions like you are trying to do (the SelfReg table). Custom actions are very hard to get working correctly, but you should not use the built-in mechanism to run self-registration either (as explained in detail in the linked answer above)
Rather than using custom actions or the SelfReg table, COM registration information should be extracted from your COM files at compilation time - in other words when you compile your MSI file from your WiX source files. The extracted registry data should be used to populate the family of MSI data tables designed to reliably register and unregister the COM file during installation and uninstallation respectively.
WiX: The "heat.exe" Command Line Tool
Understanding the intricate details of this process is not necessary - all you need to know is what tools to use. WiX provides the "heat.exe" tool for this purpose. It is essentially a "harvester" tool capable of generating valid WiX XML source files for several purposes - one of which is COM extraction. It also supports traversing directories in general - generating WiX source files which can install the files encountered during traversal. It is essentially a very quick way to make an MSI package once you know how to use it.
Dependency Walker
So we have established that you should take the time to learn how to use heat.exe to generate the WiX source necessary to register the COM file properly. however, there is one more problem: the missing dependencies.
For a COM file to be able to self-register - or for you to be able to successfully extract the COM registry data using heat.exe - the COM file must be able to load correctly. For this to be possible all dll dependencies must be available on the system in question in an accessible location.
Get yourself a copy of Dependency Walker and use it to scan your COM file for what files it depends on. Here is an example of a COM file which fails to load because it cannot find MMUtilities.dll
:
You will most likely find something similar wrong with your dll (or whatever file type it is, for example OCX) when it is run from your setup's installation location. The required dependency files can not be found by regsvr32.exe and the registration process fails.
There are some reported missing dependencies that are not important - I guess this has to do with the age of the Dependency Walker tool - it hasn't been updated recently as far as I know. Look for a file you recognize as either your own dependency file or a core system file as opposed to very long dll names of files you have never heard of. Keep in mind that some dlls have dependency language dlls that are required for loading. For example MMUtilities.dll needs MmUtilitiesEnglish.dll or another language dll present in the same folder to be able to load correctly.
Some sample false positive dependencies for the above file: API-MS-WIN-CORE-RTLSUPPORT-L1-1-0.DLL
, API-MS-WIN-CORE-PROCESSTHREADS-L1-1-0.DLL
, API-MS-WIN-CORE-REGISTRY-L1-1-0.DLL
, etc... There were many. I believe, but I am not sure, that the root cause of these false positives centers around problems with side-by-side components installed to the WinSxS folder, but that is a whole other discussion - just mentioning it.
UPDATE: I just checked this again and most of the false positive dependencies seen above are apparently API-sets - a Windows feature introduced long after Dependency Walker was created, and hence not handled correctly by the tool.
As the linked answer indicates (do read it, link above), there is now also a rewrite of Dependency Walker in C# called "Dependencies", available here: https://github.com/lucasg/Dependencies (untested by me at time of writing, will test shortly).
Also quick mention: if you have an executable to check (as opposed to a dll, ocx, etc...), you can launch it via the Profile => Start Profiling...
menu entry and you will then also see "hidden run-time dependencies" not specified in the binary import table (where dependencies / imports are specified). You need to really exercise the application using all features in all dialogs to be sure to get all such dependencies.
The dependency walker web page calls these hidden dependencies explicit dependencies (a dynamic or run-time dependency) and system hook dependencies (injected dependencies). See the link just above for more details.
Heat.exe Extraction
Once you have determined what files are missing for making your WiX heat.exe extraction work, you can put the files in question "next to" your COM dll so they are found during its loading. You can test run using regsvr32.exe to see if registration completes correctly. There should be no error messages when you run registration manually like this. Remember to run registration from an elevated command prompt.
Several other stackoverflow answers explain how to use heat.exe - I haven't used it in a long time: How to run heat.exe and register a dll in wix. Here is the official documentation for heat.exe from the WiX guys themselves. It can be a somewhat intimidating tool - it has a lot of features.
In its simplest form (for normal 32-bit COM files with all dependencies available in the path or local folder), you can run this heat.exe command line to generate an output WiX source file called YourFileName.wxs
with all the required COM registry data.
heat.exe file YourFileName.ocx -o YourFileName.wxs
I wrote an answer several years ago showing how to incorporate the exported WiX registry data into your main WiX source: How to Reference a Heat Output(wxs) in Wix (Command Line). I believe this is an accurate description of the procedure, but for some reason someone down-voted the answer. Please give it a go and see if it works for you.
Important!: heat.exe does not yet correctly process 64-bit COM binaries (December, 2017).
I have been informed that the WiX Expansion Pack (not free) handles 64-bit binaries and provides several other features. I suppose I can link to it (I am not affiliated with FireGiant): https://www.firegiant.com/wix/wep-documentation/harvesting/. Somehow people need to know about these things, but I am not sure about the the stackoverflow etiquette of linking.
Are your binaries 64-bit? (it doesn't look that way from your installation folder, but I add this for others who might find it). For a 64-bit component I guess we have come full circle and have to advise you to either use the above expansion pack feature or just try to set the file to self-register as described here. I hate this self-register "solution", but I can't think of any other quick fixes at the moment (none that I would recommend anyway). I will check again. Make sure to check the latest WiX release to see if the 64-bit problem has been fixed before going for this "self-registration fix". It is at least better than trying to register using custom actions and batch files (which should never be attempted - there are so many potential problems relating to MSI's complex custom action sequencing, impersonation / elevation, conditioning,installation modes with silent and interactive, not to mention the potential interference from security software, and the list goes on).
Some links:
- How do you register a Win32 COM DLL file in WiX 3?
- Cannot register DLL using WiX
- Use wix to perform function of REGSVR32
- Heat.exe Cannot Harvest TypeLib Info from a 64-bit COM DLL
- Heat.exe: 64-bit .dll fails to be converted to a 64-bit .msi
这篇关于使用 Wix Msi 安装程序安装后将 CPP dll 注册到 COM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用 Wix Msi 安装程序安装后将 CPP dll 注册到 COM
基础教程推荐
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 从 std::cin 读取密码 2021-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- Windows Media Foundation 录制音频 2021-01-01