Что нового

Запуск программы с графическим интерфейсом как служба в сеансе пользователя.

liond66

Новичок
Сообщения
99
Репутация
1
Версия AutoIt
3.3.14.5
Версия
0.1
Для гарантии, что программа всегда работает, надёжнее всего запускать её как службу.

Но начиная с Windows 7 в Microsoft решили, что всё что запускается как служба, запускается в скрытой нулевой сессии, и графический интерфейс не доступен.

Я решил эту задачу, используя несколько тем с форумов. Кому актуально, читаем дальше.

Здесь используется программа psexec от Microsoft, которая может запускать программы в указанной сессии от имени указанного пользователя. Там автор запускает программу от имени системной учётной записи.

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

Я запускаю cmd.exe и в окне можно проверить, что программа работает от имени пользователя и получает соответствующую пользовательскую среду.

Но функция определения сессии пользователя для меня работала не корректно, и я нашёл другой вариант.

Этот вариант определения сессии пользователя для меня работает корректно после закрытия сессии и повторного входа. Для индикации что сессия готова, я проверяю наличие процесса explorer.exe.

Это решение для запуска исполняемого файла как службы. Полученная служба корректно отрабатывает остановку и перезапуск. Закрывает нашу программу после остановки. Есть возможность записи в журнал. В функцию _Svc_Main вставляем свой код.



Как этим пользоваться.

-скачиваем файлы ServiceExample.au3, Services.au3, ServicesConstants.au3

- в ту же папку записываем файл psexec.exe из скачанного пакета https://download.sysinternals.com/files/PSTools.zip

-в файле ServiceExample.au3 замените в строке 53 –u ХХХХ на имя пользователя и –p XXXX пароль пользователя.

Можно заменить cmd.exe на вашу программу в строке 40, но для проверки я бы оставил как есть.

- компилируем файл ServiceExample.au3

- через командную строку запускаем файл ServiceExample.exe –i Test

Параметр –i указавает, что нужно создать службу.

Второй параметр указывает имя службы, но я так понял, что он не обязателен.

В нашем случае создаётся служба с именем Autoit Service Test.

Заходим в оснастку служб services.msc, находим нашу службу. В свойствах на первой вкладке задаём автоматический запуск. На вкладке “Вход в систему” переключаем на учётную запись пользователя и вводим те же имя пользователя и пароль, записанные в файле ServiceExample.au3.

- запускаем службу.

Проверяйте, пользуйтесь.

И если кто знает напишите:

- как запустить программу в определённой сессии без использования psexec, а силами Autoit?

- другие способы определить, что пользователь выполнил вход в систему и сессия пользователя готова, не через explorer.exe



Спасибо авторам указанных по ссылкам тем:

ilogic, inververs, arcker и Mark Russinovich (psexec.exe).
Сообщение автоматически объединено:
 

Вложения

musicstashall

Новичок
Сообщения
272
Репутация
4
Есть интересная функция для наблюдения за сессиями пользователей:

Код:
; https://docs.microsoft.com/ru-ru/windows/win32/api/wtsapi32/nf-wtsapi32-wtsregistersessionnotification?redirectedfrom=MSDN
Global Const $NOTIFY_FOR_THIS_SESSION = 'NOTIFY_FOR_THIS_SESSION' ; Должны приниматься уведомления только того сеанса, которое включает окно, идентифицированное значением параметра hWnd.
Global Const $NOTIFY_FOR_ALL_SESSIONS = 'NOTIFY_FOR_ALL_SESSIONS' ; Уведомления всех сессий должны приниматься

Global Const $WTS_CONSOLE_CONNECT = 0x1 ; Сеанс, обозначенный lParam, был подключен к консольному терминалу или сеансу RemoteFX.
Global Const $WTS_CONSOLE_DISCONNECT = 0x2 ; Сеанс, обозначенный lParam, был отключен от консольного терминала или сеанса RemoteFX.
Global Const $WTS_REMOTE_CONNECT = 0x3 ; Сеанс, обозначенный lParam, был подключен к удаленному терминалу.
Global Const $WTS_REMOTE_DISCONNECT = 0x4 ; Сеанс, идентифицированный lParam, был отключен от удаленного терминала.
Global Const $WTS_SESSION_LOGON = 0x5 ; Пользователь вошел в сеанс, указанный lParam.
Global Const $WTS_SESSION_LOGOFF = 0x6 ; Пользователь вышел из сеанса, указанного lParam.
Global Const $WTS_SESSION_LOCK = 0x7 ; Сеанс, указанный lParam, заблокирован.
Global Const $WTS_SESSION_UNLOCK = 0x8 ; Сеанс, указанный lParam, разблокирован.
Global Const $WTS_SESSION_REMOTE_CONTROL = 0x9 ; Сеанс, идентифицированный lParam, изменил свой статус удаленного управления. Чтобы определить статус, вызовите GetSystemMetrics и проверьте метрику SM_REMOTECONTROL.
Global Const $WTS_SESSION_CREATE = 0xA ; Зарезервировано для использования в будущем.
Global Const $WTS_SESSION_TERMINATE = 0xB ; Зарезервировано для использования в будущем.

$iGUI = GUICreate()
_WTSRegisterSessionNotification($iGUI, $NOTIFY_FOR_THIS_SESSION)
GUIRegisterMsg($WM_WTSSESSION_CHANGE, '_SysEvent')
_WinAPI_SetProcessShutdownParameters(0x00FF)
_WinAPI_ShutdownBlockReasonCreate($iGUI, 'This application is blocking system shutdown because the saving critical data is in progress.')

Func _WTSRegisterSessionNotification($hWnd, $Notify)
    Local $Ret = DllCall('Wtsapi32.dll', 'bool', 'WTSRegisterSessionNotification', 'HWND', $hWnd, 'DWORD', $Notify)
    Return $Ret[0]
EndFunc

Func _SysEvent($hWnd, $Msg, $wParam, $lParam)

EndFunc

Сообщение автоматически объединено:

Из под пользовательской среды работают только два события $WTS_SESSION_LOCK и $WTS_SESSION_UNLOCK. Возможно в службе будут работать все.
 
Последнее редактирование:
Автор
L

liond66

Новичок
Сообщения
99
Репутация
1
работают только два события $WTS_SESSION_LOCK и $WTS_SESSION_UNLOCK
Я так понимаю, что с этим можно играться, чтобы определить вход в сессию. Я попробую применить из службы. Спасибо.

Проверил. Если запускаю в качестве скрипта, то получаю события Lock - UnLock.
Если запускаю через службу, то ничего не получаю.
Служба запускается в нулевой сессии и не видит события в пользовательской сессии.
Но попытка интересная.
 
Последнее редактирование:

musicstashall

Новичок
Сообщения
272
Репутация
4
Должно работать, иначе просто смысл теряется. Мож я чего-то не до конца реализовал. В скрипте сверху ссылку на статью прикрепил.
И, вероятно, ты регистрировал это событие — $NOTIFY_FOR_ALL_SESSIONS ?
 
Автор
L

liond66

Новичок
Сообщения
99
Репутация
1
Через службу я регистрировал те же события: Lock-UnLock.
Я теоретически понимаю и написал, почему это не работает:
сессия службы ноль, и там не происходят никакие события вплоть до перезагрузки компьютера.
Но ты можешь проверить сам и показать код, если это заработает.
Да и вообще, чем это поможет в данной теме?
Кроме события входа в сессию, важно узнать момент, когда рабочий стол готов, иначе наш GUI отрисовывается не корректно.
Сообщение автоматически объединено:

ты регистрировал это событие — $NOTIFY_FOR_ALL_SESSIONS ?
И может даже стоит проверить это.
 
Верх