从C#关闭最小化/图标化过程(Closing a minimized/iconized proces

2019-06-25 11:55发布

这是我的问题:我需要关闭的过程,已经在运行,从C#程序。 问题是,这一进程现在运行为一个图标(最小化到任务栏),并且除非用户打开它至少一次(这永远不会在无人值守的机器发生),它永远不会有一个主窗口。

我有另一项要求是,应用程序被关闭杀死 。 我需要它来写它的内存缓冲区写入磁盘 - 和杀害它会导致数据丢失。

这是我试过到目前为止:

        foreach (Process proc in Process.GetProcesses())
        {
            if (proc.ProcessName.ToLower().StartsWith("myapp"))
            {
                if (proc.MainWindowHandle.ToInt32() != 0)
                {
                    proc.CloseMainWindow();
                    proc.Close();
                    //proc.Kill();  <--- not good!
                }
            }
        }

我已经添加了if语句,发现,MainWindowHandle == 0时在窗口最小化后。 卸下如果没有帮助。 无论是CloseMainWindow()还是关闭()工作。 杀()的做法,但如上面提到的-这不是我所需要的。

任何想法将被接受,包括使用晦涩难懂的Win32 API函数:)

Answer 1:

这应该工作:

[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr FindWindow(string className, string windowName);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

private const int WM_CLOSE = 0x10;
private const int WM_QUIT = 0x12;

public void SearchAndDestroy(string windowName) 
{
    IntPtr hWnd = FindWindow(null, windowName);
    if (hWnd == IntPtr.Zero)
        throw new Exception("Couldn't find window!");
    SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}

由于某些窗口不响应WM_CLOSEWM_QUIT可能要代替它。 这些声明应在32位和64位工作。



Answer 2:

如果是在任务栏上,它就会有一个窗口。 还是你的意思,它在任务栏通知区域(也称为系统托盘)? 在这种情况下,它仍然将有一个窗口。

Win32应用程序真的没有一个“主窗口”,除了按照惯例(主窗口是响应WM_DESTROY调用PostQuitMessage,导致消息循环退出的一个)。

随着程序的运行,运行间谍++。 要查找所有进程所拥有的窗口,你应该选择间谍 - 从主菜单>进程。 这将显示进程树。 从那里,你可以深入到线,再到窗口。 这会告诉你该进程有哪些窗口。 记下的窗口类和标题。 有了这些,你可以使用FindWindow函数(或EnumWindows的)找到在未来的窗口句柄。

随着窗口的句柄,您可以发送WM_CLOSE或WM_SYSCOMMAND / SC_CLOSE(相当于点击窗口标题中的“X”)的消息。 这应该会导致程序很好地关闭。

请注意,我从一个Win32点的观点在这里谈论。 您可能需要使用的P / Invoke或其他技巧来得到这个从.NET程序中工作。



Answer 3:

这里有一些答复和澄清:

rpetrich:想你的方法之前,问题是,我不知道窗口名称,它不同于用户到用户,版本的升级-仅仅是exe文件名保持不变。 我只有进程名。 正如你可以在代码中看到的过程中MainWindowHandle以上为0。

罗杰 :是的,我确实意味着任务栏通知区域-感谢澄清。 我需要调用PostQuitMessage。 我只是不知道怎么回事,只给出一个PROCESSS,而不是一个窗口。

克雷格 :我很乐意说明情况:应用程序有一个命令行界面,允许你指定决定它会做何将它保存结果的参数。 在任务栏通知,但一旦它的运行,只有这样,才能阻止它和得到的结果是右键单击它是选择“退出”。

现在,我的用户希望脚本/批处理应用程序。 他们有绝对的一批开始就没有问题(只指定的exe和名称和一堆标志),但后来就死了正在运行的进程。 假设没有一个会改变的过程中提供了一个API运行时停止它(这是相当大),我需要一种方法来人为地将其关闭。

同样,在无人值守的电脑,启动过程中的脚本可以通过任务调度和操作控制程序启动,但没有办法关闭下跌过程。

希望澄清我的情况,并再次感谢大家谁是试图帮助!



Answer 4:

问题阐明你为什么要尝试这样的:如果在过程中唯一的用户界面的系统托盘图标,你为什么要杀死并离开,但运行的进程? 用户如何将访问过程? 而如果机器是“无人值守”,为什么用托盘图标关心自己?



文章来源: Closing a minimized/iconized process from C#