【问题标题】:How upgrade "secondary" executable using Wix?如何使用 Wix 升级“辅助”可执行文件?
【发布时间】:2011-02-02 18:24:38
【问题描述】:

我有用 Wix 3 编写的 msi 设置。没什么太花哨的,几个可执行文件 + 一些注册表操作。

我们有 2 个可执行文件,主应用程序和一直在运行的看门狗应用程序(一旦用户登录就会启动)。

我已经发布了我们软件的新版本,在 wix 中我们指定升级而不先卸载。新版本msi运行时,主应用升级,但是看门狗应用没有升级(即使没有运行,所以不是“in-use”问题)

我粘贴在我的 wxs 文件下面,希望您能帮助我找出问题所在。

非常感谢,

杰克

这是 wxs 文件:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <?include Properties.wxi?>
  <Product Id="$(var.ProductCode)" Name="$(var.Title)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
    <Package Description="$(var.ProductName)" Comments="$(var.ProductName)" InstallerVersion="200" Compressed="yes" />

    <Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
    <Upgrade Id="$(var.UpgradeCode)">
      <UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND' Minimum='$(var.ProductVersion)' IncludeMinimum='no' />
      <UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND" Minimum="0.0.0"  IncludeMinimum="yes" Maximum="$(var.ProductVersion)" IncludeMaximum="no" />
    </Upgrade>

    <Media Id="1" Cabinet="product.cab" EmbedCab="yes" CompressionLevel="high"/>
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder" Name="PFiles">
        <Directory Id="ApplicationRootFolder" Name="$(var.ProductName)">
          <Component Id="MyAppComponent" Guid="6657828D-0D3F-43A6-A2CB-375BFBB8A412">
            <RemoveFolder Id="ApplicationRootFolder" On="uninstall" />
            <File Id="MyAppMain" Name="MyApp.exe" Source="..\Release\MyApp.exe"/>
            <File Id="FirstRunApp" Name="FirstRunApp.exe" Source="..\Release\FirstRunApp.exe"/>
            <File Id="MyAppWatchDog" Name="MyAppWatchDog.exe" Source="..\Release\MyAppWatchDog.exe"/>
            <!--File Id="CheckSniffer" Name="CheckSniffer.exe" Source="..\Release\CheckSniffer.exe"/-->
            <File Id="License" Name="License.rtf" Source="License.rtf"/>
          </Component>
        </Directory>
      </Directory>
      <Directory Id="DesktopFolder" >
        <Component Id="DesktopShortcuts" Guid="5567ED7E-03F8-4AB8-AFB5-F8074F4ED1B5">
          <RegistryValue Id="RegShortcutDesktop" Root="HKCU" Key="Software\$(var.ProductName)" Name="DesktopSC" Value="1" Type="integer" KeyPath="yes" />
          <Shortcut Id="DesktopShortcut" Name="$(var.ProductName)" Directory="DesktopFolder" Description="$(var.ProductName)" Target="[ApplicationRootFolder]$(var.Name).exe" Icon="Icon.exe" WorkingDirectory="ApplicationRootFolder" />
        </Component>
      </Directory>
      <Directory Id="ProgramMenuFolder">
        <Directory Id="ProjectMenuFolder" Name="$(var.ProductName)">
          <Component Id="StartMenuShortcuts" Guid="5567ED7E-03F8-4AB8-AFB5-F8074F4ED1B4">
            <RegistryValue Root="HKCU" Key="Software\$(var.ProductName)" Type="string" Value="[ApplicationRootFolder]" Name="InstallPath"/>
            <RegistryValue Root="HKCU" Key="Software\Microsoft\Windows\CurrentVersion\Run" Type="string" Value="[#MyAppWatchDog]" Name="MyAppWatchdog"/>
            <RegistryValue Root="HKCU" Key="Software\$(var.ProductName)" Type="string" Value="" />
            <Shortcut Id="ProgramMenuShortcut" Name="$(var.ProductName)" Description="$(var.ProductName)" Target="[ApplicationRootFolder]$(var.Name).exe" Icon="Icon.exe" WorkingDirectory="ApplicationRootFolder" />
            <Shortcut Id="UninstallProduct" Name="Uninstall" Description="Uninstalls the $(var.ProductName)" Target="[System64Folder]msiexec.exe" Arguments="/x {$(var.ProductCode)}" />
            <RemoveFolder Id="ProgramMenuDir" On="uninstall" />
            <RemoveRegistryKey Root="HKCU" Key="Software\$(var.ProductName)" Action="removeOnUninstall"/>
          </Component>
        </Directory>
      </Directory>
    </Directory>
    <Feature Id="DefaultFeature" Title="$(var.Name)" Level="1">
      <ComponentRef Id="MyAppComponent" />
      <ComponentRef Id="StartMenuShortcuts" />
      <ComponentRef Id="DesktopShortcuts" />
    </Feature>

    <Property Id="SEARCHWINPCAP">
      <RegistrySearch Id="RegistrySearch" Root="HKLM" Key="SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\WinPcapInst" Name="VersionMajor" Type="raw"/>
    </Property>

    <Property Id="WIXUI_INSTALLDIR" Value="ApplicationRootFolder"/>
    <Property Id="PRODUCTNAME" Value="$(var.ProductName)"/>
    <!--Property Id="SNIFFER_CHECK_RESULT" Value="0"/-->
    <WixVariable Id="WixUIBannerBmp" Value="logo.JPG" />
    <WixVariable Id="WixUILicenseRtf" Value="License.rtf" />

    <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch $(var.Title)" />
    <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
    <Property Id="WixShellExecTarget" Value="[#MyAppMain]" />
    <CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />

    <CustomAction Id="SetLaunchWatchDogTarget" Property="WixShellExecTarget" Value="[#MyAppWatchDog]" />
    <CustomAction Id="LaunchWatchDog" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />

    <Binary Id="BinBrowseForFile" SourceFile="tools\WinPcap_4_1_2.exe"/>
    <CustomAction Id='LaunchWinPcapSetup' BinaryKey="BinBrowseForFile" ExeCommand="/Install" Execute="deferred" Impersonate="no"  Return="check"/>
    <CustomAction Id='NoDowngrade' Error='A later version of [ProductName] is already installed.'/>

    <Property Id="CUSTOM_TITLE" Value="$(var.Title) Setup" />
    <CustomAction Id='SetRepearTitle' Property='CUSTOM_TITLE' Value='Repair $(var.Title)'/>
    <CustomAction Id='SetRemoveTitle' Property='CUSTOM_TITLE' Value='Remove $(var.Title)'/>

    <!--debug-->
    <Binary Id="BinCustomAction" SourceFile="bin\release\CustomActions.CA.dll"/>
    <!--Binary Id="BinCheckSniffer" SourceFile="..\Release\CheckSniffer.exe"/-->
    <Property Id="USER_GUID_PATH" Value="Software\Licenses"/>
    <Property Id="USER_GUID" />
    <Property Id="DUBUG_URL" Value="http://debug.myapp.com/service/"/>
    <Property Id="DUBUG_STATE" Value="STARTED" />
    <CustomAction Id='SendRequest' BinaryKey="BinCustomAction" DllEntry="SendRequest" Execute="immediate" Return="check" />
    <CustomAction Id='SendRequest_WinPcap_Start' BinaryKey="BinCustomAction" DllEntry="SendRequest" Execute="immediate" Return="check" />
    <CustomAction Id='SendRequest_WinPcap_Finish' BinaryKey="BinCustomAction" DllEntry="SendRequest" Execute="immediate" Return="check" />
    <CustomAction Id='LicenseAgreement_Next' Property='DUBUG_STATE' Value='LICENSE_AGREED' />
    <CustomAction Id='InstallDirDlg_Install' Property='DUBUG_STATE' Value='INSTALL' />
    <CustomAction Id='Exit_Finish' Property='DUBUG_STATE' Value='FINISH' />
    <CustomAction Id='WinPcap_Start' Property='DUBUG_STATE' Value='WINPCAP_STARTED' />
    <CustomAction Id='WinPcap_Finish' Property='DUBUG_STATE' Value='WINPCAP_FINISHED' />
    <CustomAction Id='Traffic_Failed' Property='DUBUG_STATE' Value='TRAFFIC_FAILED' />
    <CustomAction Id='Traffic_Uninstalled' Property='DUBUG_STATE' Value='UNINSTALLED' />
    <CustomAction Id='Shell_icacls' Directory='ApplicationRootFolder' ExeCommand='icacls FirstRunApp.exe /setintegritylevel Low' Return="ignore" Execute="commit" Impersonate="no"/>

    <InstallExecuteSequence>
      <Custom Action='NoDowngrade' After='FindRelatedProducts'>NEWERFOUND</Custom>
      <Custom Action="WinPcap_Start" Before="SendRequest_WinPcap_Start" ><![CDATA[SEARCHWINPCAP < "4" AND NOT Installed]]></Custom>
      <Custom Action="SendRequest_WinPcap_Start" Before="LaunchWinPcapSetup"><![CDATA[SEARCHWINPCAP < "4" AND NOT Installed]]></Custom>
      <Custom Action="LaunchWinPcapSetup" Before="InstallFiles"><![CDATA[SEARCHWINPCAP < "4" AND NOT Installed]]></Custom>
      <!-- disable currently Custom Action="CheckSniffer" Before="Shell_icacls">NOT Installed</Custom-->
      <Custom Action="Shell_icacls" Before="InstallFinalize"><![CDATA[VersionNT >= 600 AND NOT Installed]]></Custom>
      <!--Custom Action="Shell_RunWatchDog" After="InstallFinalize"><![CDATA[NOT Installed]]></Custom-->
      <RemoveExistingProducts After="InstallFinalize"></RemoveExistingProducts>
      <Custom Action="Traffic_Uninstalled" Before='SendRequest'>Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
      <Custom Action="SendRequest" After='InstallFinalize'>Installed AND NOT UPGRADINGPRODUCTCODE</Custom>
    </InstallExecuteSequence>

    <UI />
    <UIRef Id="WixUI_Wizard" />

    <PropertyRef Id="NETFRAMEWORK35" />
    <Condition Message="This application requires .NET Framework 3.5 SP1.">Installed OR NETFRAMEWORK35</Condition>

    <Icon Id="Icon.exe" SourceFile="..\MyApp\Resources\icon_main.ico" />
  </Product>
</Wix>

【问题讨论】:

  • 您使用的是什么版本的 wix?这种行为存在于什么操作系统和服务包以及安装的 msi 版本上?当您在运行升级之前明确关闭看门狗应用程序时,升级是否按预期工作?你的 wxs 文件是什么样的?
  • 哇,实际上即使看门狗应用程序没有运行,它也没有被覆盖,所以我想它更基本。我们正在使用 Wix 3。
  • 看门狗应用程序EXE是否比已经安装的文件版本更高?仅当新包包含更高版本时,才会更新版本化文件。如果是,请尝试创建日志以查看文件未被覆盖的原因。
  • Cosmin,感谢您提出这一点。实际上看门狗是我们添加的一个新应用程序,并没有增加它的版本。所以现在一切正常!但我还有 1 个问题,在 XP SP2 上的行为与 W7/Vista 上的不同。在 W7/Vista 中,安装程序关闭了看门狗,但在 XP 中,它没有关闭,并提示用户重新启动对话框。只有在重新启动看门狗文件被替换后。您是否知道如何在升级阶段终止 Wix 中的进程?再次非常感谢

标签: wix windows-installer setup-project wix3


【解决方案1】:

从您的 Wix 代码中让我感到震惊的第一件事是,您将所有可执行文件都放在一个组件中,但该组件没有 KeyPath。这是一个非常糟糕的主意!这肯定会导致许多服务问题,例如您遇到的 watchdog.exe 没有更新的问题。

Windows Installer 将组件视为最小的安装单元。此外,Windows 安装程序只会查看 KeyPath 来确定组件是否存在(或需要更新等)。由于“MyAppComponent”没有 keypath,WI 将默认使用 Directory 作为您的 keypath。这意味着在升级过程中,如果 WI 找到您的目录,它将假定该组件已安装并且不会更新该组件中的任何文件。

要遵循的经验法则是,任何 .exe 或 .dll 文件都必须是组件中的唯一文件,并且它也应该是组件的键路径。我什至会在我的设置中为每个单独的文件创建一个组件,这将避免将来出现许多令人头疼的问题。尝试将 MyAppComponent 替换为以下组件:

<Directory Id="ApplicationRootFolder" Name="$(var.ProductName)">
  <Component Id="MyApp.exe" Guid="INSERT_GUID_HERE">
    <File Id="MyApp.exe" Name="MyApp.exe" Source="..\Release\MyApp.exe" KeyPath="yes"/>
  </Component>
  <Component Id="FirstRunApp.exe" Guid="INSERT_GUID_HERE">
    <File Id="FirstRunApp.exe" Name="FirstRunApp.exe" Source="..\Release\FirstRunApp.exe" KeyPath="yes"/>
  </Component>
  <Component Id="MyAppWatchDog.exe" Guid="INSERT_GUID_HERE">
    <File Id="MyAppWatchDog.exe" Name="MyAppWatchDog.exe" Source="..\Release\MyAppWatchDog.exe" KeyPath="yes"/>
  </Component>
  <Component Id="CheckSniffer.exe" Guid="INSERT_GUID_HERE">
    <File Id="CheckSniffer.exe" Name="CheckSniffer.exe" Source="..\Release\CheckSniffer.exe" KeyPath="yes"/>
  </Component>
  <Component Id="License.rtf" Guid="INSERT_GUID_HERE">
    <File Id="License.rtf" Name="License.rtf" Source="License.rtf" KeyPath="yes"/>
  </Component>
</Directory>

这应该可以解决您的更新问题。您可能还想考虑将快捷方式组件拆分为每个组件一个快捷方式,并将 HKCU 值设置为每个组件的键路径。

【讨论】:

    【解决方案2】:

    感谢所有努力提供帮助的人。

    @Cosmin Pirvu 是正确答案的人。我们没有更新看门狗应用程序的版本,因此它没有被安装。

    谢谢

    【讨论】:

      猜你喜欢
      • 2018-12-27
      • 1970-01-01
      • 1970-01-01
      • 2011-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-21
      • 2021-03-14
      相关资源
      最近更新 更多