【问题标题】:Custom Action for Wix Installer failing after first time runWix 安装程序的自定义操作在第一次运行后失败
【发布时间】:2014-11-24 03:38:33
【问题描述】:

我一直在尝试使用 msiexec 实现 msi 安装并将自定义参数传递给它。

msiexec /i somefile.msi /l*v output.txt IPADDRESS="127.0.0.1" PORT="9999"

现在我有以下代码来完成获取 IPADDRESS 和 PORT 并将它们写入文件的工作。以下是我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Deployment.WindowsInstaller;

namespace SetupCA
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult WriteFileToDisk(Session session)
        {
            session.Log("Begin WriteFileToDisk");

            string ipAddress = session["IPADDRESS"];
            string port = session["PORT"];
            string temp = @"
{{
 ""ip"" : ""{0}"" ,
""port"" : ""{1}""
}}";
            string config = string.Format(temp, ipAddress, port);
            session.Log("Config Generated was " + config);  
            System.IO.Directory.CreateDirectory("C:\\somefolder");
            try{
                 System.IO.File.Delete("C:\\somefolder\\some.config");
            }
            catch(Exception e){

            }
            System.IO.File.WriteAllText(@"C:\somefolder\some.config", config); 
            session.Log("Ending WriteFileToDisk");

            return ActionResult.Success;
        }
    }
}

编辑:完整的 Wix 代码 我使用了在 Wix 中生成的 dll 文件:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="CustomWixInstallerWithCustomAction" Language="1033" Version="1.0.0.0" Manufacturer="Developer" UpgradeCode="ba9015b9-027f-4451-adb2-e38f9168a850">
    <Package InstallerVersion="200" Compressed="no" InstallScope="perMachine" />

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

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

<Fragment>
    <Directory Id="TARGETDIR" Name="SourceDir">
        <Directory Id="ProgramFilesFolder">
            <Directory Id="INSTALLFOLDER" Name="CustomWixInstaller" />
        </Directory>
    </Directory>
</Fragment>

<Fragment>
    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
  <Component Id="SomeRandomEXE">
    <File Source ="some.exe" />
  </Component>
    </ComponentGroup>
<Binary Id="SetupCA"  SourceFile="SetupCA.CA.dll"/>
<CustomAction Id="WRITEFILETODISK" Execute="immediate" BinaryKey="SetupCA" DllEntry="WriteFileToDisk" />
<InstallExecuteSequence>
  <Custom Action="WRITEFILETODISK" Sequence="2"></Custom>

</InstallExecuteSequence>
</Fragment>

当我使用上面给出的命令安装 msi 时,一切正常。文本文件在文件夹中生成,其中包含参数期间给出的内容。但是当我使用相同的命令时,这些参数不会被提取并写入文件中。但如果我使用以下方式卸载它:

msiexec /x file.msi

然后再次运行,它可以工作。这里有什么问题?

【问题讨论】:

  • 对不起,但对我来说不清楚,你在尝试什么。特别是,您对句子“一切正常......使用上面给出的命令。[...]但是当我使用相同的(???)命令时,......”这句话的意思。第二:您要做什么,只需将命令行中给出的 ip 和端口记录到另一个配置文件中?或者您想从配置文件中取出两个 msi 属性?第三,也是最重要的。 msi 日志文件说的是您的自定义操作是否已启动。没有这些信息,我们什么也说不出来。
  • 程序编译的dll用于Wix的Custom Action内部,它应该获取给msifile的参数并将这些参数写入某个配置文件。当我使用上面的命令运行 msi 文件时,它会正确完成所有工作并创建配置文件。当我第二次运行相同的命令等时,不会获取这些参数并且配置文件看起来像 {"ip:"","port":""} 。如果我使用下面给出的命令卸载 msifile 并安装它再次,它确实有效。我的代码有问题吗。
  • @SarvagyaPant 您不能一遍又一遍地执行相同的安装程序,MSI 将检测到它当前已安装并中止安装。如果我没记错的话,您正在考虑维修或升级。如果是这种情况,您需要配置安装程序以使其正常运行。

标签: c# wix windows-installer


【解决方案1】:

Rolo 在评论中先给出了正确答案:

更详细:
如果您第二次调用 msi 设置,您不能指望它会像第一次那样做。 第一次调用(如果一切顺利)它会进行安装,第二次调用它几乎什么都不做,因为产品已经安装。

在两者之间卸载它或使用“REINSTALL=ALL”参数(可能与其他选项如 REINSTALLMODE 一起使用),然后完成修复/重新安装。

即使您的自定义操作适用于“第二次通话”,也没有任何价值。这就像试图破解墙上的电灯开关。有人可能会说:“我已将开关连接到 Arduino,每次有人打开灯时,都会响起警报。但不幸的是,如果我在灯还亮着的时候第二次按下灯开关,它不会工作……”

希望该示例有助于展示 MSI 背后的理念。

-- 除此之外:

对于您想要的,经验丰富的 msi 人员不会使用自定义操作。 “IniFile 表”就是为这样的事情而设计的。对于整个 MSI 空间,内置功能可能比自定义操作更可靠,仅作为一个示例,它也可以在延迟自定义操作中工作,例如在某些安全场景中是必需的。在这种情况下,简单的自定义操作无法轻松读取属性。

http://msdn.microsoft.com/en-us/library/aa369282%28v=vs.85%29.aspx

http://blogs.technet.com/b/alexshev/archive/2008/04/03/from-msi-to-wix-part-15-installable-items-ini-files.aspx

【讨论】:

  • 感谢您的洞察力。虽然我必须使用自定义操作,但使用 Inifile Table 的想法似乎也不错。
  • 如果我必须使用 Inifile,我应该如何使用它来执行任务。
  • 您好!您不必执行任何操作,只需填写 IniFile 表。我已经为此提供了一些链接,谷歌搜索会找到更多信息。MSI 正在正确的地方为您执行它。如果您对内部细节感兴趣,请查看您的 MSI 的执行顺序(您已下载 Orca、Insted 或其他任何建议),您会发现“WriteIniValues”操作。
【解决方案2】:

如果看不到您的整个 WiX 文件,就很难告诉您出了什么问题。有许多元素可能会阻止它。但从听起来的情况来看,我认为自定义操作不会在 case overinstall 中触发。

在我对你的其他问题的另一个回答中,我建议把:

        session.Log("Begin WriteFileToDisk");

在您的自定义操作中。这正是调试的原因。在第二次运行安装程序时,您是否在输出日志中看到这些行(用于开始和结束)?

最后,可能对您有所帮助的工具是 ORCA.exe 工具。
http://msdn.microsoft.com/en-us/library/aa370557%28v=vs.85%29.aspx

该工具可让您打开您的 msi 文件,并查看已设置的所有配置。因此,您可以查看是否为调用的自定义操作设置了条件。

【讨论】:

  • 对于同一 MSI 的第二次运行,我确实在日志中得到了 Begin WriteFileToDisk 和 End WriteFileToDsik 语句。我没有得到的是传递给 MSI 的参数
  • 如果开始和结束正在写入,则自定义操作正在运行,但可能处于修复模式?我不确定。据我了解,属性也应该设置为修复模式,但也许不是?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多