Wix 向项目中添加新的自定义操作将阻止运行现有的自定义操作

Wix 向项目中添加新的自定义操作将阻止运行现有的自定义操作,wix,custom-action,wix3.6,Wix,Custom Action,Wix3.6,我有一个自定义操作项目,它有我公司创建的安装程序使用的各种CA,其中一些用于通过Microsoft.Web.Administration API操纵IIs7 我在包含IIs相关CA的类中添加了一个名为SetApplicationAutoStart的新自定义操作。此自定义操作用于设置autoStart属性,强制IIs预加载和启动WCF服务,以便缩短初始响应时间 添加此操作后,名为SetAppPoolLoadUserProfileTrue的现有CA停止工作。此CA强制站点上的设置为true,即使计算

我有一个自定义操作项目,它有我公司创建的安装程序使用的各种CA,其中一些用于通过Microsoft.Web.Administration API操纵IIs7

我在包含IIs相关CA的类中添加了一个名为SetApplicationAutoStart的新自定义操作。此自定义操作用于设置autoStart属性,强制IIs预加载和启动WCF服务,以便缩短初始响应时间

添加此操作后,名为SetAppPoolLoadUserProfileTrue的现有CA停止工作。此CA强制站点上的设置为true,即使计算机上的默认站点已更改,因此此设置为false,因此我们确实需要它工作

当操作失败时,日志文件包含以下行

MSI (s) (A0:18) [15:02:43:639]: Executing op: ActionStart(Name=SetAppPoolLoadUserProfileTrue,,)
Action 15:02:43: SetAppPoolLoadUserProfileTrue. 
MSI (s) (A0:18) [15:02:43:641]: Executing op: CustomActionSchedule(Action=SetAppPoolLoadUserProfileTrue,ActionType=3073,Source=BinaryData,Target=SetAppPoolLoadUserProfileTrue,CustomActionData=AppPoolName=xxxxx)
MSI (s) (A0:18) [15:02:43:670]: Creating MSIHANDLE (377) of type 790536 for thread 50712
MSI (s) (A0:C8) [15:02:43:670]: Invoking remote custom action. DLL: C:\Windows\Installer\MSIBD82.tmp, Entrypoint: SetAppPoolLoadUserProfileTrue
CustomAction SetAppPoolLoadUserProfileTrue returned actual error code 1154 (note this may not be 100% accurate if translation happened inside sandbox)
MSI (s) (A0:C8) [15:02:43:673]: Closing MSIHANDLE (377) of type 790536 for thread 50712
MSI (s) (A0:18) [15:02:43:674]: Note: 1: 1723 2: SetAppPoolLoadUserProfileTrue 3: SetAppPoolLoadUserProfileTrue 4: C:\Windows\Installer\MSIBD82.tmp 
Error 1723. There is a problem with this Windows Installer package. A DLL required for this install to complete could not be run. Contact your support personnel or package vendor.  Action SetAppPoolLoadUserProfileTrue, entry: SetAppPoolLoadUserProfileTrue, library: C:\Windows\Installer\MSIBD82.tmp 
MSI (s) (A0:18) [15:20:25:139]: Product: xxxxxxx -- Error 1723. There is a problem with this Windows Installer package. A DLL required for this install to complete could not be run. Contact your support personnel or package vendor.  Action SetAppPoolLoadUserProfileTrue, entry: SetAppPoolLoadUserProfileTrue, library: C:\Windows\Installer\MSIBD82.tmp 
Action ended 15:20:25: InstallFinalize. Return value 3.

从该操作的PE中提取dotnet PE时出现问题。二进制文件中的所有其他CA都能正常工作,包括新的CA。

这实际上很奇怪,但在长时间搜索答案并尝试了很多不同的方法后,我尝试将新CA的名称从SetApplicationAutoStart更改为ConfigureApplicationAutoStart,结果是SetAppPoolLoadUserProfileTrue启动再次正常工作

我经历了与您描述的症状完全相同的症状。WiX工具集似乎有问题。我的WiX tolset版本是3.8,我还有一个自定义操作,它不会运行,更改它的名称修复了这个问题。SFX编译器只编译损坏的DLL,没有任何问题的迹象。更糟糕的是,在我的例子中,这是一个应该在卸载时使用Result=“ignore”运行的函数,因此在运行实际的安装程序后,我甚至没有任何立即的迹象表明存在问题

我试着去了解这个名字到底有什么问题,但没有找到任何令人满意的解释。在源代码中,有问题的函数在哪里,字母顺序是什么似乎无关紧要(例如:按字母顺序前后的函数成功)。将DLL加载到Dependes.exe中表明存在导出,但尝试运行DLL32时找不到该导出。更改其名称可以解决此问题。此外,有时您可以添加另一个函数,失败的函数会成功,但您刚才添加的函数会失败

这是我为解决这个问题所做的:我编写了一个C++程序,加载编译的自定义操作并验证导出。然后我编写了一个单元测试,它验证了定制操作中的所有导出。这显然不能解决问题,但至少您会遇到单元测试失败,并且知道您的安装程序已损坏。如果你感兴趣的话,这里是C++代码:

typedef int(__stdcall *CustomActionProc)(HANDLE);

int _tmain(int argc, _TCHAR* argv[])
{
    if (argc != 3)
    {
        _tprintf(_T("Parameters: DLL, EntryPoint\n"));
        return 1;
    }

    LPCTSTR dllName = argv[1];
    LPCTSTR entryPoint = argv[2];

    HMODULE hLib = LoadLibrary(dllName);
    if (hLib == NULL)
    {
        _tprintf(_T("Error loading %s\n"), dllName);
        return 1;
    }

    CustomActionProc procAddress = 
        (CustomActionProc) GetProcAddress(hLib, CStringA(entryPoint));
    if (procAddress == NULL)
    {
        _tprintf(_T("Error locating entrypoint %s\n"), entryPoint);
        return 1;
    }

    return 0;
}
单元测试是:

    [TestMethod]
    public void TestCustomActionCanBeInvoked()
    {
        var asm1 = typeof(MyCustomActionsClass).Assembly;
        var methods = asm1.GetTypes().SelectMany(t =>
            t.GetMethods().Where(m => m.GetCustomAttributes(false)
                    .Where(a => a.GetType().Name == "CustomActionAttribute").Any()));

        var binFolder = (new FileInfo(this.GetType().Assembly.Location)).DirectoryName;
        var customActionsSfx = Path.Combine(binFolder, "MyCustomAction.CA.dll");
        var testMsiExport = Path.Combine(binFolder, "TestMsiExport.exe");

        foreach (var m in methods)
        {
            Trace.WriteLine("Method Name: " + m.Name);

            var p = Process.Start(new ProcessStartInfo()
            {
                FileName = testMsiExport,
                Arguments = "\"" + customActionsSfx + "\" " + m.Name,
                UseShellExecute = false,
                RedirectStandardOutput = true,
            });

            p.OutputDataReceived += (s, d) => Trace.WriteLine(d.Data);
            p.BeginOutputReadLine();
            p.WaitForExit();

            if (p.ExitCode != 0)
            {
                Assert.Fail("Bad Sfx export detected! Export name: " + m.Name);
            }
        }
    }

希望这对我这种情况的人有所帮助。这是一个非常令人沮丧的一天,我一直在努力解决这个问题。

同样的事情也发生在我身上。“galets”已经指向了正确的方向,让我走上正轨(对不起,没有代表投票)

简短版本:

MakeSfxCA生成的本机DLL不符合PE/COFF规范,从而导致观察到的行为

长版本:

  • 构造一个CA,例如“HavocAction”,它有三个导出的入口点(即用“CustomAction”属性标记),名为“HavocEntryPointa”、“HavocEntryPointB”、“HavocZappEntryPoint”(注意准确的拼写)。这些方法可能只返回“ActionResult.Success”
  • 提出简单的设置,a)只调用“HavocEntryPointa”,b)只调用“HavocEntryPointB”
  • ==>设置“a”将工作,设置“b”将失败
  • 取消对“HavocZappEntryPoint”上的“CustomAction”属性的注释,行为将反转,即
  • ==>设置“a”将失败,设置“b”将工作
  • 进一步分析

    当您使用转储包装的CA.dll文件时

    dumpbin/Exports havoaction.CA.dll

    你会得到(摘录)

    这是错误的(搜索“pecoff_v83.docx”,参见)。当从dll加载方法时,为了进行二进制搜索,应该对条目进行排序(通过ASCII)(条目“HavocEntryPointa”和“HavocEntryPointB”互换)

    我的猜测是,当从dll加载代码时,二进制搜索失败,导致错误。由于二进制搜索的性质,删除“HavocZappEntryPoint”会反转效果

    关于OP的评论

    Kjartan首先使用了“SetApplicationAutoStart”和“SetAppPoolLoadUserProfileTrue”,由于顺序错误,未能正确导出到CA.dll;大写字母“P”位于小写字母“l”之前,但这是由MakeSfxCA交换的。他的后一选择“ConfigureApplicationAutoStart”和“SetAppPoolLoadUserProfileTrue”的订购符合PE/COFF规范

    附言:这是现在

    更新


    PPS:从WiX 3.9 RC3版本开始,包括针对该问题的错误修复;一切正常。

    我还看到某个.DLL破坏了CA功能,只需重命名这个.DLL文件,它就可以启动并运行。非常奇怪。将此更改为正确答案,因为这将允许人们创建适当的解决方案。此错误存在于Win10上的Wix 3.10中:(请注意,Visual Studio在生成解决方案(Configuration Manager)时未预先选择要生成的自定义操作项目)。这可能导致意外的过期自定义操作程序集。
    125   7C 00003A36 
    126   7D 00003A4C HavocEntryPointa
    127   7E 00003A62 HavocEntryPointB
    128   7F 00003A78 HavocZappEntryPoint
    129   80 000042FC zzzEmbeddedUIHandler
    130   81 000043B8 zzzInitializeEmbeddedUI
    131   82 0000467F zzzShutdownEmbeddedUI
    132   83 00003AA5 zzzzInvokeManagedCustomActionOutOfProcW