Как установить «взаимодействовать с рабочим столом» в установщике службы Windows - PullRequest
6 голосов
/ 28 июля 2010

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

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 - и графический интерфейс не отображается!Так что, если я остановлю службу, перепроверьте и запустите ее снова - бинго!все начинается и показывается.Второй способ достижения результата - перезагрузка - после этого также отображается графический интерфейс.

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

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

Ответы [ 3 ]

5 голосов
/ 09 марта 2012
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();
            }


        }
2 голосов
/ 10 января 2013

То же, что и Хейса, но с 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: метод изменения службы () для описания параметров.

2 голосов
/ 29 июля 2010

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...