Казалось, что это было способом Microsoft развивать модель событий со временем. Также кажется, что они также позволяют другому способу сделать это с "новым" делегатом Действия, и это - изменения.
Обычно службы не у меня нет окон (не говоря уже о перекачке сообщений) для получения сообщения Windows.
Если ошибка действительно возникает только при завершении работы (в отличие от простой остановки службы), возможно, что-то зависит от ресурса, который исчезает, что не обрабатывается должным образом (в этом случае исправление ошибки может заключаться в правильной настройке зависимостей служб). Пробовали ли вы использовать инструменты удаленной отладки, чтобы подключиться к процессу перед завершением работы?
Стоит выяснить, можете ли вы заставить проблему возникнуть без завершения работы, возможно, просто остановив службу с помощью диспетчера управления службами (нет необходимости сделать это программно,
Если у вас есть hwnd окна, вы можете отправить это сообщения. Единственное ограничение заключается в том, что вы не можете отправлять сообщения, содержащие указатели, такие как установка текста окна.
Просто вызовите PostMessage ()
со значением hwnd и сообщением, которое вы хотите отправить.
Чтобы найти hwnd, вы можете использовать spy ++.
Я не уверен, как вы подключаете все это к службам Windows, поскольку службы Windows не имеют окон.
Службы должны управляться с помощью Класс ServiceController
Представляет службу Windows и позволяет подключаться к работающей или остановленной службе, управлять ею или получать информацию о ней.
Вы можете использовать его для запуска, остановки и связи со службами, использующими этот класс.
Я бы порекомендовал импортировать и определить следующее:
[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");, хотя не полагайтесь на это, как я не делаю Не думаю, что он получит то, что вам нужно. Просто предложение.
Я не Я думаю, что существует инструмент для отправки произвольных сообщений, потому что каждое сообщение может иметь произвольные значения LPARAM и WPARAM.
Но самый полезный инструмент для работы с сообщениями Windows - это spy ++. Spy ++ включен в Visual Studio и помогает вам видеть, какие сообщения отправляются, иерархию окон и т. Д.
Вы можете отправлять сообщения через C # с помощью Win32 API SendMessage . Вы можете получить запрошенный дескриптор окна, используя Win32 API, например FindWindow или FindWindowEx .
Изменить (чтобы соответствовать редактированию вопроса): службы автоматически останавливаются окнами при завершении работы . Итак, чтобы исправить вашу ошибку, похоже, вам нужно изменить код самой службы, чтобы она должным образом закрылась.
Edit2:
Я не знаю, похожий ли это дескриптор, я сомневаюсь, но кто-то может сообщить мне, если это так, но вы можете получить дескриптор процесса, что означает, что вы можете получить процесс с помощью Process.GetProcessesByName ("MyAppName");, хотя не полагайтесь на это, поскольку я не думаю, что он будет получите ручку, которая вам нужна. Просто предложение.
На самом деле этот метод будет работать ... вам просто нужно получить доступ к свойству MainWindowHandle объекта процесса. Например ...
Process myProcess;
Int handle;
myProcess = Process.GetProcessesByName("MyAppName");
handle = myProcess.MainWindowHandle;