我在 Windows 7 上有一个简单的 WiX (3.5.2030.0) 安装程序(根据 msiexec.exe 的属性,Windows Installer 5.0.7600.16385),它使用提供的自定义操作来创建 SQL 数据库。当我自己运行 MSI 或在 C# 设置引导程序中的事务中运行它(使用 DTF 进行互操作)时,它可以正常工作。
当我在引导程序中运行 MSI 并在外部 UI 处理程序中挂接时(工作中唯一的代码更改是这样的调用:
Installer.SetExternalUI(ExternalUIHandler, ilm);
),但是,CreateDatabase 调用失败。SQL 日志中没有任何相关内容 - 它显示正在启动的数据库。SQL Profiler 中没有任何相关内容 - 它显示 CA 检查数据库的存在,然后在创建失败后尝试删除。以下是调试详细日志显示的内容:
MSI (s) (74:F4) [16:42:59:213]: Executing op: ActionStart(Name=CreateDatabase,Description=Creating Databases,)
MSI (s) (74:F4) [16:42:59:243]: Executing op: CustomActionSchedule(Action=CreateDatabase,ActionType=25601,Source=BinaryData,Target=**********,CustomActionData=**********)
MSI (s) (74:F4) [16:42:59:253]: Creating MSIHANDLE (769) of type 790536 for thread 5876
MSI (s) (74:A4) [16:42:59:253]: Invoking remote custom action. DLL: C:\Windows\Installer\MSID856.tmp, Entrypoint: CreateDatabase
MSI (s) (74!7C) [16:43:01:493]: Creating MSIHANDLE (770) of type 790531 for thread 8060
MSI (s) (74!7C) [16:43:01:513]: Closing MSIHANDLE (770) of type 790531 for thread 8060
CustomAction CreateDatabase returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
MSI (s) (74:A4) [16:43:14:682]: Closing MSIHANDLE (769) of type 790536 for thread 5876
请注意,日志没有显示有用的 SQL 错误代码 - 只是(一如既往地无用)1603 错误(翻译:有些东西坏了)。
外部 UI 处理程序中的挂钩与运行数据库创建有什么关系?
我知道这个问题与我的外部 UI 处理程序代码有关,因为如果我用“返回 MessageResult.None”将它短路,那么一切正常。
我的顶级处理程序代码如下;它基于http://msdn.microsoft.com/en-us/library/aa368786(VS.85).aspx:
switch (messageType) {
case InstallMessage.FatalExit:
MessageBox.Show("FATAL EXIT: " + message, "Fatal exit",
MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case InstallMessage.Error:
MessageBox.Show("ERROR: " + message, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
case InstallMessage.Warning:
MessageBox.Show("WARNING: " + message, "Warning",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
break;
case InstallMessage.User:
// nothing to do here
break;
case InstallMessage.Info:
// nothing to do here
break;
case InstallMessage.FilesInUse:
MessageBox.Show("Files in use: " + message, "Files in use",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
break;
case InstallMessage.ResolveSource:
// nothing to do here
break;
case InstallMessage.OutOfDiskSpace:
MessageBox.Show("OUT OF DISK SPACE: " + message,
"Out of disk space", MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
break;
case InstallMessage.ActionStart:
_enableActionData = false;
ProcessActionStart(message);
break;
case InstallMessage.ActionData:
ProcessActionDataMessage(message);
break;
case InstallMessage.Progress:
// http://msdn.microsoft.com/en-us/library/aa370573(VS.85).aspx
ProcessProgressData(message);
break;
case InstallMessage.CommonData:
// ignore for now
break;
case InstallMessage.Initialize:
case InstallMessage.Terminate:
SetHighLevelStatus(messageType.ToString());
break;
case InstallMessage.ShowDialog:
// nothing to do here
break;
}
AddDetailedStatusLine("... " + messageType + ":" + message);
return MessageResult.None;
//return MessageResult.OK;
因为还没有实现完整的 UI,现在只是进度部分,我返回“None”,这样内部 UI 仍然会触发。显然,这需要在生产前进行更改。MessageBox 调用也是如此,在生产代码中可能会有不同的处理方式。
谢谢!