【问题标题】:How do I pass msiexec properties to a WiX C# custom action?如何将 msiexec 属性传递给 WiX C# 自定义操作?
【发布时间】:2009-05-07 16:11:57
【问题描述】:

我正在使用 Wxs 3.0 创建一个 MSI 文件。我的 MSI 引用了一个 C# 自定义操作,使用新的 C# Custom Action project 编写。

我想向 msiexec 传递一个参数,该参数被路由到我的自定义操作 - 例如:

msiexec /i MyApp.msi ENVIRONMENT=TEST#

在我的 .wxs 文件中,我这样引用我的自定义操作:

<Property Id="ENVIRONMENT"/>
<Binary Id="WixCustomAction.dll"  SourceFile="$(var.WixCustomAction.Path)" />
<CustomAction Id="WixCustomAction" BinaryKey="WixCustomAction.dll"    DllEntry="ConfigureSettings"/>
<InstallExecuteSequence>
   <Custom Action="WixCustomAction" After="InstallFiles"></Custom>
</InstallExecuteSequence>

我的 C# 自定义操作是这样设置的:

[CustomAction]
public static ActionResult ConfigureSettings(Session session)
{

}

我希望能够像这样访问该属性:

string environmentName = session.Property["ENVIRONMENT"];

但这似乎不起作用。

如何访问我在自定义操作中传递给 msiexec 的属性?

【问题讨论】:

    标签: wix windows-installer installation custom-action


    【解决方案1】:

    如果不是

    <CustomAction Id="SetCustomActionDataValue"
                  Return="check"
                  Property="Itp.Configurator.WixCustomAction"
                  Value="[ENVIRONMENT],G2,[CONFIGFILE],[TARGETDIR]ITP_v$(var.VERSION_MAJOR)" />
    

    你写这个:

    <CustomAction Id="SetCustomActionDataValue"
                  Return="check"
                  Property="Itp.Configurator.WixCustomAction"
                  Value="Environment=[ENVIRONMENT];G=G2;ConfigFile=[CONFIGFILE];TargetDir=[TARGETDIR]ITP_v$(var.VERSION_MAJOR)" />
    

    那么您将能够像这样引用您的变量:

    string env=session.CustomActionData["Environment"];
    

    【讨论】:

    • 一件事不要来自样本,分号周围不应该有任何空格。
    【解决方案2】:

    只是为了完整性;使用 Jeremy Lew 描述的方法,在上面的博客中允许以下内容:

    调用:

    msiexec /i ITP.Platform.2.msi ENVIRONMENT=QA CONFIGFILE=EnvironmentConfig.xml
    

    在 .wxs 文件中有这个:

    <Property Id="ENVIRONMENT" Secure="yes" />
    <Property Id="CONFIGFILE" Secure="yes" />
    <Binary Id="Itp.Configurator.WixCustomAction.dll"
            SourceFile="$(var.Itp.Configurator.WixCustomAction.Path)" />
    
    <CustomAction Id="SetCustomActionDataValue"
                  Return="check"
                  Property="Itp.Configurator.WixCustomAction"
                  Value="[ENVIRONMENT],G2,[CONFIGFILE],[TARGETDIR]ITP_v$(var.VERSION_MAJOR)" />
    
    <CustomAction Id="Itp.Configurator.WixCustomAction"
                  Return="check"
                  Execute="deferred"
                  BinaryKey="Itp.Configurator.WixCustomAction.dll"
                  DllEntry="ConfigureItpBrandSettings" />
    
    <InstallExecuteSequence>
      <Custom Action="SetCustomActionDataValue" After="InstallFiles"></Custom>
      <Custom Action="Itp.Configurator.WixCustomAction" After="SetCustomActionDataValue"></Custom>
    </InstallExecuteSequence>
    

    使用自定义操作:

        /// <summary>
        /// CustomAction keys should be Environment,BrandId,ConfigPath,itpBasePath
        /// </summary>
        /// <param name="session"></param>
        /// <returns></returns>
        [CustomAction]
        public static ActionResult ConfigureItpBrandSettings(Session session)
        {
            string[] arguments = GetCustomActionDataArguments(session);
    
            string environmentName = arguments[0];
            string brandId = arguments[1];
            string configPath = arguments[2];
            string itpBasePath = arguments[3];
    
            //Do stuff
    
            return ActionResult.Success;
        }
    
        private static string[] GetCustomActionDataArguments(Session session)
        {
            string[] keys = new string[session.CustomActionData.Keys.Count];
            session.CustomActionData.Keys.CopyTo(keys,0);
            return keys[0].Split(',');
        }
    

    有效。

    解析 CustomActionData 参数非常难看,但它确实有效。希望有人知道一种更优雅的方式来做到这一点。

    【讨论】:

      【解决方案3】:

      这是我的工作代码:

      <Binary Id="MyCA" SourceFile="..\bin\ChainerRun.CA.exe" />
      
      <CustomAction Id="SetCustomActionDataValue" Return="check" Property="CustomActionData" Value="TARGETDIR=[TARGETDIR];AA=Description;" />
      
      <CustomAction Id="ReadAndSet" 
                  BinaryKey="MyCA" 
                  DllEntry="ReadAndSet" 
                  Execute="immediate"
                  HideTarget="no" 
                  Return="check" />
      
      <InstallExecuteSequence>
          <Custom Action="SetCustomActionDataValue" Before="InstallFiles" />
          <Custom Action="ReadAndSet" After="SetCustomActionDataValue" />
      </InstallExecuteSequence>
      

      在C#自定义动作函数中:

      [CustomAction]
      public static ActionResult ReadAndSet(Session session)
      {
          ActionResult retCode = ActionResult.NotExecuted;
      
          System.Diagnostics.Debug.Assert(false);
      
          session.Log("ReadAndSet() begins ...");
      
          string installLocation = session.CustomActionData["TARGETDIR"];
          string hostName = session.CustomActionData["AA"];
          ...
      }
      

      【讨论】:

      • 谢谢!这似乎是这里最明显的例子,而且效果很好。
      【解决方案4】:

      您的自定义操作必须是延迟自定义操作才能在 InstallFiles 之后运行。延迟的自定义操作无法访问属性,但它们可以访问 CustomActionData。请参阅this blog post 以讨论如何处理它。 (此示例是一个 VBScript 自定义操作,但您将能够通过 session.CustomActionData 集合检索值。)

      【讨论】:

      • 请注意,该博客文章的链接不再有效。新链接是blogs.claritycon.com/sajojacob/2008/02/29/…
      • @SébastienNussbaumer:嗯,那个链接现在也失效了...... jlew:你应该在这里发布实际代码,而不是链接。
      【解决方案5】:

      如果我们谈论的是 Wix Sharp(而不是带有 XML 内容的普通 Wix),那么添加自定义属性就是小菜一碟。您所要做的就是为您的托管操作设置 UsesProperties 属性。

      例如,如果您想添加一个名为“MYPROP”的自定义属性,只需像这样定义您的操作:

      new ElevatedManagedAction(nameof(CustomActions.MyCustomAction))
      {
          Condition = Condition.Installed,
          When = When.Before,
          Step = Step.RemoveFiles,
          Return = Return.check,
          Execute = Execute.deferred,
          UsesProperties = "MYPROP"
      }
      

      通过 msiexec 命令行设置属性值:

      msiexec /i my.msi MYPROP=MYVALUE
      

      然后您就可以从您的自定义操作中访问它:

      [CustomAction]
      public static ActionResult MyCustomAction(Session session)
      {
          session.Log("MYPROP VALUE: " + session.CustomActionData["MYPROP"]);
          return ActionResult.Success;
      }
      

      当属性没有通过命令行设置时,默认值为空字符串。

      【讨论】:

        猜你喜欢
        • 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
        相关资源
        最近更新 更多