从C#关闭最小化/图标化进程#
这是我的问题:我需要从C#程序关闭已经运行的进程。 问题是,该过程现在作为一个图标运行(最小化为任务栏),并且除非用户至少打开一次(这绝不会在无人值守的机器上发生),否则它永远不会有主窗口 。从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!
}
}
}
我已经添加了如果条款,发现,MainWindowHandle == 0当被最小化窗口后。删除如果没有帮助。 CloseMainWindow()也不是Close()工作。 ()杀()确实,但如上所述 - 这不是我所需要的。
任何想法将被接受,包括使用晦涩难懂的Win32 API函数:)
首先,请允许我感谢所有在这里回答的人,甚至读过这个问题。我相信堆栈溢出将成为像我们这样的人的一个伟大的网站。这里有一些答复和澄清:
rpetrich: 想你的方法之前,问题是,我不知道窗口名称,它不同于用户到用户,版本的升级 - 仅仅是exe文件名遗体不变。我所拥有的就是进程名称。正如你可以在这个过程中的MainWindowHandle上面的代码中看到的是0
罗杰: 是的,我确实意味着任务栏通知区域 - 感谢澄清。 I 需要来调用PostQuitMessage。我只是不知道如何,只有一个流程,而不是一个窗口。
克雷格: 我会很高兴来说明情况:应用程序有一个命令行界面,允许你指定决定它会做何将它保存结果的参数。但一旦运行,停止它并获得结果的唯一方法是在托盘通知中右键单击它并选择“退出”。
现在我的用户想要脚本/批处理应用程序。他们完全没有问题,从批处理开始(只需指定exe名称和一堆标志),但却被一个正在运行的进程卡住了。假设没有人会改变这个过程来提供一个API来阻止它在运行时(这是相当古老的),我需要一种方法来人为关闭它。
同样,在无人值守的电脑,启动过程中的脚本可以通过任务调度或操作启动控制程序,但没有办法关闭下跌过程。
。希望澄清我的情况,并再次感谢大家谁是试图帮助!
如果它在任务栏上,它就会有一个窗口。或者你的意思是它在任务栏通知区域(又名SysTray)?在这种情况下,它仍然会有一个窗口。
Win32应用程序并没有真正的“主窗口”,除了约定(主窗口是调用PostQuitMessage来响应WM_DESTROY,导致消息循环退出的窗口)。
程序运行时,运行Spy ++。要查找进程拥有的所有窗口,您应该从主菜单中选择Spy - > Processes。这将显示一个进程树。从那里,你可以钻取到线程,然后到窗口。这会告诉你该进程有哪些窗口。记下窗口类和标题。有了这些,您可以使用FindWindow(或EnumWindows)来查找将来的窗口句柄。
随着窗口句柄,可以发送一个或WM_CLOSE WM_SYSCOMMAND/SC_CLOSE(相当于单击上的窗口标题的“X”)消息。这应该导致程序很好地关闭。
请注意,我在这里从Win32的观点谈论。您可能需要使用P/Invoke或其他技巧才能使其从.NET程序中运行。
这应该工作:
[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_CLOSE
回应,WM_QUIT
可能要代替它。这些声明应该适用于32位和64位。
问题阐明你为什么要尝试这样的:如果在过程中唯一的用户界面的系统托盘图标,你为什么会想杀死和,但离开的过程中运行?用户将如何访问该进程?如果机器“无人值守”,为什么要关注托盘图标?
我知道这个问题已经超过六年了,但是您是否曾经找到过C#解决方案?我最终使用了一种名为AutoIt的脚本语言,它拥有一个ProcessClose函数,它不会“杀死”它,但并未将它与C#结合在一起。 – 2014-11-23 03:39:45