gpt4 book ai didi

c# - 在通过 Wix 管理的自定义操作安装之前优雅地关闭应用程序

转载 作者:行者123 更新时间:2023-11-30 17:19:23 25 4
gpt4 key购买 nike

在我的 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.

最佳答案

如果正确理解 Wix 的 CloseApp CustomAction,您应该枚举进程中的所有窗口。

http://wix.codeplex.com/SourceControl/changeset/view/175af30efe78#src%2fca%2fwixca%2fdll%2fCloseApps.cpp

所以你需要实现一个 EnumWindows(EnumCallBack, HANDLE processToClose)在 EnumCallBack 中,您实际上为每个窗口发布消息 WM_CLOSE。

关于c# - 在通过 Wix 管理的自定义操作安装之前优雅地关闭应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4933645/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com