2009-08-05 151 views
8

是否有任何工具發送(模仿)Windows消息如'WM_ENDSESSION'到Windows服務?發送Windows消息到Windows服務

OR

我怎麼能發送窗口消息,使用C#的過程?

(我只知道C#)

編輯:目的:基本上我有調試Windows服務用於固定僅發生在關閉系統的錯誤。

+6

我認爲它是屬於stackoverflow.com – 2009-08-05 13:29:30

+0

任何運氣呢? – ThePower 2009-08-06 11:59:19

回答

3

通常,服務沒有窗口(更不用說消息泵)來接收Windows消息。

如果錯誤確實只發生在關機(而不是僅僅停止服務)上,可能會出現這樣的情況:某些東西依賴於正在消失的資源,而這些資源沒有得到正常處理(在這種情況下,錯誤修復程序可能是正確設置服務依賴關係)。您是否嘗試過使用遠程調試工具在關機之前附加到進程?

這是值得研究,如果你能得到要發生的問題,而無需關閉,也許當剛剛與服務控制管理器停止服務(無需編程方式做到這一點,因爲這是一個調試的情況),在這種情況下,你可以在你的服務中斷點OnStop()(我假設C#)並觀察發生了什麼。

+0

我有一種感覺,依賴關係不能幫助關閉......但我不確定這一點。 – Rory 2010-10-24 16:42:01

0

我不認爲有一種工具可以發送任意消息,因爲每條消息都可以具有任意的LPARAM和WPARAM值。

但圍繞windows消息的最有用的工具是spy ++。 Spy ++包含在Visual Studio中,可幫助您查看發送的消息,窗口層次結構等。

您可以使用SendMessage Win32 API通過C#發送消息。您可以通過使用Win32 API(如FindWindowFindWindowEx)來獲得它要求的窗口句柄。

編輯(以匹配問題的編輯):服務在關機時自動停止。所以要修復你的bug,聽起來你需要修改服務本身的代碼來正確關閉。

Edit2:或者,如果你想停止服務,你應該使用Win32 API ControlService傳入SERVICE_CONTROL_STOP0x00000001

+0

但我必須將消息發送到作爲Windows服務運行的進程? FindWindow在這種情況下如何工作? – devnull 2009-08-05 13:24:54

+2

該服務必須首先有一個窗口或消息隊列才能發送消息。根據Vista設置,您可能無法將消息發送到在不同會話中運行的服務。如果你有服務的控制權,更好的選擇是管道。 – 2009-08-05 13:26:59

2

如果你有一個窗口的hwnd,你可以發送消息。唯一的限制是您無法發送包含設置窗口文本等指針的消息。
只需撥打PostMessage(),使用hwnd的值和您要發送的消息。
要找到hwnd,你可以使用spy ++。

我不知道你怎麼樣,因爲Windows服務連接這一切的Windows服務沒有窗戶。

1

我會建議導入和定義如下:

[System.Runtime.InteropServices.DllImportAttribute("user32.dll")] 
public static extern bool PostMessage(IntPtr handleWnd, UInt32 Msg, Int32 wParam, Int32 lParam); 

const int WM_ENDSESSION = 0x0016, 
      WM_TRUE = 0x1, 
      WM_FALSE = 0x0; 

然後通過爲0x1或爲0x0發送代表真或假的消息的wParam。

因此,在你的代碼,你將使用:

PostMessage(HandleToSendTo, WM_ENDSESSION, WM_TRUE, 0); 

哪裏HandleToSendTo是你想將消息發送到窗口的窗口句柄。

編輯
獲得Windows處理,如果你不知道吧,我假設你會知道它的名稱或者姓名。如果是這樣你可以使用這個:

[DllImport("user32.dll", EntryPoint = "FindWindowEx")] 
     public static extern int FindWindowEx(int hwndParent, int hwndEnfant, int lpClasse, string lpTitre); 

哪個更多有關可在this question.

或許

發現我不知道這是一個類似手柄,我懷疑它,但有人可以讓我知道如果它是,但你可以得到一個進程句柄,這意味着你可以使用Process.GetProcessesByName(「MyAppName」)得到進程,儘管不要依賴這個,因爲我沒有認爲它會得到你以後的處理。只是一個建議。

10

服務應使用ServiceController class

你可以用它來啓動,停止,並與服務進行通信來控制。

+2

這個答案極大地改善了我的生活。 – David 2011-03-30 15:51:10

0

我不知道這是一個類似手柄,我對此表示懷疑,但有人可以讓我知道,如果它是,但你可以得到一個進程句柄,這意味着你可以使用進程中取得的過程。 GetProcessesByName(「MyAppName」),儘管不要依賴這個,因爲我不認爲它會得到你以後的句柄。只是一個建議。

實際上這種方法將工作......您只需訪問過程對象的'MainWindowHandle'屬性。對於實例...

Process myProcess; 
Int handle; 
myProcess = Process.GetProcessesByName("MyAppName"); 
handle = myProcess.MainWindowHandle; 
3

退房的答案How to simulate windows shutdown while debugging?

服務有一個「事件」稱爲OnShutdown他們可以訂閱,因此它可能是問題出在該代碼。如果代碼是.net,你可以繼承它,所以你可以調用受保護的OnShutdown方法來調試。但問題也可能如其他人所建議的那樣,服務期望資源可用,這不是因爲它們已經關閉。

此外,如果該服務是以.net 2.0編寫的,請注意,Stop()命令在工作站關閉時不會自動調用服務!這非常令人驚訝,並且是fixed in .net 3.5,但是如果您使用.net 2.0,則需要在OnShutdown()中自己調用Stop()。

+0

爲什麼這不投票更多 – Malachi 2013-10-10 22:01:39