Wix CustomAction dll

时间:2014-10-06 12:57:00

标签: c# wix installation

我使用CAQuietExec的自定义操作在某些情况下失败 - 日志文件中出现的唯一错误消息对我来说非常适合作为开发人员,对最终用户来说是无用的。我的目标是在回滚安装之前捕获失败的操作并预设标准错误消息。

为此,基于我的研究,我决定自己需要编写自己的自定义动作dll,因此我开始关注this tutorial。在这个阶段,我的dll只记录测试消息并尝试将错误消息传回对话框屏幕。但是当我编译并运行msi时,根本没有任何事情发生 - 没有任何记录,也没有任何错误消息。看看Orca中的msi,它看起来还不错 - 但正如你在下面看到的那样,测试dll应该导致安装在实际运行时立即中止而不是。

所以我的问题是:我是否会以最佳方式向用户提供反馈?如果是这样,任何想法为什么我的自定义操作都没有运行?

由于

CustomAction.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Deployment.WindowsInstaller;
using System.Collections.ObjectModel;
using System.Management.Automation;

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

        DisplayMSIError(session, "A test message");

        return ActionResult.Failure;
    }

    static void DisplayMSIError(Session session, String msg)
    {
        var r = new Record();
        r.SetString(0, msg);
        session.Message(InstallMessage.Error, r);
    }
}
}

Product.wxs

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="MyPackage" Language="1033" Version="0.0.0.1" Manufacturer="Acme" UpgradeCode="GUID">
<Package InstallerVersion="300" Compressed="yes" InstallScope="perMachine" />

<Binary Id="MyCustomActions.CA.dll" src="MyCustomActions\MyCustomActions.CA.dll" />

<CustomAction Id="MyCustomActionsTest"
  Return="check"
  Execute="immediate"
  BinaryKey="MyCustomActions.CA.dll"
  DllEntry="CustomAction1" />

<InstallExecuteSequence>
  <Custom Action="MyCustomActionsTest" After="LaunchConditions"  />
  ...
</InstallExecuteSequence>
</Product>
</Wix>

2 个答案:

答案 0 :(得分:0)

呃,我浪费了几个小时的时间:但对于遇到同样问题的人,我会用自定义动作发布我的问题的答案 - 希望这会节省你的时间和挫折感。

我把测试操作很早地放在序列中,以为我会看到错误消息对话框。因此,我并没有真正尝试完成安装 - 当欢迎对话框出现时,我认为我的行动没有运行。但是,它必须已运行,因为当您实际选择某个功能并允许安装进度时,将显示错误消息。

尽管如此,如果有人能够提供一些见解,以确定这是否是提供一些用户对CAQuietExec正常运行的用户反馈的最佳方式,那么我们将不胜感激。

答案 1 :(得分:0)

您对此解决方案有何看法:

      Record record = new Record();
      record.FormatString = string.Format("Something has gone wrong!");

      session.Message(
         InstallMessage.Error | (InstallMessage) ( MessageBoxIcon.Error ) |
         (InstallMessage) MessageBoxButtons.OK,
         record );

来自this answer

另一种方法 - 创建自己的UI并根据需要显示任何消息。 小例子:

自定义操作:

    [CustomAction]
    public static ActionResult CheckSqlSessionState(Session session)
    {
        try
        {
            session.SendMessage(InstallMessage.Info, "Check Sql Session State");

            return ActionResult.Success;
        }
        catch (Exception exception)
        {
            session.SendMessage(InstallMessage.Error,
                string.Format("Error during the cheking sesssion state. {0}", exception.Message));
            return ActionResult.Failure;
        }
    }

注册:

    <CustomAction Id="WiXSetup.CustomAction.CheckSqlSessionState"
          BinaryKey="WiXSetup.CustomActions.dll" 
          DllEntry="CheckSqlSessionState" Execute="deferred" />

    <CustomAction Id="SetCheckSqlSessionStateDataValue"
          Return="check"
          Property="WiXSetup.CustomAction.CheckSqlSessionState" />

    <InstallExecuteSequence>
         <Custom Action="SetCheckSqlSessionStateDataValue" Before="WiXSetup.CustomAction.CheckSqlSessionState">NOT Installed</Custom>
         <Custom Action="WiXSetup.CustomAction.CheckSqlSessionState" After="WiXSetup.CustomAction.UpdateHomePageUrls">NOT Installed</Custom>
   </InstallExecuteSequence>

CSharp UI:

   using Microsoft.Deployment.WindowsInstaller;

   private ExternalUIRecordHandler recordHandler;
   // ...

   IntPtr parent = IntPtr.Zero;

   recordHandler = RecordHandler;

   private MessageResult RecordHandler(InstallMessage messageType, Record messageRecord, MessageButtons buttons, MessageIcon icon, MessageDefaultButton defaultButton)
    {
        switch (messageType)
        {
            case InstallMessage.Info:
                log.Info(message);
                return MessageResult.OK;
            case InstallMessage.Initialize:
                log.Debug(message);
                return MessageResult.OK;
            case InstallMessage.ActionData:
                log.Debug(message);
                return MessageResult.OK;
            case InstallMessage.ActionStart:
                log.Debug(message);
                return MessageResult.OK;
            case InstallMessage.CommonData:
                return MessageResult.OK;
            case InstallMessage.Error:
                log.Error(message);
                return MessageResult.OK;
            case InstallMessage.FatalExit:
                log.Fatal(message);
                return MessageResult.OK;
            case InstallMessage.FilesInUse:
                return MessageResult.No;
            case InstallMessage.OutOfDiskSpace:
                break;
            case InstallMessage.Progress:
                return MessageResult.OK;
            case InstallMessage.ResolveSource:
                return MessageResult.No;
            case InstallMessage.ShowDialog:
                return MessageResult.OK;
            case InstallMessage.Terminate:
                return MessageResult.OK;
            case InstallMessage.User:
                return MessageResult.OK;
            case InstallMessage.Warning:
                log.Warn(message);
                return MessageResult.OK;
        }

        return MessageResult.No;
    }