Подключение через именованный канал из службы Windows (сеанс # 0) в настольное приложение (сеанс # 1)
С учетом :
– приложение – приложение GUI для рабочего стола (WPF) .NET
– просмотр служб Windows для приложения (также .NET)
Служба Windows периодически «пингирует» приложение, чтобы убедиться, что оно здорово (и если это не winservice, он перезапустит его).
Я собирался реализовать «pinging» через именованные каналы. Чтобы сделать вещи проще, я решил сделать это с WCF. Приложение имеет WCF-сервис (одна операция Ping возвращает что-то). Служба Windows является клиентом для этого WCF-сервиса, периодически вызывает его на основе таймера.
Это все в Windows 7.
Служба Windows работает под управлением LocalService (в сеансе # 0).
Настольное приложение запускается под уже зарегистрированным пользователем (в сеансе # 1).
- Как изящно прекратить процесс?
- Win32 - чтение с stdin с таймаутом
- Как создать изменяемый CDialog в MFC?
- Можно ли использовать std :: basic_string в качестве непрерывного буфера при таргетинге на C ++ 03?
- Delphi - получить, какие файлы открываются приложением
Проблема :
Служба Windows не может видеть конечную точку WCF (с NetNamedPipeBinding), созданную и прослушиваемую в настольном приложении. Это означает, что при вызове через wcf proxy я получаю это исключение: «Конечная точка« net.pipe: // localhost / HeartBeat »не найдена на вашей локальной машине»
Я уверен, что код в порядке, потому что другое настольное приложение (в сеансе # 1) может видеть конечную точку.
Очевидно, здесь я имею дело с некоторыми элементами безопасности для изоляции системных объектов Win32. Но я считаю, что должен быть способ обходных ограничений, с которыми я столкнулся.
Я могу пожертвовать подходом WCF и перейти к исходному NamedPipe.
- Создание экранной клавиатуры
- Системная ошибка. Код: 8. Недостаточно памяти для обработки этой команды
- Как запустить Windows, скомпилированную для PowerPC на современных компьютерах PowerPC без набора инструкций,?
- Ограничивает ли Windows 7 доступ к папкам, как Vista?
- WaitForInputIdle не работает для запуска программной программы mspaint
- Возможно ли программно добавить папки на панель быстрого доступа Windows 10 в окне проводника?
- Windows threading: _beginthread vs _beginthreadex vs CreateThread C ++
- Есть ли эквивалент Windows для fdopen для HANDLE?
Более простым решением может быть использование договора WCF-дуплекса с сервисом Windows, обслуживающим службу WCF. Приложение-клиент будет вызывать операцию в службе для регистрации, когда она запустится. Тогда Ping будет операцией, вызываемой периодически службой в контракте обратного вызова клиента, на который приложение ответит.
Видимость службы работает таким образом, потому что служба Windows может работать с SeCreateGlobalPrivilege, и поэтому объект общей памяти, через который имя канала публикуется службой, может быть создано в пространстве имен Global kernel, видимом для других сеансов. Интерактивные приложения не могут легко получить эту привилегию в Windows7, поэтому службы WCF в таких приложениях возвращаются к публикации канала в пространстве имен Local kernel, видимом только в пределах их собственного сеанса.
Наконец, я нашел решение – напрямую используя Named Pipes из System.IO.Pipes. Похоже, что поддержка WCF в канале поддержки не использует System.IO.Pipes.
Сервер :
using (var pipeServer = new NamedPipeServerStream("mypipe", PipeDirection.Out, 1)) { try { while (true) { // #1 Connect: try { pipeServer.WaitForConnection(); } catch (ObjectDisposedException) { yield break; } if (ae.IsCanceled()) return; // #2: Sending response: var response = Encoding.ASCII.GetBytes(DateTime.Now.ToString()); try { pipeServer.Write(response, 0, response.Length); } catch (ObjectDisposedException) { return; } // #3: Disconnect: pipeServer.Disconnect(); } } finally { if (pipeServer.IsConnected) pipeServer.Disconnect(); } }
Клиент :
using (var pipeClient = new NamedPipeClientStream(".", "mypipe", PipeDirection.In)) { try { try { pipeClient.Connect(TIMEOUT); } catch(TimeoutException ex) { // nobody answers to us continue; } using (var sr = new StreamReader(pipeClient)) { string temp; while ((temp = sr.ReadLine()) != null) { // got response } } } catch(Exception ex) { // pipe error throw; } }