C # Eventing через IPC - PullRequest
       37

C # Eventing через IPC

1 голос
/ 09 февраля 2011

Хорошо, вкратце, у меня есть служба Windows, которая обрабатывает Win32_VolumeChangeEvent и регистрирует поступление дисков USB в журнал событий и в базу данных SQL. Дополнительным компонентом этого является скрытый пользовательский интерфейс (WinForms), который загружается во время сеанса пользователя при входе в систему - при этом появляется окно с сообщением, напоминающее пользователям о политике компании в отношении USB-ключей и т. Д. AFAIK, это был лучший путь, поскольку службы не могут дольше работать в интерактивном режиме.

В любом случае ... архитектурно, v1 этой мелочи выполнялся с компонентом пользовательского интерфейса, обрабатывающим сообщения WndProc для вставки устройства, а затем передавал идентификатор устройства через IPC (именованные каналы) в службу, которая обрабатывает методы WMI / запись EventLog (как не все пользователи имеют права локального администратора). Это имело обратную сторону: элемент пользовательского интерфейса был уничтожен и больше не обнаруживал вставки устройства.

Итак, текущая версия такова, что служба обрабатывает Win32_VolumeChangeEvents и получает необходимые данные с устройства, затем регистрирует их в EventLog и SQL. Все отлично и работает отлично. За исключением того, что сейчас я задаюсь вопросом, как лучше всего вызвать пользовательский интерфейс для отображения всплывающего окна.

Я искал вокруг Google и здесь, в поисках идей о событиях через IPC, так что я могу просто подписаться на событие из компонента пользовательского интерфейса и запустить его в сервисе, но я не нахожу ничего, что выскакивает, как быть полезным Я также ограничен .net2, поэтому WCF находится вне поля зрения (хотя я не боюсь p / invoke, если вы хотите пойти по этому пути).

Итак. Как бы вы это сделали? Ссылки, мысли, разговоры, псевдокод, актуальный код ... все ценится. Я пытаюсь придерживаться того, что считаю лучшей практикой, хотя я также считаю, что программирование - это своего рода искусство, и моя лучшая практика может быть чьей-то ужасной историей.

Так ТАК - что бы вы сделали? Дайте мне знать, если мне нужно уточнить:)

Ответы [ 2 ]

3 голосов
/ 09 февраля 2011

В старые добрые времена программирования Windows API мы иногда использовали RegisterWindowMessage для регистрации уникального идентификатора сообщения, который (по-видимому) только наше окно знало, как обрабатывать. Затем мы можем вызвать это окно из другого приложения, вызвав PostMessage с дескриптором окна HWND_BROADCAST, а параметр msg будет тем уникальным значением сообщения. Это прекрасно работает, если все, что вы хотите разделить между процессами, может поместиться в два значения DWORD (wparam и lparam). Совместное использование большего количества данных может быть выполнено, если вы выделите глобальную память и передадите ссылку в качестве одного из параметров.

Это все еще возможно с .NET. Конечно, нет проблем позвонить PostMessage. Что касается обработки сообщения в коде пользовательского интерфейса, вы должны переопределить форму WndProc. См. Как я могу отправлять / получать сообщения Windows между VB6 и c #? для примера.

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

Вы можете пойти по пути именованного события и использовать совместно используемую память (файл отображения памяти) для совместного использования состояния.

Или вы можете установить сокеты, именованные каналы, TcpListener / TcpClient или даже UdpClient. Все должны работать с различной степенью сложности и / или надежности.

1 голос
/ 09 февраля 2011

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

Обновление: после повторного чтения вопроса я думаю, что, возможно, ваш пользовательский интерфейс не получаетСообщения Windows, поэтому вам нужен другой механизм.Почему бы не создать семафор объект синхронизации в сервисе и ждать его в процессе пользовательского интерфейса (в отдельном потоке)?

...