【问题标题】:Msi Installer Runs custom Action but leaves File for InstallationMsi 安装程序运行自定义操作但留下文件进行安装
【发布时间】:2015-01-09 09:47:46
【问题描述】:

我有以下 Wix 文件,它应该安装 C:\SampleProgram 中的内容。生成的 msi 应该安装为msiexec /i installer.msi IPADDRESS="1.1.1.1"。参数IPADDRESS 由自定义操作获取,该操作将在程序自行安装的文件夹中生成如下配置文件。

{
  "ip" : "1.1.1.1" 
}

问题是生成的安装文件在我的一台机器上工作正常,但它只在另一台机器上创建一个配置文件。成功安装 MSI 的文件夹将包含我的 wix 文件的 ComponentGroup 下定义的所有 Component 文件。如果安装成功,安装程序会将所有这些组件复制到已安装文件夹中。即使它没有安装文件,但它运行了自定义操作。

详细日志为here

如果有人搜索 Component: BoostThreadLibrary ,我会得到 Installed: Absent,正如给定的 here 所说,组件或功能当前未安装。。

错误是和我的机器还是这个代码有关。

我在下面附上了 wix 文件:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="*" Name="SampleProgram" Language="1033" Version="3.0.0" Manufacturer="Learning" UpgradeCode="a0265d05-8e65-4af2-98e1-a675b728dd2d">
        <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

        <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
        <MediaTemplate EmbedCab="yes" />

        <Feature Id="ProductFeature" Title="SampleProgram" Level="1">
            <ComponentGroupRef Id="ProductComponents" />
        </Feature>
    </Product>

  <Fragment>
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="WindowsVolume">
        <Directory Id="INSTALLFOLDER" Name="SampleProgram" />
      </Directory>
    </Directory>
  </Fragment>

  <Fragment>
    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
      <Component Id="ProductComponent">
        <File
          Id="LPAEXE"
          Name="lpa.exe"
          DiskId="1"
          Source="$(var.lpa.TargetPath)"
          Vital="yes"
          KeyPath="yes" />

        <?if $(var.Configuration) = "Release"?>
          <ServiceInstall Id="ServiceInstaller" Type="ownProcess" Vital="yes"
                          Name="LearningService" DisplayName="LearningService"
                          Description="How to make a Service" Start="auto"
                          Account="LocalSystem" ErrorControl="normal" Interactive="no" />

          <ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall"
                          Name="LearningService" Wait="yes" />
        <?endif?>
      </Component>
      <Component Id="BoostThreadLibrary">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_thread-vc100-mt-gd-1_55.dll" />
        <?else?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_thread-vc100-mt-1_55.dll" />
        <?endif?>
      </Component>
      <Component Id="BoostSystemLibrary">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_system-vc100-mt-gd-1_55.dll" />
        <?else?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_system-vc100-mt-1_55.dll" />
        <?endif?>
      </Component>
      <Component Id="BoostChronoLibrary">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_chrono-vc100-mt-gd-1_55.dll" />
        <?else?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_chrono-vc100-mt-1_55.dll" />
        <?endif?>
      </Component>
      <Component Id="BoostFileSystemLibrary">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_filesystem-vc100-mt-gd-1_55.dll" />
        <?else?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_filesystem-vc100-mt-1_55.dll" />
        <?endif?>
      </Component>
      <Component Id="BoostDateTimeLibrary">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_date_time-vc100-mt-gd-1_55.dll" />
        <?else?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_date_time-vc100-mt-1_55.dll" />
        <?endif?>
      </Component>

      <Component Id="BoostZlibLibrary">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_zlib-vc100-mt-gd-1_55.dll" />
        <?else?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_zlib-vc100-mt-1_55.dll" />
        <?endif?>
      </Component>
      <Component Id="BoostIOStreamLibrary">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_iostreams-vc100-mt-gd-1_55.dll" />
        <?else?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_iostreams-vc100-mt-1_55.dll" />
        <?endif?>
      </Component>
      <Component Id="BoostRegexLibrary">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_regex-vc100-mt-gd-1_55.dll" />
        <?else?>
        <File Source ="C:\boost_1_55_0_dyn\stage\lib\boost_regex-vc100-mt-1_55.dll" />
        <?endif?>
      </Component>
      <Component Id="libeay32">
        <File Source ="C:\OpenSSL-Win32\libeay32.dll" />
      </Component>
      <Component Id="ssleay32">
        <File Source ="C:\OpenSSL-Win32\ssleay32.dll" />
      </Component>
      <Component Id="czmq">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="..\..\ext_library\zmq\czmq\czmq-2.1.0\lib\Win32\DebugDLL\czmq.dll" />
        <?else?>
        <File Source ="..\..\ext_library\zmq\czmq\czmq-2.1.0\lib\Win32\ReleaseDLL\czmq.dll" />
        <?endif?>
      </Component>

      <Component Id="log4cplus">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="..\..\ext_library\log4cplus\bin\Debug\log4cplusD.dll" />
        <?else?>
        <File Source ="..\..\ext_library\log4cplus\bin\Release\log4cplus.dll" />
        <?endif?>
      </Component>
      <Component Id="libzmq">
        <?if $(var.Configuration) = "Debug"?>
        <File Source ="..\..\ext_library\zmq\zeromq-4.0.3\lib\Win32\Debug\libzmq.dll" />
        <?else?>
        <File Source ="..\..\ext_library\zmq\zeromq-4.0.3\lib\Win32\Release\libzmq.dll" />
        <?endif?>
      </Component>
      <Component Id="SSL_Crt_File">
        <File Source ="..\..\src\keys\ca.crt" />
      </Component>

    </ComponentGroup>    
    <Binary Id="SetupCA"  SourceFile="..\..\ext_library\SetupCA\SetupCA\bin\Release\SetupCA.CA.dll"/>
    <CustomAction Id="WRITEFILETODISK" Execute="immediate" BinaryKey="SetupCA" DllEntry="WriteFileToDisk" />
    <InstallExecuteSequence>
      <Custom Action="WRITEFILETODISK" Sequence="2"></Custom>
    </InstallExecuteSequence>
  </Fragment>
</Wix>

【问题讨论】:

    标签: c++ wix windows-installer


    【解决方案1】:

    问题的核心是自定义操作的调度:

    <CustomAction Id="WRITEFILETODISK" Execute="immediate" BinaryKey="SetupCA" DllEntry="WriteFileToDisk" />
    <InstallExecuteSequence>
      <Custom Action="WRITEFILETODISK" Sequence="2"></Custom>
    </InstallExecuteSequence>
    

    作为在InstallFinalize 之前安排的即时操作,在运行此自定义操作时不会发生对文件的任何更改。虽然这对于卸载来说可能很重要,但这可能与您想要的安装相反。

    要读取由您的安装安装的文件,您应该安排您的操作Execute="deferred",并在InstallFiles 之后的某个时间。如果您在系统位置修改项目,它也应该是Impersonate="No",它只适用于延迟执行上下文。

    请注意,一旦您的操作被推迟,您将不得不通过CustomActionData 访问属性。

    【讨论】:

    • 问题是相同的代码适用于其他机器。一切都已完全设置并创建了配置,但在我的机器上我没有得到任何已安装的文件。相反,在日志中,我得到 Installed: Absent 的组件
    • 感谢您指出自定义操作问题。我也会修改的。
    • 我可能误读了您所说的“问题是我无法获取 Wix 应该在已安装文件夹中复制的文件,但安装程序运行自定义操作”,因为很多人都遇到了这个问题我描述。您能否澄清一下您的期望,您遇到的情况,以及每一种发生的确切时间 - 即如果总体失败是最后没有安装文件,我的回答充其量是切题的。
    • 生成的安装程序在另一台机器上工作,它将正确加载所有组件并生成配置文件。我机器上的同一个安装程序不会加载我在ComponentGroup 中提供的任何组件,但会生成配置文件。在比较两种安装的日志时,我看到 Installed: Local 表示成功安装的机器,但 Absent 在我的机器中。它只是不加载写在ComponentGroup 中的任何组件。问题与我的代码或我的机器有关吗?
    • 不清楚您所说的“加载所有组件”是什么意思 - 这听起来像是描述您的自定义操作所做的事情的术语,而不是 Windows Installer 的预期行为。请编辑问题,以便更清楚地了解预期行为,以及您如何诊断它不会发生。
    【解决方案2】:

    我不知道为什么,但将 upgrade code 更改为其他 GUID 确实解决了问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多