Запуск интерактивного приложения .Net winforms из службы - PullRequest
1 голос
/ 19 февраля 2009

Среда - VS2008, Vista SP1.

Я написал службу управления процессами, которая может запускать приложения либо в сеансе 0, либо на интерактивной консоли (обычно 1). Обратите внимание, что это НЕ нормальный режим работы, он предназначен только для внутренней отладки. В полевых условиях эти процессы будут надежно скрыты в сеансе 0. Проблемы безопасности не применяются.

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

Я использую следующий код для этого:

ZeroMemory (&sui, sizeof(STARTUPINFO));
sui.cb = sizeof (STARTUPINFO);
sui.wShowWindow = pTask->GetWinStartState() ;
sui.dwFlags     = STARTF_USESHOWWINDOW ;
ZeroMemory (&pi,sizeof(pi));

if (bInteractive)
{
   HANDLE  hToken = NULL;
   DWORD dwSessionId = WTSGetActiveConsoleSessionId();
   WTSQueryUserToken (dwSessionId, &hToken);
   sui.lpDesktop = TEXT("winsta0\\default"); 
   LPVOID  pEnv = NULL;
   DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
   HMODULE hModu = LoadLibrary(TEXT("Userenv.dll"));

   if (hModu )
   {
      if (CreateEnvironmentBlock (&pEnv, hToken, FALSE))
         dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;    
      else
         pEnv = NULL;
   }

   bCreatedOk = CreateProcessAsUser (hToken,
                                     NULL,
                                     (LPTSTR)(pTask->GetExeName()),
                                     NULL,
                                     NULL,
                                     FALSE,
                                     dwCreationFlag,
                                     pEnv,
                                     NULL,
                                     &sui,
                                     &pi);
}
else
{
   bCreatedOk = CreateProcess (NULL, ... blah...);
}

Все это прекрасно работает, и я могу запускать и отслеживать собственные процессы как в сеансе службы Vista, так и в консоли. Отлично. Торты и эль для всех.

Так вот в чем проблема. Если я попытаюсь запустить приложение winforms (C #) в интерактивном режиме, то вот, похоже, что оно запускается, отображается в Process Explorer как работающее в сеансе 1, но на рабочем столе ... nada Окно не появляется вообще. Процесс запускается и выключается все нормально, но окно никогда не появляется. Точно такой же winform exe, запускаемый из explorer, также отображается в сеансе 1, но на этот раз на рабочем столе выглядит просто отлично.

Есть идеи?

Ответы [ 3 ]

1 голос
/ 19 февраля 2009

Несмотря на очевидную истерию, нет ничего плохого в запуске приложения из службы в интерактивном сеансе при условии, что оно выполнено с теми же привилегиями, что и у интерактивного пользователя или ниже . Поскольку вы запускаете как интерактивный пользователь, повышение привилегий не может быть.

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

0 голосов
/ 19 февраля 2009

Похоже, вы пытаетесь нарушить изоляцию сеанса. Как сказал Мистер Мэн, я не думаю, что это правильно.

http://support.microsoft.com/?scid=kb%3Ben-us%3B165194&x=5&y=3 может быть полезно, если вы действительно хотите это сделать. В этом примере кода они, кажется, инициализируют больше вещей, чем вы.


РЕДАКТИРОВАТЬ Если это для целей отладки, вступление i-e VS 2008, просто добавьте цикл ожидания в начале и запустите VS с правами администратора. Вы можете подключиться к процессу обслуживания, не сталкиваясь с системной изоляцией.

0 голосов
/ 19 февраля 2009

Одним словом "не надо".

Сервисы обычно работают с ограниченными привилегиями, а НЕ как текущий пользователь. Таким образом, в Vista + им запрещено взаимодействовать с рабочим столом пользователя. Вдобавок ко всему, службы получают нулевую оконную станцию.

Раньше вы имели возможность установить флажок, на котором было написано что-то вроде «Разрешить взаимодействие с рабочим столом», но больше нет. Это плохая практика.

Лучше всего создать вспомогательное приложение, которое запускается в контексте пользователя и взаимодействует со службой через именованный канал, LRPC или сокет, а затем попросите вспомогательное приложение запустить программу для пользователя. Так работает большинство антивирусов.

Кроме того, прочитайте этот технический документ от Microsoft по этому вопросу. Службы не могут работать ни в чем, кроме сеанса 0.

ПРИМЕЧАНИЕ: небольшое исследование показывает, что вам нужно дублировать токен, используя что-то вроде этого:

DuplicateTokenEx(hTokenNew,MAXIMUM_ALLOWED,NULL,
    SecurityIdentification,TokenPrimary,&hTokenDup);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...