Пишу программу, которая в зависимости от условий, определяемых при запуске, должно инициализироваться и работаеть в 3-х режимах:
1. Как системная служба
2. Как обычное Forms-приложение;
3. Как консольное приложение.
В коде проекта:
if IsInstalling() or IsStartAsService() then
RunAsService()
else
if IsStartAsConsole() or IsStartAsSchedulerTask() then
RunAsConsole()
else
RunAsApplication();
Первый пункт решился при помощи недавнего обсуждения:
http://pda.delphimaster.net/?id=1239772550&n=5&p=2Второй пункт - если ни одно условие не соблюдается;
Третий пункт - если родительский процесс - cmd.exe или планировщик.
С определением запуска из консольного интерпритатора - проблем нет.
function IsStartAsConsole(): Boolean;
begin
ConSDTIn := GetStdHandle(STD_INPUT_HANDLE);
ConSTDOut := GetStdHandle(STD_OUTPUT_HANDLE);
Result := (ConSDTIn <> 0);
end;
А вот с планировщиком - непонятно. Дело в том что в разных версиях виндовс имя родительского процесса приложения, запущенного из-под планировщика, разное (определено опытным путем):
function IsStartAsSchedulerTask(): Boolean;
var
ParentProcess: string;
begin
ParentProcess := ParentProcName;
Result := False;
Result := Result or AnsiSameText(ParentProcName, 'svchost.exe');
Result := Result or AnsiSameText(ParentProcName, 'winlogon.exe');
Result := Result or AnsiSameText(ParentProcName, 'taskeng.exe');
end;
Справочно:
function IsStartAsService(): Boolean;
begin
Result := AnsiSameText(ParentProcName(), 'services.exe');
end;
function ParentProcName: string;
const
ProcessBasicInformation = 0;
var
Info: PROCESS_BASIC_INFORMATION;
dwProcessHandle: dword;
ProcessName: string;
Hndl: THandle;
begin
Result:= 'noname';
dwProcessHandle:= GetCurrentProcess;
if NtQueryInformationProcess(dwProcessHandle, ProcessBasicInformation, @Info, SizeOf(Info), nil) = NO_ERROR
then begin
Hndl:= OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, Info.uInheritedFromUniqueProcessId);
if Hndl <> 0 then
try
SetLength(ProcessName, MAX_PATH);
if GetModuleBaseNameA(Hndl, 0, PChar(ProcessName), MAX_PATH) > 0
then Result:= PChar(ProcessName);
finally
CloseHandle(Hndl);
end;
end;
end;
В связи с вышеперечисленным вопрос: А нетли универсального, достоверного, не зависящего от версии виндовс, способо определения запуска приложения из-под планировщика виндовс (Task Scheduler)?
PS:
Приходит в голову просто при создании задачи использовать аргументы командной строки, и тем самым не использовать автоматическое распознование...
Я понимаю, что в принципе - это самое простое и быстрое решение проблемы :)
Но, тем не менее, интересует сабжевый вопрос...
Спасибо.