向没有窗口的进程发送WM_CLOSE消息

本文关键字:WM CLOSE 消息 进程 窗口 | 更新日期: 2023-09-27 17:59:15

启动流程-

 ProcessStartInfo psi = new ProcessStartInfo("G:''SampleWinApp.exe");            
 psi.UseShellExecute = false;
 psi.CreateNoWindow = true;            
 Process prcs = Process.Start(psi);

使用PostMessage 发送WM_CLOSE

const int WM_CLOSE = 0x0010;
public void SendCloseSignal(Process proc)
{
    uint uiPid = (uint) proc.Id;
    bool bResult = EnumWindows(new WNDENUMPROC(EnumWindowsProc), uiPid);
    if (!bResult && Marshal.GetLastWin32Error() == 0) {
        object objWnd = processWnd[uiPid];
        if (objWnd != null) {
            IntPtr ptrWnd = (IntPtr) objWnd;
            PostMessage(ptrWnd, WM_CLOSE, 0, 0);
            return;
        }
    }
    foreach (ProcessThread thread in proc.Threads) {
        PostThreadMessage((uint) thread.Id, WM_CLOSE, UIntPtr.Zero, IntPtr.Zero);
    }
}
private static bool EnumWindowsProc(IntPtr hwnd, uint lParam)
{
    uint uiPid = 0;
    if (GetParent(hwnd) == IntPtr.Zero)
    {
        GetWindowThreadProcessId(hwnd, ref uiPid);
        if (uiPid == lParam)
        {
            processWnd[uiPid] = hwnd;
            return false;
        }
    }
    return true;
} 

CreateNoWindow = false启动exe,发送WM_CLOSE消息,应用程序正常关闭。对于CreateNoWindow = true,WM_CLOSE消息永远不会到达客户端。即使是PostThreadMessage似乎也不起作用。有什么方法可以发送WM_CLOSE消息吗?我找了一天的时间来解决这个问题。。没有运气。

编辑:为每个应用程序安装一个windows服务。启动/停止服务启动/停止应用程序。目前,我们在服务停止时终止应用程序。由于这是一种野蛮的杀戮,应用程序不会优雅地消亡。一些应用程序监听CTRL信号。现在,我只需要一些方法来向这些应用程序发送WM_CLOSE消息。

第2版:如果有窗口,WM_CLOSE将触发CTRL_CLOSE_EVENT。但是,当任何进程在CreateNoWindow=true的情况下启动时,这永远不会触发。

向没有窗口的进程发送WM_CLOSE消息

有什么方法可以发送WM_CLOSE消息吗?

CCD_ 3被发送到窗口。如果流程中没有窗口,那么就没有什么可处理的消息。如果您希望关闭一个没有窗口的进程,那么发送WM_CLOSE不是解决方案。

看起来你只是想扼杀进程。当控制台进程具有关联的窗口时,您将使用WM_CLOSE消息来触发CTRL_CLOSE_EVENT信号。

由于CTRL_CLOSE_EVENT已经是一种相当残酷的方法来杀死一个进程,在我看来,你完全有理由简单地杀死它。你已经有了一个Process对象。只需使用Process.Kill()即可杀死它。

另一方面,也许你真正想问的问题是:

如何在另一个进程中向CTRL_CLOSE_EVENT发送信号?

这里可以找到一个相关的问题:我可以向Windows上的应用程序发送ctrl-C(SIGINT)吗?在我看来,最好的答案是Nemo1024,而不是公认的答案。这个答案链接到他的博客文章:http://stanislavs.org/stopping-command-line-applications-programatically-with-ctrl-c-events-from-net/

据我所知,那篇文章应该能为你提供解决问题所需的信息。它列出了四种情况。前两个涉及CCD_ 11作为触发闭合信号的手段。第三是扼杀这个过程。第四个可能就是你想要的。当然,第四种选择是最复杂的。引用自文章:

在这个线程的底部找到一个提示后,我终于咬紧牙关,开始了没有窗口的过程。当需要停止进程时,父进程将其控制台附加到子进程,停止自身侦听Ctrl-C事件,并将事件发布到控制台,从而终止附加的子进程。然后,它为自己恢复Ctrl-C处理程序并释放控制台。