使用CustomAction卸载Wix的问题

时间:2019-03-17 08:49:41

标签: installation wix windows-installer wix3.7

我创建了一个非常简单的MSI,它将一些文件复制到ProgramFiles目录,并在安装对以C#编写的二进制文件中找到的自定义操作的调用时进行。

在安装时,我可以轻松调用所需的任何自定义操作。例如,我创建了一个安装步骤,用户应在其中输入许可证,并在确认许可证后使用C#自定义操作中编写的逻辑针对服务器对许可证进行检查。

但是,在卸载时,每次我添加一个自定义操作(即使它只返回成功都没有执行任何操作),都会收到安装失败的错误消息。

这是我使用卸载步骤的方式:

<InstallExecuteSequence>
  <Custom Action='TestUninstallation' After='MsiUnpublishAssemblies'>REMOVE="ALL"</Custom>
</InstallExecuteSequence>

其中TestUninstallation的定义如下:

<CustomAction Id="TestUninstallation" Return="check" Execute="deferred" Impersonate="no" BinaryKey="TestCustomAction" DllEntry="Uninstall" />

DllEntry属性等于Uninstall,这是一种C#方法,仅返回成功。

安装完成后,我试图卸载,并在AdminUISequence中定义了具有属性OnExit的UserExit对话框。

知道我想念什么吗?

1 个答案:

答案 0 :(得分:0)

调试 :托管代码相对易于调试(本地代码实际上甚至更容易)。这里有一些指针:


  

建议 :我认为您只有一个 broken reference to the dll export function -换句话说,错误的dll函数名称/引用:< / p>

<CustomAction Id="TestUninstallation" Return="check" Execute="deferred" Impersonate="no"
              BinaryKey="CustomActions" DllEntry="__ERRONEOUS FUNCTION REFERENCE__" />

只需检查dll实际导出的内容并进行匹配,如下所示:

<CustomAction Id="CustomAction1" BinaryKey="CustomActions" DllEntry="CustomAction1"/>

一如既往,真正的McCoy是对dll本身的检查,以查看您是否具有正确的函数名(the below screen shot from this prior answer, recommended read)。

This is a native code C++ dll

Dependency Walker

This is a DTF-packaged managed code dll

Managed Code Custom Action

请注意,这是一个嵌入了托管代码内容的本机dll。它产生了一个非常不同的函数列表,但是您仍然必须在其中找到所引用的函数名称。

This is a straight-up managed code dll (no native wrapping)

Managed code dll, unwrapped

最后:这是直接托管代码DLL,没有包装在本机dll外壳中。


不可卸载的安装程序 :当自定义操作在卸载过程中崩溃或失败时,您将有摆脱安装的问题(它只是回滚而您卡住安装)。有几个修复程序或解决方法。

总体看来-我认为-不会使自定义操作在卸载时失败,或者至少要对它们进行条件处理,以便您可以通过在命令行中设置属性来强制卸载

在MSI属性表中设置: SUPPRESSERROR = 0 。然后-在需要时-在命令行上设置:

msiexec.exe /x {PRODUCT-GUID} SUPPRESSERROR="1"

在MSI内部,您可以使用以下条件来执行卸载自定义操作:

REMOVE="ALL" AND SUPPRESSERROR="0"

现在,如果SUPPRESSERROR不为0,则自定义操作将不会运行。

有一个较旧的答案,还有其他更多选择:I screwed up, how can I uninstall my program?(由Wim Coenen提供,我将他的答案与更多建议混在一起)。


样板 :为了快速使用,让我在此处转储样板临时自定义操作测试项目。假设在同一Visual Studio解决方案中有一个名为 "CustomAction1" 的C#托管代码自定义操作项目,并且在WiX源中向其中添加了一个引用-就像您已经很清楚地知道了(这在以后的版本中我们都忘记了问题所在,需要再次测试):

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

    <UIRef Id="WixUI_Mondo" />
    <Property Id="SUPPRESSERROR" Value="0" Secure="yes" />

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

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

    <!--BEGIN CUSTOM ACTION SECTION-->

      <Binary Id="CustomActions" SourceFile="$(var.CustomAction1.TargetDir)\$(var.CustomAction1.TargetName).CA.dll" />
      <CustomAction Id="TestUninstallation" Return="check" Execute="deferred" Impersonate="no" BinaryKey="CustomActions" DllEntry="CustomAction1" />

      <InstallUISequence></InstallUISequence>

      <InstallExecuteSequence>
        <Custom Action='TestUninstallation' After='InstallInitialize'></Custom>
      </InstallExecuteSequence>

    <!--END CUSTOM ACTION SECTION-->

  </Product>

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

  <Fragment>

    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">

      <Component>
        <File Source="C:\Projects\MySetup\MyApp.exe">
        </File>
      </Component>

    </ComponentGroup>

  </Fragment>
</Wix>
  1. 创建WiX项目
  2. 复制粘贴代码,设置新的升级GUID
  3. 创建CustomAction项目,默认名称
  4. 从wix项目中添加对自定义操作项目的引用
  5. 添加对WiXUIExtension.dll的引用
  6. 调整组件中文件的路径
  7. 编译