1

我们开发了一个非常全面的 wix 安装程序 msi 包,其中包括一些 10 多个 c# 自定义操作。

我的问题是我还没有弄清楚如何以编程方式“设置”一个属性。

基本上我想做的是将现有属性解析为新属性。

这种解析在 c# 中会很好,但也可以在 RegEx、JavaScript 或 w/e 中完成。

但是,我无法通过我的 c# 自定义操作(“无法从非即时自定义操作访问会话详细信息”)执行此操作,并且据我所知,我只能从类型 51 自定义操作更改属性。但是类型 51 不能使用我的 c# 自定义操作。所以它的捕获22。

谁能给我一个关于如何在 wix 中执行以下操作的示例:使用一个属性的值执行正则表达式/字符串操作并使用结果设置另一个。

对我来说这似乎很明显,这应该是可能的,但是经过大量搜索后,我仍然一无所知。

任何帮助,将不胜感激。


编辑#1:使用 wix 工作 3 年后,我仍然觉得自己像个业余爱好者,但这里有:我认为发送属性并在自定义操作中使用它们的唯一方法是这种模式:

 <CustomAction Id="CA.SetCreateMessageQueueProperty"
                  Property="CA.CreateMessageQueue"
                  Value="MsmqData=.\Private$\[MYAPPLICATIONNAME]/ObservationReportingService.svc,Observation delivery queue"
                  Return="check"/>
    <CustomAction Id="CA.CreateMessageQueue" 
                  BinaryKey="BI.CA" 
                  DllEntry="CreateMessageQueue" 
                  Execute="deferred" 
                  Return="check"
                  Impersonate="no"/>
    <InstallExecuteSequence>
      <Custom Action="CA.SetCreateMessageQueueProperty"
              After="InstallFiles"/>
      <Custom Action="CA.CreateMessageQueue" After="CA.SetCreateMessageQueueProperty">
        <![CDATA[((&FE.Afs=3) AND NOT (!FE.Afs=3))]]>
      </Custom>
    </InstallExecuteSequence>

在自定义动作 c# 程序集中:

[CustomAction]
        public static ActionResult CreateMessageQueue(Session session)
        {
            return session.DoCustomAction("CreateMessageQueue",
                () =>
                    {
                        string msmqData = session.ExtractString("MsmqData");

                        //create actual message queue
                            }
                        }
                    });
        }

internal static ActionResult DoCustomAction(this Session session, string name, Action action)
        {
            session.Log("Begin " + name);
            session.Log("session.CustomActionData.Count:" + session.CustomActionData.Count);
            try
            {
                action.Invoke();
            }
            catch (Exception ex)
            {
                session.Log(string.Format("Exception: {0}\nInner Exception: {1}", ex, ex.InnerException));
                return ActionResult.Failure;
            }
            return ActionResult.Success;
        }
4

2 回答 2

2

我认为您正在尝试在延迟自定义操作期间检索现有属性并将其分配给新属性。

<CustomAction Id="SetProperty" Return="check" Property="NameOfCustomActionYouAreUsingToRetrieveProperty" Value="[PROPERTY]"></CustomAction>

由于InstallExecuteSequence无法访问安装程序属性中的延迟自定义操作,我们必须将该属性添加到CustomActionData.

我用 C++ 编写了我的自定义操作,但我会发布代码,您会想到将其更改为 C# 代码。

extern "C" UINT __stdcall NameOfCustomActionYouAreUsingToRetrieveProperty(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
LPWSTR szValueBuf = NULL;

hr = WcaInitialize(hInstall, "NameOfCustomActionYouAreUsingToRetrieveProperty");
ExitOnFailure(hr, "Failed to initialize");

WcaLog(LOGMSG_STANDARD, "Initialized.");

hr = WcaGetProperty(L"CustomActionData",&szValueBuf);
ExitOnFailure(hr, "failed to get CustomActionData");

hr = MsiSetProperty(hInstall, "NEWPROPERTY",  szValueBuf);
ExitOnFailure(hr, "failed to set the new property");

LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);     
}
于 2013-02-13T09:22:12.893 回答
1

在 C# 中,您的代码将如下所示:

[CustomAction]
public static ActionResult MyCustomAction(Session session)
{
  string property = session["PROPERTYNAME"];
  session["PROPERTYNAME"] = "Look at me!";
  return ActionResult.Success;
}

session对象有权访问安装数据库及其所有表。并且使用它的索引器,您可以获取和设置属性表中的任何属性。

您还需要一个描述 .NET 运行时的小型 .config 文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v2.0.50727"/>
  </startup>
</configuration>

比使用and的C++ 替代方案干净得多。MsiGetPropertyMsiSetProperty

希望这会有所帮助。你可以在这个 WiX 教程中找到我刚刚写的所有内容,尤其是这个页面

于 2013-02-12T22:23:50.397 回答