2012-08-15 67 views
2

我有一个自定义动作项目,其中包含由我的公司创建的安装程序使用的各种CA,其中一些用于通过Microsoft操作IIs7 .Web.Administration API。将新的自定义动作添加到项目中可防止运行现有的自定义动作

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

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

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

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。

+0

请注意Visual Studio在构建我的解决方案(配置管理器)时未预先选择要构建的CustomActions项目。这可能会导致意外的过时的自定义操作程序集。 – 2016-05-04 15:12:19

回答

2

同样的事情发生在我身上。 “galets”已经指向了正确的方向,让我走上了正轨(没有代表upvote,抱歉)。

短版:

MakeSfxCA生产机DLL不按PE/COFF规范导致了观察到的行为。

龙版本:

  1. 构建一个CA,例如“HavocAction”具有三个导出入口点(即标记有“CustomAction”属性),名为“HavocEntryPointa”,“HavocEntryPointB”,“HavocZappEntryPoint”(介意确切的拼写)。这些方法可能会返回“ActionResult.Success”。
  2. 拿出简单的设置,一个)调用只是 “HavocEntryPointa”,B)只是调用 “HavocEntryPointB”
  3. ==>设置 “一)” 会工作,设置 “二)” 将失败
  4. 取消对在 “HavocZappEntryPoint” 和行为 “CustomAction” 属性反转,即
  5. ==>设置 “一)” 会失败,设置 “二)” 将工作

进一步分析

当你转储包装的CA.dll文件与

DUMPBIN /出口HavocAction.CA.dll

你喜欢的东西(节选)

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 

这是错误的(搜索 “pecoff_v83.docx”,比照。 Exported DLL functions not ordered lexically?)。条目应该被排序(通过ASCII),以便在从dll加载方法(条目“HavocEntryPointa”和“HavocEntryPointB”互换)时执行二进制搜索。

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

关于备注OP

Kjartan第一次使用“SetApplicationAutoStart”和“SetAppPoolLoadUserProfileTrue”,这是不正常出口到CA.dll由于错误排序;大写字母“P”在小写字母“l”之前,但是这由MakeSfxCA互换。他的后一种选择“ConfigureApplicationAutoStart”和“SetAppPoolLoadUserProfileTrue”按照PE/COFF规范排序。

PS:现在是http://wixtoolset.org/issues/4502

更新

PPS:与维克斯3.9 RC3版本包含此问题的bug修复启动;一切都按预期工作。

+0

将此更改为正确的答案,因为这将允许人们创建适当的解决方法。 – 2014-08-22 16:31:22

+0

Wix 3.10在Win10上存在该错误:( – 2016-08-05 20:36:19

1

其实,这是很奇怪,但很长一段时间后,寻找问题的答案,并试图不同的东西我试图改变从SetApplicationAutoStart到ConfigureApplicationAutoStart新的CA的名字很多的,并且导致SetAppPoolLoadUserProfileTrue重新开始正常工作

+0

我也看到某个.DLL打破了CA的功能,只是重命名这个.DLL文件才能启动并运行。很奇怪。 – 2014-08-04 15:41:02

2

我经历过,确切地说与您所描述的症状相同。 WiX工具集似乎存在问题。我的WiX tolset版本是3.8,我也有一个自定义操作,不会运行,并且更改它的名字可以解决问题。 SFX编译器只是编译了没有任何问题迹象的损坏的DLL。更糟糕的是,在我的情况下,这是一个应该使用Result =“ignore”卸载时运行的函数,所以我甚至没有任何即时的迹象表明在运行实际安装程序后出现问题。

我试着试着弄明白到底是什么问题,并没有找到任何令人满意的解释。在源代码中,违规函数的位置似乎并不重要,它是按字母顺序排列的(例如,函数按字母顺序排列在函数之前和之后)。将DLL加载到depends.exe显示有一个导出,但试图rundll32它无法找到该导出。更改名称可以解决问题。另外,有时你可以添加另一个函数,失败的函数会成功,但是你刚添加的函数会失败。

下面是我已经做了什么来解决这个问题:我写了一个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); 
      } 
     } 
    } 

希望这可以帮助别人在我的处境。这是一个非常令人沮丧的一天,试图指出这一点。