2009-08-05 24 views
8

Gibt es ein Tool zum Senden (imitieren) einer Windows-Nachricht wie "WM_ENDSESSION" an einen Windows-Dienst?Windows-Nachricht an einen Windows-Dienst senden

ODER

Wie kann ich eine Windows-Nachricht an einen Prozess mit C# schicken?

(Ich weiß nur, C#)

EDIT: Zweck: Im Grunde habe ich einen Bug einen Windows-Dienst debuggen für die Befestigung, die nur auf System heruntergefahren auftritt.

+6

Ich denke, es gehört auf stackoverflow.com –

+0

Irgendwelche Glück damit? – ThePower

Antwort

3

Im Allgemeinen haben Dienste keine Fenster (geschweige denn Nachrichtenpumpen), um eine Windows-Nachricht zu erhalten.

Wenn der Fehler wirklich nur beim Herunterfahren auftritt (im Gegensatz zum Stoppen des Dienstes), kann es sein, dass etwas davon abhängt, dass eine Ressource verschwindet, die nicht ordnungsgemäß behandelt wird (in diesem Fall). der Bugfix könnte sein, um die Dienstabhängigkeiten korrekt einzurichten). Haben Sie versucht, die Remote-Debugging-Tools vor dem Herunterfahren an den Prozess anzuhängen?

Es lohnt sich zu untersuchen, ob das Problem ohne Herunterfahren auftreten kann, beispielsweise wenn der Dienst mit dem Dienststeuerungs-Manager angehalten wird (dies muss programmgesteuert erfolgen, da es sich um ein Debugging-Szenario handelt). Sie können OnStop() in Ihrem Dienst unterbrechen (ich nehme C# an) und beobachten, was passiert.

+0

Ich habe das Gefühl, dass Abhängigkeiten beim Herunterfahren nicht helfen ... aber ich bin mir da nicht sicher. – Rory

0

Ich glaube nicht, dass es ein Werkzeug gibt, um beliebige Nachrichten zu senden, weil jede Nachricht beliebige LPARAM und WPARAM Werte haben kann.

Aber das nützlichste Tool, das Windows-Nachrichten umgibt, ist Spion ++. Spy ++ ist in Visual Studio enthalten und hilft Ihnen zu sehen, welche Nachrichten gesendet werden, Fensterhierarchie und mehr.

Sie können Nachrichten über C# mit der Win32-API SendMessage senden. Sie können den Fensterhandle, nach dem es fragt, mithilfe einer Win32-API wie FindWindow oder FindWindowEx abrufen.

Bearbeiten (um der Bearbeitung der Frage zu entsprechen): Dienste werden beim Herunterfahren automatisch von Windows gestoppt. Um Ihren Fehler zu beheben, müssen Sie den Code des Dienstes ändern, um ihn ordnungsgemäß herunterzufahren.

Edit2: Oder wenn Sie den Dienst stoppen möchten, sollten Sie die Win32 API ControlService über SERVICE_CONTROL_STOP0x00000001 verwenden.

+0

, aber ich muss eine Nachricht an einen Prozess senden, der als Windows-Dienst ausgeführt wird? Wie funktioniert FindWindow in diesem Fall? – devnull

+2

Der Dienst müsste an erster Stelle ein Fenster oder eine Nachrichtenwarteschlange haben, um Nachrichten senden zu können. Je nach Vista-Einstellungen können Sie die Nachricht möglicherweise nicht an einen Dienst senden, der in einer anderen Sitzung ausgeführt wird. Wenn Sie die Kontrolle über den Dienst haben, wäre eine bessere Option Rohre. –

2

Wenn Sie die HWnd eines Fensters haben, können Sie es Nachrichten senden. Die einzige Einschränkung besteht darin, dass Sie keine Nachrichten senden können, die Zeiger wie den Fenstertext enthalten.
Rufen Sie einfach PostMessage() mit dem Wert der HWND und der Nachricht, die Sie senden möchten.
Um das hwnd zu finden, können Sie spy ++ benutzen.

Ich bin mir nicht sicher, wie Sie das alles mit Windows-Diensten verbinden, da Windows-Dienste keine Fenster haben.

1

würde ich empfehlen, Importieren und definieren die folgenden:

[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; 

dann durch 0x1 oder 0x0 senden darstellt wahr oder falsch als wParam Nachricht.

in Ihrem Code So werden Sie verwenden:

PostMessage(HandleToSendTo, WM_ENDSESSION, WM_TRUE, 0); 

Wo HandleToSendTo das Fenster-Handle des Fensters ist es, Ihnen die Nachricht senden möchten.

bearbeiten
Um die Fenster handhaben, wenn Sie es nicht wissen, ich gehe davon aus, dass Sie sie den Titel oder den Namen wissen.Wenn ja, können Sie diese verwenden:

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

Welche über weitere Informationen können in this question.

finden Oder vielleicht

Ich weiß nicht, ob dies ein ähnlicher Griff ist, bezweifle ich, es, aber jemand könnte mich wissen lassen, wenn es ist, aber Sie können ein Prozess-Handle erhalten, was bedeutet, dass Sie den Prozess mit Process.GetProcessesByName ("MyAppName") abrufen konnten; obwohl nicht darauf verlassen, wie ich nicht denke, dass es den Griff bekommen wird, nach dem du suchst. Nur ein Vorschlag.

10

Dienstleistungen sollten ServiceController class

Sie können es verwenden, um zu starten, zu stoppen und die Kommunikation mit Diensten gesteuert.

+2

Diese Antwort hat mein Leben verbessert. – David

0

Ich weiß nicht, ob dies ein ähnlicher Griff ist, ich bezweifle es, aber jemand könnte mich wissen lassen, wenn es ist, aber Sie können einen Prozess behandeln, was bedeutet, dass Sie den Prozess mit Process erhalten konnten. GetProcessesByName ("MyAppName"); obwohl Sie sich nicht darauf verlassen, da ich nicht glaube, dass es das Handle bekommen wird, nach dem Sie suchen. Nur ein Vorschlag.

Eigentlich funktioniert diese Methode ... Sie müssen nur auf die Eigenschaft 'MainWindowHandle' des Prozessobjekts zugreifen. Zum Beispiel ...

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

Überprüfen Sie die Antworten auf How to simulate windows shutdown while debugging?

Dienstleistungen heraus haben ein ‚Ereignis‘ genannt OnShutdown sie abonnieren können, so könnte es sein, das Problem in diesem Code ist. Wenn der Code .net ist, können Sie ihn unterklassifizieren, so dass Sie die geschützte OnShutdown-Methode zum Debuggen aufrufen können. Das Problem könnte aber auch so sein, wie es von anderen vorgeschlagen wird, dass der Dienst Ressourcen erwartet, die nicht verfügbar sind, weil sie bereits geschlossen wurden.

Wenn der Dienst in .net 2.0 geschrieben wurde, beachten Sie, dass der Stop() Befehl nicht automatisch auf einem Dienst aufgerufen wird, wenn die Arbeitsstation heruntergefahren wird! Das ist sehr überraschend und war fixed in .net 3.5, aber wenn Sie .net 2.0 verwenden, müssen Sie Stop() selbst innerhalb OnShutdown() aufrufen.

+0

warum wird das nicht mehr gewählt – Malachi

Verwandte Themen