我一直在努力构建一个新的WiX安装程序,除了我还需要安装设备驱动程序之外,我对它非常满意。
理想情况下,我希望能够使用RegistrySearch
来检测此驱动程序的存在,例如
<Property Id="DRIVERINSTALLED">
<RegistrySearch Id="DriverInstalledSearch" Root="HKLM" Key="SOFTWARE\DriverCompany\Settings" Name="InstallPath" Type="raw" />
</Property>
如果InstallPath注册表项有值,那么我想继续安装设备驱动程序。我还没想出那个部分,但现在是次要的,因为我甚至无法每次都安装设备驱动程序。
网上有各种各样的例子,与WiX v3.5相对应的例子似乎遵循这种模式:
<CustomAction Id="InstallDeviceDrivers" Execute="deferred" Directory="INSTALLLOCATION" ExeCommand="setup.exe" Return="check" />
.
.
.
<InstallExecuteSequence>
<Custom Action="InstallDeviceDrivers" After="InstallFiles" />
</InstallExecuteSequence>
每当我运行我的msi时,我都会收到错误“无法运行此安装所需的程序”。
setup.exe被复制到我的INSTALLLOCATION,我已经通过在我的msi失败时查看该文件夹来验证这一点。
我使用了After
属性的值,但InstallFiles
似乎是正确的,因为它维护了提升的用户权限。我最初尝试InstallFinalize
,但失败了,我认为它没有以提升的权限运行。问题是,我尝试过的其他任何一项行动都没有。
然后我用msiexec /i installer.msi /l*v install.log
运行我的安装程序并查看输出文件。那是我看到一个稍微更具体的错误:
MSI (s) (74:CC) [14:06:10:098]: Executing op: ActionStart(Name=InstallDeviceDrivers,,)
Action 14:06:10: InstallDeviceDrivers.
MSI (s) (74:CC) [14:06:10:098]: Executing op: CustomActionSchedule(Action=InstallDeviceDrivers,ActionType=1058,Source=C:\Program Files\MyCompany\MyProduct\,Target=setup.exe,)
MSI (s) (74:CC) [14:06:10:108]: Note: 1: 1721 2: InstallDeviceDrivers 3: C:\Program Files\MyCompany\MyProduct\ 4: setup.exe
MSI (s) (74:CC) [14:06:10:108]: Note: 1: 2205 2: 3: Error
MSI (s) (74:CC) [14:06:10:108]: Note: 1: 2228 2: 3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 1721
Error 1721. There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. Action: InstallDeviceDrivers, location: C:\Program Files\MyCompany\MyProduct\, command: setup.exe
MSI (s) (74:CC) [14:06:11:800]: Note: 1: 2205 2: 3: Error
MSI (s) (74:CC) [14:06:11:800]: Note: 1: 2228 2: 3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 1709
MSI (s) (74:CC) [14:06:11:800]: Product: Installer -- Error 1721. There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. Action: InstallDeviceDrivers, location: C:\Program Files\MyCompany\MyProduct\, command: setup.exe
基于一些搜索,听起来我只需要以管理员身份运行,但我的安装程序已经触发了UAC ......果然,从提升的命令提示符运行安装程序没有帮助。
有人可以推荐下一步行动来调试吗?如果您还有关于如何根据注册表项的存在进行有条件安装的信息,那也非常好。谢谢!
编辑 - 我在Windows XP 32位和Windows 7 32位上运行了我的安装程序,但两者都失败了。还有另一个理由相信它与权限无关。
编辑#2 - 我不知道为什么我之前没有尝试过,但我从setup.exe更改为notepad.exe,并启动了记事本。显然CustomAction很有效。我将再次尝试使用Process Monitor来查看它在哪里寻找setup.exe ...或者我可能无法从另一个安装程序中运行安装程序?答案 0 :(得分:3)
我想修改我的答案,以涵盖我所学到的与我认为典型情况相关的内容:
首先要做的事情:
以下每个部分只有与自己直接相关的信息。在答案的最后,我将发布一个骨架(部分完成).wxs。
检测.NET Framework 4.0
首先,您需要向WixNetFxExtension添加项目引用。然后将此XML添加到<Product>
节点:(搜索.chm用于&#34; .NET&#34;)
<PropertyRef Id="NETFRAMEWORK40FULL" />
<Condition Message ="This application requires .NET Framework 4.0. Please install the .NET Framework and then run this installer again.">
<![CDATA[Installed OR NETFRAMEWORK40FULL]]>
</Condition>
在.chm中的自定义内置WixUI对话框集中找到。我只改变了以下内容:
只需将它们设置在<Product>
元素下:
<WixVariable Id="WixUIBannerBmp" Value="$(var.ProjectDir)\Bitmaps\mybanner.bmp"/>
<WixVariable Id="WixUIDialogBmp" Value="$(var.ProjectDir)\Bitmaps\mydialog.bmp"/>
我只是在Visual Studio 2010中的WiX安装程序项目中创建一个Bitmaps文件夹。
有多种内置方法可以定义您的安装程序的外观和流程,但对于我们这些懒惰的人,您只关心WIXUI_MINIMAL
和WIXUI_INSTALLDIR
。前者只是非常懒惰(这是我最初发送给人们的!),但它不允许用户做任何事情,只需单击是以安装程序。它也不会告诉你安装完成了。 IMO,WIXUI_INSTALLDIR
取得了很好的平衡。您将获得典型的欢迎对话框,单击“下一步”通过更典型的对话框,并在流程结束时获得“完成”按钮。
向WixUIExtension添加项目引用,然后使用以下XML:
WiX installer guidance (Stack Overflow)
1 1
如果要在安装结束时安装设备驱动程序,我认为最简单的方法是确保将驱动程序的setup.exe复制到安装位置,然后从那里执行。至少,这就是我的所作所为。然后你只需要使用CustomAction
:
How To: Run the Installed Application After Setup (SourceForge上的WiX)
但是,如果您想让用户决定是否安装驱动程序,该怎么办?然后你这样做:
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Install device drivers when the installer exits." />
,您的<UI>
节点现在看起来像这样:
<UI>
<UIRef Id="WixUI_InstallDir" />
<Publish Dialog="WelcomeDlg" Control="Next" Event="NewDialog" Value="InstallDirDlg" Order="2">1</Publish>
<Publish Dialog="InstallDirDlg" Control="Back" Event="NewDialog" Value="WelcomeDlg" Order="2">1</Publish>
<Publish Dialog="ExitDialog" Control="Finish" Order="1" Event="DoAction" Value="InstallDeviceDrivers">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLLOCATION" />
</UI>
上面添加的逻辑只是检查是否选中了复选框,以及&#34;和未安装&#34;是否确保此操作仅在安装程序安装应用程序时运行,而不是卸载。
只需将以下XML添加到Product
:
<Property Id="DRIVERINSTALLED">
<RegistrySearch Id="DriverInstalledSearch" Root="HKLM" Key="SOFTWARE\DriverCompany\Settings" Name="SomeRegistryKeyThatMustBePresentIfInstalled" Type="raw" />
</Property>
然后使用<SetProperty>
代替<Property>
,如前所示:
How do I create a conditional property in WiX? (Almost like an If-Then)
<SetProperty Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Install device drivers when the installer exits." After="CostFinalize">
<![CDATA[NOT DRIVERINSTALLED]]>
</SetProperty>
最后,如果您需要添加VC ++ 2010 Redistributable软件包,该怎么办?我不确定这样做的最好方法,虽然我的应用程序在我这样做的时候(之前没有),我发现添加/删除程序没有提到这很奇怪关于它实际安装的任何事情。所以对于这部分,YMMV。
由于我运行的continuous integration(CI)服务器并非必须安装Visual Studio 2010,因此我将合并模块文件放入我的WiX安装程序项目中。我创建了一个名为MergeModules的文件夹并将其放在那里。该文件位于Program Files \ Common Files \ Merge Modules中,名为Microsoft_VC100_CRT_x86.msm。现在将以下行放在<Directory>
节点中:
How To: Install the Visual C++ Redistributable with your installer (SourceForge上的WiX)
<Merge Id="VCRedist" SourceFile="$(var.ProjectDir)\MergeModules\Microsoft_VC100_CRT_x86.msm" DiskId="1" Language="0"/>
以及<Feature>
节点中的以下行:
<Feature Id="VCRedist" Title="Visual C++ 10.0 Runtime" AllowAdvertise="no" Display="hidden" Level="1">
<MergeRef Id="VCRedist"/>
</Feature>
我在下面提供不完整的骨架.wxs。它不完整,因为我只提供与此帖子没有直接关联的内容的元素名称。丢失的信息很容易找到。
答案 1 :(得分:1)
我可以建议采用不同的方法。使用WiX Burn等引导程序检查驱动程序是否已安装,如果没有,请将其作为先决条件安装。然后启动MSI安装程序。 WiX捆绑包看起来像:
<Fragment>
<util:RegistrySearch
Variable="DriverInstalled"
Root="HKLM,SOFTWARE\Microsoft\MyProduct\[UniqueId]\Setup"
Key="InstallPath"
Result="Exists" />
<PackageGroup Id="DriverPackage">
<ExePackage
SourceFile="Path_To_Driver\Setup.exe"
InstallCondition="InstallPath" />
</PackageGroup>
<PackageGroup Id="MainMsi">
<MsiPackage
SourceFile="Path_To_Msi\Installer.msi"
After="DriverPackage" />
</PackageGroup>
</Fragment>
注意:我没有测试上面的内容,但是如果你走这条路,这应该可以让你开始。如果您有兴趣,我建议您查看WiX bootstrapper bundles并 Define Searches Using Variables 说明如何使用util
扩展程序搜索引导程序中的注册表,类似于你是如何在安装程序中完成的。这种方法的好处是不会通过自定义操作来破坏安装程序。