Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过Wix管理的自定义操作在安装前优雅地关闭应用程序_C#_Wix_Pinvoke_Wix3_Custom Action - Fatal编程技术网

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

C# 通过Wix管理的自定义操作在安装前优雅地关闭应用程序,c#,wix,pinvoke,wix3,custom-action,C#,Wix,Pinvoke,Wix3,Custom Action,在我的WiX安装程序中,如果应用程序仍在运行,我希望优雅地关闭即将更新的应用程序。我不想提示用户关闭,也不想终止进程。在关闭应用程序之前,我需要有机会执行一些清理等操作 该应用程序是在系统托盘中运行的WinForms应用程序。主窗体有一个标题,比如说“mainwindow”,但它是隐藏的,并且ShowInTaskbar=false 通过玩一些不同的测试程序,尝试使用Process.Kill()Process.CloseMainWindow()FindWindow、SendMessage、Post

在我的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#Custom Action CA.dll,安装程序肯定会调用自定义操作-我可以从msiexec日志中看到这一点,如果我将自定义操作代码更改为just
Process.Kill()
,它确实会正确停止应用程序。但是,当它使用
PostMessage
代码运行时,应用程序不会关闭,也不会调用OnFormClosing

这是我的自定义操作代码

        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>

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

因此,您需要实现EnumWindows(EnumCallBack,HANDLE processToClose)
在EnumCallBack中,您实际上为每个窗口发送了PostMessage WM_CLOSE。

您是否在自定义操作中尝试了SendMessage调用而不是PostMessage?@Vijay Sirigiri Yep-我尝试了SendMessage(使用SC_CLOSE),这在我的测试程序中再次起作用,但在WiX安装程序中没有。有趣的是,OnFormClosing的EventArgs有一个CloseReason枚举,使用WM_CLOSE的PostMessage使其看起来像是taskmanager请求关闭,而使用SC_CLOSE的SendMessage使其看起来像是用户请求关闭。@我可以得到一个有效的句柄,但PostMessage的结果为false,因此它不起作用出于某种原因,这是正确的。MSDN建议不要在PostMessage中使用WM_QUIT。无论如何,我会尝试一下,看看会发生什么,但我怀疑OnFormClosing事件在这种情况下不会触发。@Peter Kelly你能添加一个对GetLastError的调用并记录结果吗?@rene GetLastError现在返回997查找它…指向CloseApp的源代码很有帮助,但这不是内置CA WixCloseApplication使用的吗?我已经尝试过了,它关闭了应用程序,但没有优雅地关闭,即OnFormClosing事件没有被触发。@Peter Kelly我在想MSI是否在提升运行,或者CA是否被提升。你能发日志吗?msiexec/i[您的msi]/l*vx日志文件。log@rene在使用util:CloseApplication之后,我发布了一些日志条目。延迟的影响是什么?Util:CloseApplication向指定的应用程序窗口发送WM_CLOSE消息。应用程序如何将该消息子类化是该应用程序的问题,而不是WiX的问题。@Christoper Painter我不确定你所说的“将该消息子类化”是什么意思,但如果你认为问题与WiX无关,那么为什么自定义操作在简单的测试程序中可以完美工作,而在WiX调用时却不能?你能提出另一种方法来实现我的目标吗?从WiX优雅地关闭WinForms系统托盘应用程序?感谢
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.