从我的WiX安装程序安装设备驱动程序(打包在.exe中)时遇到困难

时间:2012-03-05 22:27:47

标签: wix windows-installer wix3.5 custom-action

我一直在努力构建一个新的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 ...或者我可能无法从另一个安装程序中运行安装程序?

2 个答案:

答案 0 :(得分:3)

我想修改我的答案,以涵盖我所学到的与我认为典型情况相关的内容:

  • 您想在对话框中自定义位图
  • 您可能还想跳过许可协议。
  • 您希望检测某些先决条件的存在,例如.NET Framework 4.0。
  • 您想编写一个安装程序,可以在安装过程结束时安装其他软件,例如设备驱动程序。
  • 您希望使用注册表项的存在来使前面提到的复选框不可见
  • 您可能需要包含合并模块,例如VC ++ 2010可再发行组件

首先要做的事情:

  • 所有信息都在互联网上。我花了几个小时趟过信息和尝试的东西。
  • 要有耐心,不要放弃!
  • 不要只依靠Google。 WiX文档(在.chm中)具有丰富的信息。我建议您在那里搜索,如果不是第一个。
  • 我是否已经说过,&#34;要有耐心,不要放弃!&#34;

Skeleton WXS

以下每个部分只有与自己直接相关的信息。在答案的最后,我将发布一个骨架(部分完成).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对话框集中找到。我只改变了以下内容:

  • WixUIBannerBmp
  • WixUIDialogBmp

只需将它们设置在<Product>元素下:

<WixVariable Id="WixUIBannerBmp" Value="$(var.ProjectDir)\Bitmaps\mybanner.bmp"/>
<WixVariable Id="WixUIDialogBmp" Value="$(var.ProjectDir)\Bitmaps\mydialog.bmp"/>

我只是在Visual Studio 2010中的WiX安装程序项目中创建一个Bitmaps文件夹。

跳过EULA对话&amp;设置安装位置

有多种内置方法可以定义您的安装程序的外观和流程,但对于我们这些懒惰的人,您只关心WIXUI_MINIMALWIXUI_INSTALLDIR 。前者只是非常懒惰(这是我最初发送给人们的!),但它不允许用户做任何事情,只需单击是以安装程序。它也不会告诉你安装完成了。 IMO,WIXUI_INSTALLDIR取得了很好的平衡。您将获得典型的欢迎对话框,单击“下一步”通过更典型的对话框,并在流程结束时获得“完成”按钮。

向WixUIExtension添加项目引用,然后使用以下XML:

在末尾安装设备驱动程序

如果要在安装结束时安装设备驱动程序,我认为最简单的方法是确保将驱动程序的setup.exe复制到安装位置,然后从那里执行。至少,这就是我的所作所为。然后你只需要使用CustomAction

但是,如果您想让用户决定是否安装驱动程序,该怎么办?然后你这样做:

<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>

Skeleton WXS

我在下面提供不完整的骨架.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扩展程序搜索引导程序中的注册表,类似于你是如何在安装程序中完成的。这种方法的好处是不会通过自定义操作来破坏安装程序。