从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来阻止它在运行时(这是相当古老的),我需要一种方法来人为关闭它。

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

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

+0

我知道这个问题已经超过六年了,但是您是否曾经找到过C#解决方案?我最终使用了一种名为AutoIt的脚本语言,它拥有一个ProcessClose函数,它不会“杀死”它,但并未将它与C#结合在一起。 – 2014-11-23 03:39:45

如果它在任务栏上,它就会有一个窗口。或者你的意思是它在任务栏通知区域(又名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位。

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