Мною написана служба. Ее задача состоит в том что бы отлавливать событие когда логинится пользователь (локально или по RDP) и нужно у данного пользователя запустить специальное приложение. Событие служба отлавливает а вот приложение запускается не всегда. Немогу понять в чем дело. CreateProcessAsUser возвращает false, а SysErrorMessage(GetLastError) говорить что процесс был успешно запущен. Вот хочу узать кто нибудь решил данную задачу, или у кого нибудь есть полезные ссылки.
Здравствуйте, dzuyba, Вы писали:
D>Мною написана служба. Ее задача состоит в том что бы отлавливать событие когда логинится пользователь (локально или по RDP) и нужно у данного пользователя запустить специальное приложение. Событие служба отлавливает а вот приложение запускается не всегда. Немогу понять в чем дело. CreateProcessAsUser возвращает false, а SysErrorMessage(GetLastError) говорить что процесс был успешно запущен. Вот хочу узать кто нибудь решил данную задачу, или у кого нибудь есть полезные ссылки.
D>Спасибо.
Для запуска службы требуются права администратора. Если у файла правильно настроем манифест, то UAC запросит разрешение на повышение привилегий, иначе возможно будет описанный Вами эффект.
Здравствуйте, dzuyba, Вы писали:
D>CreateProcessAsUser возвращает false, а SysErrorMessage(GetLastError) говорить что процесс был успешно запущен.
"Так не бывает"(с).
Во всяком случае, я такого не видел никогда. Покажите лучше Ваш код, а также приведите полное сообщение об ошибке, без интерпретации. А лучше — код самой ошибки.
Вообще, данная задача многократно обсуждалась на этом форуме, поиск по CreateProcessAsUser поможет.
Здравствуйте, dzuyba, Вы писали:
D>Мною написана служба. Ее задача состоит в том что бы отлавливать событие когда логинится пользователь (локально или по RDP) и нужно у данного пользователя запустить специальное приложение. Событие служба отлавливает а вот приложение запускается не всегда. Немогу понять в чем дело. CreateProcessAsUser возвращает false, а SysErrorMessage(GetLastError) говорить что процесс был успешно запущен. Вот хочу узать кто нибудь решил данную задачу, или у кого нибудь есть полезные ссылки.
__>Для запуска службы требуются права администратора. Если у файла правильно настроем манифест, то UAC запросит разрешение на повышение привилегий, иначе возможно будет описанный Вами эффект.
Приложение не запускается на Win2003 и там UAC нет
Здравствуйте, Jolly Roger, Вы писали:
JR>Здравствуйте, dzuyba, Вы писали:
D>>CreateProcessAsUser возвращает false, а SysErrorMessage(GetLastError) говорить что процесс был успешно запущен.
JR>"Так не бывает"(с).
JR>Во всяком случае, я такого не видел никогда. Покажите лучше Ваш код, а также приведите полное сообщение об ошибке, без интерпретации. А лучше — код самой ошибки.
JR>Вообще, данная задача многократно обсуждалась на этом форуме, поиск по CreateProcessAsUser поможет.
procedure TCSService.ServiceControlEvent(Sender: TNTService;
const Msg: TMsg);
var ControlCode: DWord;
begin
ControlCode := Msg.message;
if ControlCode = SERVICE_CONTROL_SESSIONCHANGE then
begin
TJrlClientOperationsHelper.InfoEvent(
Format('ServiceControlEvent ControlCode = SERVICE_CONTROL_SESSIONCHANGE ' +
'Msg.lParam = %d, Msg.wParam = %d', [Msg.lParam, Msg.wParam]));
LaunchBatchAgent(Msg.lParam, Msg.wParam, True);
end;
end;
procedure TCSService.LaunchAgent(SessionID, EventType: Integer; DoWaite: Boolean);
var hToken: Cardinal;
si: _STARTUPINFOW;
pi: _PROCESS_INFORMATION;
LSTError: Cardinal;
// siw: _STARTUPINFOW;
// saP: _SECURITY_ATTRIBUTES;
// saT: _SECURITY_ATTRIBUTES;
// sdP: TSecurityDescriptor;
// sdT: TSecurityDescriptor;begin// WTS_SESSION_LOGON = 5if EventType <> 5 then
Exit;
TJrlClientOperationsHelper.WarningEvent('Запуск BatchAgent для сессии=' + IntToStr(SessionID));
if EnableProcessPrivilege(True, SE_TCB_NAME)
{ and EnableProcessPrivilege(True, SE_INCREASE_QUOTA_NAME)
and EnableProcessPrivilege(True, SE_ASSIGNPRIMARYTOKEN_NAME)}then
if WTSQueryUserToken(SessionID, hToken) then
try
ZeroMemory(@si, SizeOf(si));
si.cb := SizeOf(si);
si.lpDesktop := nil;
// Закоментировал для теста, в релизе раскоментировать Disa 2011.03.09
// if DoWaite then
// Sleep(6000);if CreateProcessAsUser(hToken, PWideChar(ExtractFilePath(ParamStr(0)) + 'BatchAgent.exe'),
PWideChar('"' + ExtractFilePath(ParamStr(0)) + 'BatchAgent.exe' + '"'), nil{@saP}, nil{@saT},
False, NORMAL_PRIORITY_CLASS{ 0{CREATE_SUSPENDED}, nil, nil, si, pi) then
begin
TJrlClientOperationsHelper.InfoEvent(Format('Успешный запуск приложения %s',
[ExtractFilePath(ParamStr(0)) + 'BatchAgent.exe']));
end
else
begin// Вот тут ошибка. LSTError = 0; SysErrorMessage = Операция успешно завершена.
LSTError := GetLastError;
TJrlClientOperationsHelper.ErrorEvent(Format('Ошибка запуска %s: %d - %s',
[ExtractFilePath(ParamStr(0)) + 'BatchAgent.exe',
LSTError, SysErrorMessage(LSTError)]));
end;
finally
CloseHandle(hToken);
end
else
TJrlClientOperationsHelper.ErrorEvent('Ошибка получения токена пользователя: ' +
SysErrorMessage(GetLastError))
else
TJrlClientOperationsHelper.ErrorEvent('Ошибка получения привилегии: ' +
SysErrorMessage(GetLastError))
end;
Данный LaunchAgent метод вызывается в службе когда пользователь логиниться в систему (на консоль или в терминал). Вызов CreateProcessAsUser возвращает false и дальше
GetLastError = 0 а SysErrorMessage = Операция успешно завершена
Заметил еще следующее, если раскоментировать Sleep(6000) то все срабатывает нормально, но мне кажеться это не совсем правильное решение.
У кого будут какие мысли.
Здравствуйте, dzuyba, Вы писали:
D>У кого будут какие мысли.
Проверьте две вещи:
Во-первых, в CreateProcessAsUser флаг выставить CREATE_DEFAULT_ERROR_MODE вместо NORMAL_PRIORITY_CLASS
Во-вторых, попробуйте, для проверки, в LaunchAgent SessionID получать через WTSGetActiveConsoleSessionId
Как-то у Вас тут намешано, и имена методов не совпадают, и Msg.message на SERVICE_CONTROL_SESSIONCHANGE почему-то проверяете, и откуда оно приходит, не понятно. Вы уверены, что с нотификацией всё в порядке? Попробуйте получать уведомления через WTSRegisterSessionNotification.
Здравствуйте, Tujh, Вы писали:
T>Во-первых, в CreateProcessAsUser флаг выставить CREATE_DEFAULT_ERROR_MODE вместо NORMAL_PRIORITY_CLASS
Выставил и никаких изменений.
T>Во-вторых, попробуйте, для проверки, в LaunchAgent SessionID получать через WTSGetActiveConsoleSessionId
Зачем мне получать SessionID с помощью WTSGetActiveConsoleSessionId, ведь эта ф-ия вернет идентификатор текущего
прользователя Local System равный 0. А мне нужен идентификатор сессии логиневшегося в данный момент пользователя,
и этот идентификатор приходит в сообщении SERVICE_CONTROL_SESSIONCHANGE в службе когда новый пользователь логинится
Msg.lParam — идентификатор сессии
Msg.wParam — тип события
Здравствуйте, Jolly Roger, Вы писали:
JR>Здравствуйте, dzuyba, Вы писали:
JR>Как-то у Вас тут намешано, и имена методов не совпадают, и Msg.message на SERVICE_CONTROL_SESSIONCHANGE почему-то проверяете, и откуда оно приходит, не понятно. Вы уверены, что с нотификацией всё в порядке? Попробуйте получать уведомления через WTSRegisterSessionNotification.
Просто это моя реализация TNTService службы виндоус вместо стандартной в Delphi. С нотификацией все работает 100% механизм отлажен очень давно. Тем более это стандартный механизм служб получать сообщения SERVICE_CONTROL_SESSIONCHANGE.