Как получить идентификатор сеанса текущего зарегистрированного пользователя? - PullRequest
4 голосов
/ 07 июля 2010

Я запускаю процесс изнутри службы Windows, используя

ProcessStartInfo processStartInfo = new ....
Process.Start(processStartInfo);

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

Мне действительно нужно запустить приложение, вызывающее его из службы, и мне действительно нужно увидетьокно приложения.

Помогите мне, пожалуйста.

UPD.Что ж, вы используете перегруженную версию Process.Start, которая принимает имя пользователя, пароль и домен - она ​​вытащит программу на рабочий стол.Но теперь оно запускает приложение под одной учетной записью, но показывает это на рабочем столе другого пользователя.Как получилось?

UPD2: У меня есть идея!Я могу использовать psexec.exe из Sysinternals Suite.Но проблема в том, что мне нужно начинать эту вещь молча "как администратор".И я не знаю как.Я имею в виду, даже если у вас уже есть права администратора, иногда вы должны вручную сказать «запустить от имени администратора», подтвердить UAC и только после этого вы готовы к работе.Я не знаю, как тихо запустить что-то, не принося UAC вещь ....

UPD3: Дорогой Господь.У меня есть эта вещь!Наконец.

Хорошо.В начале проблема действительно была в сеансе 0, что-то изолированное.Поэтому мне нужно было создать промежуточное приложение, которое можно запустить из службы, а затем это приложение, в свою очередь, предполагает запустить мое приложение через RPC и перенести его на рабочий стол.Вместо создания приложения среднего уровня я решил использовать инструмент psexec (в любом случае он работает именно так, как мне нужно - через RPC).И когда я пытался использовать этот инструмент под учетной записью LOCAL SYSTEM, он почему-то не работал.И тогда я понял - причина в том, что это чертовски всплывающее диалоговое окно EULA, которое MS помещает в каждый отдельный pstool, и было невозможно нажать кнопку, чтобы подтвердить диалог под учетной записью локальной системы.Поэтому решение состоит в том, чтобы создать ключ в реестре HKU.DEFAULT \ Software \ Sysinternals \ PsExec со значением DWORD EulaAccepted = 1

Ура, теперь это работает!НО!Теперь мне нужно вывести программу на экран текущего зарегистрированного пользователя.Для этого мне понадобится идентификатор сессии!

Итак, вопрос: как получить идентификатор сеанса текущего зарегистрированного пользователя?А что будет, если еще никто не вошел?Какой идентификатор сессии это будет?

UPD4: Вот и все!Я получил это!

[DllImport ("Kernel32.dll", EntryPoint = "WTSGetActiveConsoleSessionId")] public static extern int WTSGetActiveConsoleSessionId ();

Спасибо, ребята!

Ответы [ 4 ]

3 голосов
/ 04 сентября 2010

Вы можете получить активный идентификатор сеанса консоли, используя WTSGetActiveConsoleSessionId (из API служб терминалов).Вы можете использовать его только для WinXP / Win2K3 или выше, но это должно быть хорошо, так как вы можете жестко кодировать 0 для идентификатора сеанса на Win2K или более ранней версии.Вот подпись PInvoke для него:

[DllImport("Kernel32.dll", SetLastError = true)]
[return:MarshalAs(UnmanagedType.U4)]
public static extern int WTSGetActiveConsoleSessionId ( );

Что касается запуска процесса в сеансе пользователя, вы можете сослаться на ответ, который я дал здесь .Это в основном включает вызов четырех API;WTSGEtConsoleSessionId, WTSQueryUserToken, DuplicateTokenEx, затем CreateProcessAsUser, и он будет работать на любой машине с WinXP / Win2K3 или выше.

3 голосов
/ 07 июля 2010

Одним из решений было бы использование третьего процесса в качестве посредника и указание ему запускать приложения через RPC / именованные каналы.

Процессы:

  • Служба Windows
  • Посредническое заявление
  • Приложение, которое вы хотите запустить

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

Затем, когда служба Windows хочет запустить приложение, она находит и открывает конечную точку (именованный канал, конечная точка WCF) и отправляет сообщение для запуска приложения. Затем промежуточное приложение заботится о бизнесе, запускающем процесс, и не имеет никаких ограничений, которые имеет служба Windows.

Сделайте так, чтобы этот посреднический процесс начинался с входа в систему, и все готово.

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

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

Это можно сделать без промежуточного процесса, но для этого требуется более 500 строк кода. По сути, вы хотите запустить второй процесс как текущий вошедший в систему пользователь. Для Vista / 7 у этого пользователя будет свой собственный процесс winlogon, а для XP у него будет процесс проводника. Необходимо получить основной токен, блок среды, атрибуты безопасности и атрибуты безопасности потока этого запущенного процесса, а затем вызвать функцию API Windows CreateProcessAsUser со всей этой информацией, убедившись, что вы также выбрали правильную станцию ​​окна (обычно «WinSta0 \ Default»). «). Это все выполнимо, но вы могли бы лучше провести время с другим предложением второго процесса и IPC.

1 голос
/ 07 июля 2010

Если вы попробуете это на чем-то более новом, чем WindowsXP, это не сработает.Это происходит из-за новой функции, представленной в Vista / Windows 7, которая называется Сеанс 0 изоляции.http://msdn.microsoft.com/en-us/library/bb756986.aspx Вы не сможете запустить приложение, запущенное службой, для отображения на рабочем столе пользователя.

...