2009-08-05 26 views
8

Windowsサービスに「WM_ENDSESSION」のようなWindowsメッセージを(模倣して)送信するツールはありますか?WindowsサービスにWindowsメッセージを送信する

または

どのようにC#を使用してプロセスにWindowsメッセージを送信できますか?

(私はC#のを知っている)

EDIT:目的:基本的に私は唯一のシャットダウンシステム上で発生するバグを固定するためのWindowsサービスをデバッグする必要があります。

+6

私はそれがstackoverflow.comに属していると思います –

+0

これで運がいいですか? – ThePower

答えて

3

一般に、サービスには、ウィンドウメッセージを受信するためのウィンドウ(メッセージポンプはもちろん)がありません。

バグが本当にシャットダウン時(サービスを停止するだけではなく)に起こった場合、何かが離れているリソースに依存している場合があります。このリソースは正常に処理されていません(その場合、バグ修正は、サービスの依存関係を正しく設定することができます)。シャットダウンする前にリモートデバッグツールを使用してプロセスにアタッチしようとしましたか?

シャットダウンせずに問題が発生する可能性があるかどうかを調べることは価値があります。サービスコントロールマネージャーを使用してサービスを停止するだけです(これはプログラム的に行う必要はありません)サービス(私はC#を想定しています)でOnStop()をブレークポイントして何が起こるのかを見ることができます。

+0

シャットダウン時に依存関係が助けにならないと感じていますが、それについては分かりません。 – Rory

0

各メッセージに任意のLPARAMとWPARAMの値を設定できるので、任意のメッセージを送信するツールはないと思います。

しかし、Windowsメッセージを囲む最も有用なツールはspy ++です。 Spy ++はVisual Studioに含まれており、送信されるメッセージ、ウィンドウの階層などを確認するのに役立ちます。

SendMessage Win32 APIを使用してC#経由でメッセージを送信できます。 FindWindowまたはFindWindowExのようなWin32 APIを使用して、要求されたウィンドウハンドルを取得できます。

編集(質問の編集と一致するように):サービスは、シャットダウン時に自動的にウィンドウによって停止されます。だからあなたのバグを修正するには、サービス自体のコードを修正して、適切にシャットダウンする必要があるように思えます。

Edit2:またはサービスを停止する場合は、 0x00000001を渡すWin32 API ControlServiceを使用する必要があります。

+0

しかし、私はWindowsサービスとして実行されているプロセスにメッセージを送信する必要がありますか?この場合、FindWindowはどのように機能しますか? – devnull

+2

サービスは、メッセージを送信できるように最初の場所またはメッセージキューにウィンドウを持つ必要があります。 Vistaの設定によっては、別のセッションで実行されているサービスにメッセージを送信できない場合があります。あなたがサービスのコントロールを持っているなら、より良い選択肢はパイプでしょう。 –

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; 

そして、wParamにメッセージとして真または偽表す0x1のまたは0x0の経由で送信します。

だからあなたのコードの中で、あなたが使用します。

PostMessage(HandleToSendTo, WM_ENDSESSION, WM_TRUE, 0); 

HandleToSendToがあなたにメッセージを送信したいウィンドウのウィンドウハンドルです。

編集
あなたはそれを知っていない場合は、Windowsが扱う取得するには、私はあなたがそれがタイトルや名前を知っているだろうことを仮定しています。私は、これは同様のハンドルであるならば、私は疑うか分からないの詳細については、this question.

それとも

で見つけることができ

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

:もしそうなら、あなたはこれを使用することができます誰かが私に知らせることができますが、Processハンドルを取得できます。つまり、Process.GetProcessesByName( "MyAppName");を使用してプロセスを取得できますが、これに依存しないそれはあなたが後になっているハンドルを取得すると思います。ちょうど提案。

10

サービスを起動、停止およびサービスと通信するために使用することができServiceController class

を使用して制御する必要があります。

+2

この回答はgenuninely私の人生を改善しました。 – David

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

関連する問題