2009-08-05 24 views
8

C'è uno strumento per inviare (imitare) un messaggio di Windows come "WM_ENDSESSION" a un servizio Windows?Invia messaggio Windows a un servizio Windows

O

Come posso inviare un messaggio di Windows per un processo utilizzando C#?

(so solo C#)

EDIT: Scopo: Fondamentalmente ho per eseguire il debug di un servizio di Windows per il fissaggio di un bug che si verifica solo su un sistema chiuso.

+6

Penso che appartenga a stackoverflow.com –

+0

Qualche fortuna con quello? – ThePower

risposta

3

In genere, i servizi non dispongono di finestre (per non parlare delle pompe di messaggi) per ricevere un messaggio di Windows.

Se il bug si verifica realmente solo durante lo spegnimento (al contrario di interrompere il servizio), può accadere che qualcosa dipenda da una risorsa che sta andando via, che non viene gestita correttamente (nel qual caso, la correzione del bug potrebbe essere essere impostare correttamente le dipendenze del servizio). Hai provato a utilizzare gli strumenti di debug remoto per collegarti al processo prima dello spegnimento?

Vale la pena di indagare se è possibile che il problema si verifichi senza arrestare, forse quando si interrompe il servizio con Gestione controllo servizi (non è necessario eseguire questa operazione a livello di programmazione, poiché si tratta di uno scenario di debug), nel qual caso, puoi interrompere il servizio OnStop() nel tuo servizio (sto assumendo C#) e guarda cosa succede.

+0

Ho la sensazione che le dipendenze non siano d'aiuto allo spegnimento ... ma non ne sono sicuro. – Rory

0

Non penso che ci sia uno strumento per inviare messaggi arbitrari perché ogni messaggio può avere valori LPARAM e WPARAM arbitrari.

Ma lo strumento più utile che circonda i messaggi di Windows è spy ++. Spy ++ è incluso in Visual Studio e consente di vedere quali messaggi vengono inviati, gerarchia delle finestre e altro.

È possibile inviare messaggi tramite C# con l'API Win32 SendMessage. È possibile ottenere l'handle della finestra richiesto utilizzando un'API Win32 come FindWindow o FindWindowEx.

Modifica (per abbinare la modifica della domanda): I servizi vengono arrestati automaticamente da Windows all'arresto. Quindi per correggere il tuo bug sembra che tu debba modificare il codice del servizio stesso per chiuderlo correttamente.

Modifica2: O se si desidera interrompere il servizio, è necessario utilizzare l'API Win32 ControlService passando a SERVICE_CONTROL_STOP0x00000001.

+0

ma devo inviare un messaggio a un processo in esecuzione come servizio di Windows? Come funziona FindWindow in questo caso? – devnull

+2

Il servizio dovrebbe avere una finestra in primo luogo o una coda di messaggi per poter inviare messaggi. E a seconda delle impostazioni di Vista, potresti non essere in grado di inviare comunque il messaggio a un servizio che viene eseguito in una sessione diversa. Se hai il controllo del servizio un'opzione migliore sarebbe pipe. –

2

Se si ha la finestra di una finestra, è possibile inviarla messaggi. L'unica limitazione è che non è possibile inviare messaggi contenenti puntatori come l'impostazione del testo della finestra.
Basta chiamare PostMessage() con il valore di hwnd e il messaggio che si desidera inviare.
Per trovare hwnd puoi usare spy ++.

Non sono sicuro di come si collega tutto questo ai servizi Windows poiché i servizi Windows non hanno finestre.

1

Suggerirei Importazione e definire quanto segue:

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

Poi invia attraverso 0x1 o 0x0 che rappresenta vera o falsa, come il messaggio wParam.

Quindi, nel codice, utilizzare:

PostMessage(HandleToSendTo, WM_ENDSESSION, WM_TRUE, 0); 

Dove HandleToSendTo è l'handle di finestra della finestra che si desidera inviare il messaggio.

Modifica
Per ottenere le finestre gestire se non lo sai, sto supponendo che si sa che è il titolo o il nome.Se è così è possibile utilizzare questo:

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

Quali ulteriori informazioni si possono trovare in this question.

O forse

Non so se questa è una maniglia simile, dubito ma qualcuno potrebbe farmi sapere se lo è, ma è possibile ottenere un handle di Process, il che significa che è possibile ottenere il processo utilizzando Process.GetProcessesByName ("MyAppName") ;, anche se non si basa su questo perché non lo faccio pensa che otterrà il comando che cerchi. Solo un suggerimento.

10

I servizi dovrebbero essere controllate utilizzando ServiceController class

si può utilizzare per avviare, arrestare e comunicare con i servizi.

+2

Questa risposta ha migliorato in modo geniale la mia vita. – David

0

Non so se questo è un handle simile, ne dubito, ma qualcuno potrebbe farmi sapere se lo è, ma è possibile ottenere un handle di processo, il che significa che è possibile ottenere il processo utilizzando Process. GetProcessesByName ("MyAppName") ;, anche se non si basano su questo perché non penso che otterrà l'handle che si sta cercando. Solo un suggerimento.

In realtà questo metodo funzionerà ... è sufficiente accedere alla proprietà 'MainWindowHandle' dell'oggetto processo. Per esempio ...

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

controllare le risposte a How to simulate windows shutdown while debugging?

servizi hanno un 'evento' chiamato OnShutdown essi possono sottoscrivere, in modo che possa essere il problema è in quel codice. Se il codice è .net, è possibile creare una sottoclasse in modo che sia possibile chiamare il metodo OnShutdown protetto per eseguire il debug. Ma il problema potrebbe anche essere suggerito da altri che il servizio si aspetta che le risorse siano disponibili e non perché siano già state chiuse.

Inoltre, se il servizio è stato scritto in .net 2.0, notare che il comando Stop() non viene chiamato automaticamente su un servizio quando la workstation viene arrestata! Questo è molto sorprendente ed è stato fixed in .net 3.5, ma se stai usando .net 2.0 devi chiamare Stop() te stesso all'interno di OnShutdown().

+0

perché questo non è più votato – Malachi

Problemi correlati