123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- {
- This file is part of the Free Component Library (FCL)
- Copyright (c) 1999-2008 by the Free Pascal development team
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- {$IFDEF FPC_DOTTEDUNITS}
- Uses
- WinApi.Windows;
- {$ELSE FPC_DOTTEDUNITS}
- Uses
- Windows;
- {$ENDIF FPC_DOTTEDUNITS}
- Resourcestring
- SNoCommandLine = 'Cannot execute empty command-line';
- SErrCannotExecute = 'Failed to execute %s : %d';
- { SErrNoSuchProgram = 'Executable not found: "%s"';
- SErrNoTerminalProgram = 'Could not detect X-Terminal program';
- }
- Const
- PriorityConstants : Array [TProcessPriority] of Cardinal =
- (HIGH_PRIORITY_CLASS,IDLE_PRIORITY_CLASS,
- NORMAL_PRIORITY_CLASS,REALTIME_PRIORITY_CLASS);
- procedure TProcess.CloseProcessHandles;
- begin
- if (FProcessHandle<>0) then
- CloseHandle(FProcessHandle);
- if (FThreadHandle<>0) then
- CloseHandle(FThreadHandle);
- end;
- Function TProcess.PeekExitStatus : Boolean;
- begin
- GetExitCodeProcess(ProcessHandle,FExitCode);
- Result:=(FExitCode<>Still_Active);
- end;
- Function GetStartupFlags (P : TProcess): Cardinal;
- begin
- With P do
- begin
- Result:=0;
- if poUsePipes in FProcessOptions then
- Result:=Result or Startf_UseStdHandles;
- if suoUseShowWindow in FStartupOptions then
- Result:=Result or startf_USESHOWWINDOW;
- if suoUSESIZE in FStartupOptions then
- Result:=Result or startf_usesize;
- if suoUsePosition in FStartupOptions then
- Result:=Result or startf_USEPOSITION;
- if suoUSECOUNTCHARS in FStartupoptions then
- Result:=Result or startf_usecountchars;
- if suoUsefIllAttribute in FStartupOptions then
- Result:=Result or startf_USEFILLATTRIBUTE;
- end;
- end;
- Function GetCreationFlags(P : TProcess) : Cardinal;
- begin
- With P do
- begin
- Result:=0;
- if poNoConsole in FProcessOptions then
- Result:=Result or Detached_Process;
- if poNewConsole in FProcessOptions then
- Result:=Result or Create_new_console;
- if poNewProcessGroup in FProcessOptions then
- Result:=Result or CREATE_NEW_PROCESS_GROUP;
- If poRunSuspended in FProcessOptions Then
- Result:=Result or Create_Suspended;
- if poDebugProcess in FProcessOptions Then
- Result:=Result or DEBUG_PROCESS;
- if poDebugOnlyThisProcess in FProcessOptions Then
- Result:=Result or DEBUG_ONLY_THIS_PROCESS;
- if poDefaultErrorMode in FProcessOptions Then
- Result:=Result or CREATE_DEFAULT_ERROR_MODE;
- result:=result or PriorityConstants[FProcessPriority];
- end;
- end;
- Function StringsToPWidechars(List : TStrings): pointer;
- var
- EnvBlock: Widestring;
- I: Integer;
- begin
- EnvBlock := '';
- For I:=0 to List.Count-1 do
- EnvBlock := EnvBlock + List[i] + #0;
- EnvBlock := EnvBlock + #0;
- GetMem(Result, Length(EnvBlock));
- CopyMemory(Result, @EnvBlock[1], Length(EnvBlock));
- end;
- Procedure InitProcessAttributes(P : TProcess; Var PA : TSecurityAttributes);
- begin
- FillChar(PA,SizeOf(PA),0);
- PA.nLength := SizeOf(PA);
- end;
- Procedure InitThreadAttributes(P : TProcess; Var TA : TSecurityAttributes);
- begin
- FillChar(TA,SizeOf(TA),0);
- TA.nLength := SizeOf(TA);
- end;
- Procedure InitStartupInfo(P : TProcess; Var SI : STARTUPINFO);
- Const
- SWC : Array [TShowWindowOptions] of Cardinal =
- (0,SW_HIDE,SW_Maximize,SW_Minimize,SW_Restore,SW_Show,
- SW_ShowDefault,SW_ShowMaximized,SW_ShowMinimized,
- SW_showMinNOActive,SW_ShowNA,SW_ShowNoActivate,SW_ShowNormal);
- begin
- FillChar(SI,SizeOf(SI),0);
- With SI do
- begin
- dwFlags:=GetStartupFlags(P);
- if P.FShowWindow<>swoNone then
- dwFlags:=dwFlags or Startf_UseShowWindow
- else
- dwFlags:=dwFlags and not Startf_UseShowWindow;
- wShowWindow:=SWC[P.FShowWindow];
- if (poUsePipes in P.Options) then
- begin
- dwFlags:=dwFlags or Startf_UseStdHandles;
- end;
- if P.FillAttribute<>0 then
- begin
- dwFlags:=dwFlags or Startf_UseFillAttribute;
- dwFillAttribute:=P.FillAttribute;
- end;
- dwXCountChars:=P.WindowColumns;
- dwYCountChars:=P.WindowRows;
- dwYsize:=P.WindowHeight;
- dwXsize:=P.WindowWidth;
- dwy:=P.WindowTop;
- dwX:=P.WindowLeft;
- end;
- end;
- Procedure CreatePipes(Var HI,HO,HE : Thandle; Var SI : TStartupInfo; CE : Boolean; APipeBufferSize : Cardinal);
- begin
- CreatePipeHandles(SI.hStdInput,HI,APipeBufferSize);
- CreatePipeHandles(HO,Si.hStdOutput,APipeBufferSize);
- if CE then
- CreatePipeHandles(HE,SI.hStdError,APipeBufferSize)
- else
- begin
- SI.hStdError:=SI.hStdOutput;
- HE:=HO;
- end;
- end;
- Procedure TProcess.Execute;
- Var
- PName,PDir,PCommandLine : PWidechar;
- FEnv: pointer;
- FCreationFlags : Cardinal;
- FProcessAttributes : TSecurityAttributes;
- FThreadAttributes : TSecurityAttributes;
- FProcessInformation : TProcessInformation;
- FStartupInfo : STARTUPINFO;
- HI,HO,HE : THandle;
- begin
- PName:=Nil;
- PCommandLine:=Nil;
- PDir:=Nil;
-
- if (FApplicationName='') then
- begin
- If (FCommandLine='') then
- Raise EProcess.Create(SNoCommandline);
- PCommandLine:=PWidechar(FCommandLine)
- end
- else
- begin
- PName:=PWidechar(FApplicationName);
- If (FCommandLine='') then
- PCommandLine:=PWidechar(FApplicationName)
- else
- PCommandLine:=PWidechar(FCommandLine)
- end;
-
- If FCurrentDirectory<>'' then
- PDir:=PWidechar(FCurrentDirectory);
- if FEnvironment.Count<>0 then
- FEnv:=StringsToPWideChars(FEnvironment)
- else
- FEnv:=Nil;
- Try
- FCreationFlags:=GetCreationFlags(Self);
- InitProcessAttributes(Self,FProcessAttributes);
- InitThreadAttributes(Self,FThreadAttributes);
- InitStartupInfo(Self,FStartUpInfo);
- If poUsePipes in FProcessOptions then
- CreatePipes(HI,HO,HE,FStartupInfo,Not(poStdErrToOutPut in FProcessOptions),FPipeBufferSize);
- Try
- If Not CreateProcess (PName,PCommandLine,@FProcessAttributes,@FThreadAttributes,
- FInheritHandles,FCreationFlags,FEnv,PDir,@FStartupInfo,
- fProcessInformation) then
- Raise EProcess.CreateFmt(SErrCannotExecute,[FCommandLine,GetLastError]);
- FProcessHandle:=FProcessInformation.hProcess;
- FThreadHandle:=FProcessInformation.hThread;
- FProcessID:=FProcessINformation.dwProcessID;
- Finally
- if POUsePipes in FProcessOptions then
- begin
- FileClose(FStartupInfo.hStdInput);
- FileClose(FStartupInfo.hStdOutput);
- if Not (poStdErrToOutPut in FProcessOptions) then
- FileClose(FStartupInfo.hStdError);
- CreateStreams(HI,HO,HE);
- end;
- end;
- FRunning:=True;
- Finally
- If FEnv<>Nil then
- FreeMem(FEnv);
- end;
- if not (csDesigning in ComponentState) and // This would hang the IDE !
- (poWaitOnExit in FProcessOptions) and
- not (poRunSuspended in FProcessOptions) then
- WaitOnExit;
- end;
- Function TProcess.WaitOnExit : Boolean;
- Var
- R : DWord;
- begin
- R:=WaitForSingleObject (FProcessHandle,Infinite);
- Result:=(R<>Wait_Failed);
- If Result then
- GetExitStatus;
- FRunning:=False;
- end;
- Function TProcess.WaitOnExit(Timeout : DWord) : Boolean;
- Var
- R : DWord;
- begin
- R:=WaitForSingleObject (FProcessHandle,Timeout);
- Result:=R=0;
- If Result then
- begin
- GetExitStatus;
- FRunning:=False;
- end;
- end;
- Function TProcess.Suspend : Longint;
- begin
- Result:=SuspendThread(ThreadHandle);
- end;
- Function TProcess.Resume : LongInt;
- begin
- Result:=ResumeThread(ThreadHandle);
- end;
- Function TProcess.Terminate(AExitCode : Integer) : Boolean;
- begin
- Result:=False;
- If ExitStatus=Still_active then
- Result:=TerminateProcess(Handle,AexitCode);
- end;
- Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
- begin
- FShowWindow:=Value;
- end;
|