Отправить сообщение Windows в службу Windows - PullRequest
8 голосов
/ 05 августа 2009

Существует ли какой-либо инструмент для отправки (имитации) сообщения Windows, например «WM_ENDSESSION», в службу Windows?

OR

Как я могу отправить сообщение Windows процессу, использующему C #?

(я знаю только C #)

РЕДАКТИРОВАТЬ: Цель: в основном я должен отладить службу Windows для исправления ошибки, которая возникает только при выключении системы.

Ответы [ 7 ]

11 голосов
/ 05 августа 2009

Службы должны контролироваться с использованием Класс ServiceController

Представляет службу Windows и позволяет подключаться к работающей или остановленной службе, манипулировать ею или получать информацию о ней.

Вы можете использовать его для запуска, остановки и связи со службами, использующими этот класс.

4 голосов
/ 06 августа 2009

Как правило, службы не имеют окон (не говоря уже о сообщениях сообщений) для получения сообщения Windows.

Если ошибка действительно возникает только при завершении работы (в отличие от простой остановки службы), возможно, что-то зависит от того, какой ресурс уходит, что не обрабатывается изящно (в этом случае исправление ошибки может быть правильно настроено для служебных зависимостей). Вы пытались использовать инструменты удаленной отладки для подключения к процессу до выключения?

Стоит выяснить, можно ли разрешить возникновение проблемы без выключения, возможно, при простой остановке службы с помощью диспетчера управления службами (нет необходимости делать это программно, так как это сценарий отладки), в этом случае вы может установить точку останова OnStop () в вашем сервисе (я полагаю, C #) и посмотреть, что произойдет.

3 голосов
/ 24 октября 2010

Ознакомьтесь с ответами на Как имитировать выключение Windows при отладке?

Сервисы имеют «событие», называемое OnShutdown, на которое они могут подписаться, поэтому проблема может заключаться в этом коде. Если код .net, вы можете создать его подкласс, чтобы вы могли вызвать защищенный метод OnShutdown для отладки. Но проблема также может заключаться в том, что другие могут предположить, что служба ожидает, что ресурсы будут доступны, а не потому, что они уже закрыты.

Также, если служба была написана на .net 2.0, обратите внимание, что команда Stop () не вызывается автоматически для службы, когда рабочая станция закрывается! Это очень удивительно, и было исправлено в .net 3.5 , но если вы используете .net 2.0, вам нужно самостоятельно вызывать Stop () в OnShutdown ().

2 голосов
/ 05 августа 2009

Если у вас есть окно, вы можете отправлять ему сообщения. Единственным ограничением является то, что вы не можете отправлять сообщения, содержащие указатели, такие как текст настройки окна.
Просто позвоните PostMessage() со значением hwnd и сообщением, которое вы хотите отправить.
Чтобы найти hwnd, вы можете использовать spy ++.

Я не уверен, как вы все это подключаете к службам Windows, поскольку службы Windows не имеют Windows.

1 голос
/ 05 августа 2009

Я бы порекомендовал импортировать и определить следующее:

[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 - дескриптор окна, в которое вы хотите отправить сообщение.

Редактировать
Чтобы получить дескриптор окна, если вы его не знаете, я предполагаю, что вы будете знать, что это заголовок или имя. Если это так, вы можете использовать это:

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

Какую дополнительную информацию можно найти в этом вопросе.

Или, может быть,

Я не знаю, является ли это похожим дескриптором, я сомневаюсь в этом, но кто-то может сообщить мне, если это так, но вы можете получить дескриптор процесса, что означает, что вы можете получить процесс, используя Process.GetProcessesByName (" MyAppName ") ;, хотя и не полагайтесь на это, поскольку я не думаю, что он получит тот дескриптор, который вам нужен. Просто предложение.

0 голосов
/ 01 октября 2009

Я не знаю, является ли это похожим дескриптором, я сомневаюсь в этом, но кто-то может сообщить мне, если это так, но вы можете получить дескриптор процесса, что означает, что вы можете получить процесс, используя Process.GetProcessesByName (" MyAppName ") ;, хотя и не полагайтесь на это, поскольку я не думаю, что он получит тот дескриптор, который вам нужен. Просто предложение.

На самом деле этот метод будет работать ... вам просто нужно получить доступ к свойству MainWindowHandle объекта процесса. Для экземпляра ...

Process myProcess;
Int handle;
myProcess = Process.GetProcessesByName("MyAppName");
handle = myProcess.MainWindowHandle;
0 голосов
/ 05 августа 2009

Я не думаю, что есть инструмент для отправки произвольных сообщений, потому что каждое сообщение может иметь произвольные значения LPARAM и WPARAM.

Но наиболее полезным инструментом для сообщений Windows является шпион ++. Spy ++ входит в состав Visual Studio и помогает увидеть, какие сообщения отправляются, иерархию окон и многое другое.

Вы можете отправлять сообщения через C # с помощью SendMessage Win32 API. Вы можете получить дескриптор окна, которое он запрашивает, используя Win32 API, например FindWindow или FindWindowEx .

Редактировать (в соответствии с редактированием вопроса): Службы автоматически закрываются окнами при завершении работы. Таким образом, чтобы исправить ошибку, похоже, вам нужно изменить код самой службы, чтобы она корректно закрылась.

Edit2: или, если вы хотите остановить службу, вы должны использовать Win32 API ControlService , передавая SERVICE_CONTROL_STOP 0x00000001.

...