2008-09-21 25 views
2

這是我的問題:我需要從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函數:)

回答

0

首先,請允許我感謝所有在這裏回答的人,甚至讀過這個問題。我相信堆棧溢出將成爲像我們這樣的人的一個偉大的網站。這裏有一些答覆和澄清:

rpetrich: 想你的方法之前,問題是,我不知道窗口名稱,它不同於用戶到用戶,版本的升級 - 僅僅是exe文件名遺體不變。我所擁有的就是進程名稱。正如你可以在這個過程中的MainWindowHandle上面的代碼中看到的是0

羅傑: 是的,我確實意味着任務欄通知區域 - 感謝澄清。 I 需要來調用PostQuitMessage。我只是不知道如何,只有一個流程,而不是一個窗口。

克雷格: 我會很高興來說明情況:應用程序有一個命令行界面,允許你指定決定它會做何將它保存結果的參數。但一旦運行,停止它並獲得結果的唯一方法是在托盤通知中右鍵單擊它並選擇「退出」。

現在我的用戶想要腳本/批處理應用程序。他們完全沒有問題,從批處理開始(只需指定exe名稱和一堆標誌),但卻被一個正在運行的進程卡住了。假設沒有人會改變這個過程來提供一個API來阻止它在運行時(這是相當古老的),我需要一種方法來人爲關閉它。

同樣,在無人值守的電腦,啓動過程中的腳本可以通過任務調度或操作啓動控制程序,但沒有辦法關閉下跌過程。

。希望澄清我的情況,並再次感謝大家誰是試圖幫助!

+0

我知道這個問題已經超過六年了,但是您是否曾經找到過C#解決方案?我最終使用了一種名爲AutoIt的腳本語言,它擁有一個ProcessClose函數,它不會「殺死」它,但並未將它與C#結合在一起。 – 2014-11-23 03:39:45

1

如果它在任務欄上,它就會有一個窗口。或者你的意思是它在任務欄通知區域(又名SysTray)?在這種情況下,它仍然會有一個窗口。

Win32應用程序並沒有真正的「主窗口」,除了約定(主窗口是調用PostQuitMessage來響應WM_DESTROY,導致消息循環退出的窗口)。

程序運行時,運行Spy ++。要查找進程擁有的所有窗口,您應該從主菜單中選擇Spy - > Processes。這將顯示一個進程樹。從那裏,你可以鑽取到線程,然後到窗口。這會告訴你該進程有哪些窗口。記下窗口類和標題。有了這些,您可以使用FindWindow(或EnumWindows)來查找將來的窗口句柄。

隨着窗口句柄,可以發送一個或WM_CLOSE WM_SYSCOMMAND/SC_CLOSE(相當於單擊上的窗口標題的「X」)消息。這應該導致程序很好地關閉。

請注意,我在這裏從Win32的觀點談論。您可能需要使用P/Invoke或其他技巧才能使其從.NET程序中運行。

2

這應該工作:

[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位。

0

問題闡明你爲什麼要嘗試這樣的:如果在過程中唯一的用戶界面的系統托盤圖標,你爲什麼會想殺死和,但離開的過程中運行?用戶將如何訪問該進程?如果機器「無人值守」,爲什麼要關注托盤圖標?

相關問題