Delphi. Запуск чужого приложения из своего сервиса?

Добрый день! Подскажите если сможете как решить следующую задачку. Есть сервис написанный на делфи, сервис должен запустить чужое приложение, пробовал сделать запуск через функции shellexecute и createprocess, приложение запускается (в диспетчере задач видно), но окна приложения нет. Галочку «разрешить взаимодействие с рабочим столом» ставил.
  • Вопрос задан
  • 9787 просмотров
Пригласить эксперта
Ответы на вопрос 4
NekitoSP
@NekitoSP
Сервис — он не от пользователя работает. И при работе сервиса нет такого понятия как «активный» рабочий стол, ведь ни для кого не секрет что можно открывать одновременно несколько учетных записей в данный момет времени, первая допустим основная, локально с компа, а вторая — через RDP, вот и получается что нет «активного» рабочего стола, а есть (скорее всего) список запущенных учетных записей из них уже и надо получать хэндл рабочего стола. Не знаю как вы пропустили этот момент, когда читали про сервисы, но я точно помню что реализовано это именно так. Советую почитать про Сервисы и Драйвера в Windows.
Ответ написан
RomeroMsk
@RomeroMsk
Если задача — запуск на рабочем столе активного пользователя (того, кто смотрит в монитор в данный момент), то можно сделать так:
function WTSGetActiveConsoleSessionId: DWORD; stdcall; external 'Kernel32.dll';
function WTSQueryUserToken(SessionId: DWORD; phToken: pHandle):bool;stdcall;external 'wtsapi32.dll';

if WTSQueryUserToken(WtsGetActiveConsoleSessionID,@hToken) then
begin
	ZeroMemory(@si,SizeOf(si));
	si.cb:=SizeOf(si);
	si.lpDesktop:=nil;
	CreateProcessAsUser(hToken,nil,PANSIChar(FilePath),nil,nil,False,0,nil,nil,si,pi);
	CloseHandle(hToken);
end;

Смысл в том, что начиная с Vista (если не ошибаюсь), запуск приложения в контексте системы весь интерактив возложит в «рабочий стол пользователя SYSTEM».
Но если пользователь залогинится после запуска — окно он не увидит, скорее всего. Решение: циклическая проверка «активности» пользователя в службе и запуск этим способом.
Ответ написан
antoo
@antoo
function ExecAndWait(const FileName,
                     Params: ShortString;
                     const WinState: Word): boolean; export;
var
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
  CmdLine: ShortString;
begin
  { Помещаем имя файла между кавычками, с соблюдением всех пробелов в именах Win9x }
  CmdLine := '"' + Filename + '" ' + Params;
  FillChar(StartInfo, SizeOf(StartInfo), #0);
  with StartInfo do
  begin

    dwFlags := STARTF_USESHOWWINDOW;
    wShowWindow := WinState;
  end;
  Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false,
                          CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
                          PChar(ExtractFilePath(Filename)),StartInfo,ProcInfo);
  { Ожидаем завершения приложения }
  if Result then
  begin
    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
    { Free the Handles }
    CloseHandle(ProcInfo.hProcess);
    CloseHandle(ProcInfo.hThread);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin

  ExecAndWait( 'C:\windows\notepad.exe', '', SW_SHOWNORMAL);
end;
</code>

попробуйте :)
Ответ написан
SegaZero
@SegaZero
галка «взаимодействовать с рабочим столом» в виста и выше попросту не работает. Советую запускать с помощью планировщика задач к примеру: апи? у gunsmoker'a хорошо написано об этом
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы