在我的WiX安裝程序中,我想優雅地關閉即將運行的即將更新的應用程序。我不想提醒用戶關閉,我不想殺死這個進程。在關閉應用程序之前,我需要有機會進行清理等。在通過Wix管理的自定義操作進行安裝之前,優雅地關閉應用程序
該應用程序是在系統托盤中運行的WinForms應用程序。主窗體有一個標題,比如說「mainwindow」,但隱藏並且有ShowInTaskbar = false。
通過一些不同的測試應用程序試圖Process.Kill() Process.CloseMainWindow() FindWindow, SendMessage, PostMessage
等玩弄我發現,對我來說,做到這一點的最好辦法是使用PostMessage
var hWnd = FindWindow(null, "mainwindowtitle");
PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
這樣我可以覆蓋OnFormClosing並執行任何清除我需要。這從我扔在一起的測試應用程序工作正常。問題是在WiX安裝程序中運行時無法正常工作。我有一個c#自定義操作CA.dll和安裝程序明確調用自定義操作 - 我可以看到從msiexec日誌,如果我將自定義操作代碼更改爲Process.Kill()
它確實停止應用程序正確。但是,當它與PostMessage
代碼一起運行時,應用程序不會關閉,並且OnFormClosing也不會被調用。
這裏是我的CustomAction代碼
private const int WM_CLOSE = 0x0010;
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[CustomAction]
public static ActionResult CloseApplicationGracefully(Session session)
{
session.Log("Starting the CloseApplicationGracefully Custom Action - attempting to stop DUC.");
var hWnd = FindWindow(null, "mainwindowtitle");
session.Log("Window handle found: " + hWnd);
bool result = PostMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
session.Log("Result of calling app to close: " + result);
if (result)
{
return ActionResult.Success;
}
return ActionResult.Failure;
}
這裏是WX設置代碼
<Binary Id="WixCustomAction.dll"
SourceFile="$(var.WixCustomAction.TargetDir)$(var.WixCustomAction.TargetName).CA.dll" />
<CustomAction Id="WixCustomAction"
BinaryKey="WixCustomAction.dll"
DllEntry="CloseDeploymentUpdater" />
<InstallExecuteSequence>
<Custom Action="WixCustomAction" After="FindRelatedProducts"></Custom>
</InstallExecuteSequence>
我曾嘗試調用不同的序列這個自定義操作,但沒有運氣... 的代碼工作一個測試程序應用程序和自定義操作在我使用Process.Kill時起作用,但在放入自定義操作時代碼不起作用 - 必須是事件序列?
編輯
使用WixCloseApplications CA作爲一個答案業績低於建議在下面的日誌條目
WixCloseApplications: App: DUC.exe found running, 1 processes, attempting to send close message.
WixCloseApplications: Sending close message to process id 0x1978
WixCloseApplications: Result 0x12
WixCloseApplications: Sending close message to process id 0x1978
WixCloseApplications: Result 0x0
WixCloseApplications: Sending close message to process id 0x1978
WixCloseApplications: Result 0x578
WixCloseApplications: Sending close message to process id 0x1978
WixCloseApplications: Result 0x0
.
.
.
MSI (s) (C8!D4) [15:00:47:985]: PROPERTY CHANGE: Adding WixCloseApplicationsDeferred property. Its value is 'DUC.exe5'.
MSI (s) (C8!D4) [15:00:48:000]: Doing action: WixCloseApplicationsDeferred
.
.
Action 15:00:48: WixCloseApplicationsDeferred.
Action start 15:00:48: WixCloseApplicationsDeferred.
.
.
Action ended 15:00:48: WixCloseApplicationsDeferred. Return value 1.
Action ended 15:00:48: WixCloseApplications. Return value 1.
您是否在自定義操作中嘗試了SendMessage調用而不是PostMessage? –
@Vijay Sirigiri是的 - 我試着SendMessage(使用SC_CLOSE),並再次在我的測試應用程序,但不是從WiX安裝程序。有趣的是,OnFormClosing的EventArgs有一個CloseReason枚舉,並且使用WM_CLOSE的PostMessage使得它看起來像是taskmanager請求關閉的原因,而使用SC_CLOSE的SendMessage使得它看起來像用戶請求關閉。 –
@rene我可以得到一個有效的句柄,但PostMessage的結果是錯誤的,所以它由於某種原因無法正常工作。 MSDN建議不要在PostMessage中使用WM_QUIT。我會嘗試它,看看會發生什麼,但我懷疑在這種情況下OnFormClosing事件不會觸發。 –