2010-07-28 2 views
5

У меня есть служба Windows, которая работает под системной учетной записью и время от времени запускает некоторые программы (да, да, я знаю, что это плохая практика, но это не моя решение). Мне нужно установить проверку «взаимодействовать с рабочим столом», чтобы увидеть gui этих запущенных программ после установки службы. Я попробовал несколько способов, поставив ниже код в AfterInstall или OnCommited обработчиков событий моего установщика службы:Как установить «взаимодействовать с рабочим столом» в установщике службы windows

ConnectionOptions coOptions = new ConnectionOptions(); 
coOptions.Impersonation = ImpersonationLevel.Impersonate; 

ManagementScope mgmtScope = new System.Management.ManagementScope(@"root\CIMV2", coOptions); 
mgmtScope.Connect(); 

ManagementObject wmiService = new ManagementObject("Win32_Service.Name='" + ServiceMonitorInstaller.ServiceName + "'"); 

ManagementBaseObject InParam = wmiService.GetMethodParameters("Change"); 
InParam["DesktopInteract"] = true; 
ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null); 

или

RegistryKey ckey = Registry.LocalMachine.OpenSubKey(
    @"SYSTEM\CurrentControlSet\Services\WindowsService1", true); 

    if(ckey != null) 
    { 
    if(ckey.GetValue("Type") != null) 
    { 
     ckey.SetValue("Type", ((int)ckey.GetValue("Type") | 256)); 
    } 
    } 

оба этих методы «работы». Они установили чек, но после запуска сервиса он запускает exe - и gui не отображается! Итак, если я остановлю службу, повторите проверку и запустите ее снова - бинго! все начинается и показывается. Второй способ добиться результата - перезагрузка - после этого также отображается gui.

Итак, вопрос: есть ли правильный способ установить «взаимодействовать с настольным компьютером», чтобы он начал работать без переустановки и перезагрузки?

ОС: Windows XP (не пробовал Vista, и 7 еще ...)

+0

попытался использовать команду «sc config» - никак ... –

+0

попытался использовать экспорт winapi с http://www.codeproject.com/KB/vb/WindowsServiceInstall.aspx - без везения ... –

ответ

2

И, наконец, после поиска в Интернете в течение недели - я нашел большой рабочий раствор: http://asprosys.blogspot.com/2009/03/allow-service-to-interact-with-desktop.html

Найдите рабочий стол для запуска. Это может показаться странным, но это не так, как просто, как кажется. С терминалом Услугами и быстрым переключением пользователей там может быть несколько интерактивных пользователей при входе в систему на том же раз. Если вы хотите, чтобы пользователь был , который сейчас сидит на физической консоли , тогда вам повезло, API-интерфейс служб терминалов WTSGetActiveConsoleSessionId получит идентификатор сеанса, в котором вы нуждаетесь. Если потребностей являются более сложными (т.е. вам нужно взаимодействовать с конкретным пользователем на сервере TS или вам нужно имя окна станции в неинтерактивной сессии ) вам необходимо перечислить терминал Серверные сессии с WTSEnumerateSessions и проверьте сеанс для получения необходимой информации с WTSGetSessionInformation.

Теперь вы знаете, с какой сессией вам необходимо связаться , и у вас есть свой идентификатор. Это ключ к всему процессу, с использованием WTSQueryUserToken и идентификатора сеанса , который теперь можно получить токен пользователя, подключенного к целевой сессии . Это полностью смягчает проблему безопасности в «взаимодействовать с рабочим столом» установка, запущенный процесс не будет работает с LOCAL SYSTEM полномочия, но с теми же учетными данными, как пользователь, который уже зарегистрирован на что сессия! No привилегия возвышение.

Использования CreateProcessAsUser и фишку мы извлеченные мы можем запустить процесс в обычном порядке, и его будет работать в целевой сессии с учетными данными целевого пользователя. Там пара предостережений, как lpCurrentDirectory и lpEnvironment должны указывать действительные значения - методы с нормальным разрешением по умолчанию для эти параметры не работают на кросс-сессии запуска. Вы можете использовать CreateEnvironmentBlock для создания стандартного блока по умолчанию для целевого пользователя .

Прилагается исходный код рабочего проекта.

+0

Этот код отлично, но кто-нибудь знает, как указать аргументы при запуске приложения? – 2011-02-22 22:22:54

4
private static void SetInterActWithDeskTop() 
     { 
      var service = new System.Management.ManagementObject(
        String.Format("WIN32_Service.Name='{0}'", "YourServiceName")); 
      try 
      { 
       var paramList = new object[11]; 
       paramList[5] = true; 
       service.InvokeMethod("Change", paramList); 
      } 
      finally 
      { 
       service.Dispose(); 
      } 


     } 
+0

Этот метод работает. Он правильно устанавливает флаг. –

+0

работает хорошо. Вы можете проверить это вручную, чтобы флаг был установлен правильно – Mefhisto1

1

То же, что и Хейса, но с WMI. (Код Powershell, но может быть легко перенесен на C#)

if ($svc = gwmi win32_service|?{$_.name -eq $svcname}) 
{ 
    try { 
     $null = $svc.change($svc.displayname,$svc.pathname,16,1,` 
     "Manual",$false,$svc.startname,$null,$null,$null,$null) 
     write-host "Change made" 
    catch { throw "Error: $_" } 
} else 
{ throw "Service $svcname not installed" } 

См MSDN: Service Change() method для описания паров.

Смежные вопросы