process.inc 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 1999-2008 by the Free Pascal development team
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. {$IFDEF FPC_DOTTEDUNITS}
  11. Uses
  12. WinApi.Windows;
  13. {$ELSE FPC_DOTTEDUNITS}
  14. Uses
  15. Windows;
  16. {$ENDIF FPC_DOTTEDUNITS}
  17. Resourcestring
  18. SNoCommandLine = 'Cannot execute empty command-line';
  19. SErrCannotExecute = 'Failed to execute %s : %d';
  20. { SErrNoSuchProgram = 'Executable not found: "%s"';
  21. SErrNoTerminalProgram = 'Could not detect X-Terminal program';
  22. }
  23. Const
  24. PriorityConstants : Array [TProcessPriority] of Cardinal =
  25. (HIGH_PRIORITY_CLASS,IDLE_PRIORITY_CLASS,
  26. NORMAL_PRIORITY_CLASS,REALTIME_PRIORITY_CLASS);
  27. procedure TProcess.CloseProcessHandles;
  28. begin
  29. if (FProcessHandle<>0) then
  30. CloseHandle(FProcessHandle);
  31. if (FThreadHandle<>0) then
  32. CloseHandle(FThreadHandle);
  33. end;
  34. Function TProcess.PeekExitStatus : Boolean;
  35. begin
  36. GetExitCodeProcess(ProcessHandle,FExitCode);
  37. Result:=(FExitCode<>Still_Active);
  38. end;
  39. Function GetStartupFlags (P : TProcess): Cardinal;
  40. begin
  41. With P do
  42. begin
  43. Result:=0;
  44. if poUsePipes in FProcessOptions then
  45. Result:=Result or Startf_UseStdHandles;
  46. if suoUseShowWindow in FStartupOptions then
  47. Result:=Result or startf_USESHOWWINDOW;
  48. if suoUSESIZE in FStartupOptions then
  49. Result:=Result or startf_usesize;
  50. if suoUsePosition in FStartupOptions then
  51. Result:=Result or startf_USEPOSITION;
  52. if suoUSECOUNTCHARS in FStartupoptions then
  53. Result:=Result or startf_usecountchars;
  54. if suoUsefIllAttribute in FStartupOptions then
  55. Result:=Result or startf_USEFILLATTRIBUTE;
  56. end;
  57. end;
  58. Function GetCreationFlags(P : TProcess) : Cardinal;
  59. begin
  60. With P do
  61. begin
  62. Result:=0;
  63. if poNoConsole in FProcessOptions then
  64. Result:=Result or Detached_Process;
  65. if poNewConsole in FProcessOptions then
  66. Result:=Result or Create_new_console;
  67. if poNewProcessGroup in FProcessOptions then
  68. Result:=Result or CREATE_NEW_PROCESS_GROUP;
  69. If poRunSuspended in FProcessOptions Then
  70. Result:=Result or Create_Suspended;
  71. if poDebugProcess in FProcessOptions Then
  72. Result:=Result or DEBUG_PROCESS;
  73. if poDebugOnlyThisProcess in FProcessOptions Then
  74. Result:=Result or DEBUG_ONLY_THIS_PROCESS;
  75. if poDefaultErrorMode in FProcessOptions Then
  76. Result:=Result or CREATE_DEFAULT_ERROR_MODE;
  77. result:=result or PriorityConstants[FProcessPriority];
  78. end;
  79. end;
  80. Function StringsToPWidechars(List : TStrings): pointer;
  81. var
  82. EnvBlock: Widestring;
  83. I: Integer;
  84. begin
  85. EnvBlock := '';
  86. For I:=0 to List.Count-1 do
  87. EnvBlock := EnvBlock + List[i] + #0;
  88. EnvBlock := EnvBlock + #0;
  89. GetMem(Result, Length(EnvBlock));
  90. CopyMemory(Result, @EnvBlock[1], Length(EnvBlock));
  91. end;
  92. Procedure InitProcessAttributes(P : TProcess; Var PA : TSecurityAttributes);
  93. begin
  94. FillChar(PA,SizeOf(PA),0);
  95. PA.nLength := SizeOf(PA);
  96. end;
  97. Procedure InitThreadAttributes(P : TProcess; Var TA : TSecurityAttributes);
  98. begin
  99. FillChar(TA,SizeOf(TA),0);
  100. TA.nLength := SizeOf(TA);
  101. end;
  102. Procedure InitStartupInfo(P : TProcess; Var SI : STARTUPINFO);
  103. Const
  104. SWC : Array [TShowWindowOptions] of Cardinal =
  105. (0,SW_HIDE,SW_Maximize,SW_Minimize,SW_Restore,SW_Show,
  106. SW_ShowDefault,SW_ShowMaximized,SW_ShowMinimized,
  107. SW_showMinNOActive,SW_ShowNA,SW_ShowNoActivate,SW_ShowNormal);
  108. begin
  109. FillChar(SI,SizeOf(SI),0);
  110. With SI do
  111. begin
  112. dwFlags:=GetStartupFlags(P);
  113. if P.FShowWindow<>swoNone then
  114. dwFlags:=dwFlags or Startf_UseShowWindow
  115. else
  116. dwFlags:=dwFlags and not Startf_UseShowWindow;
  117. wShowWindow:=SWC[P.FShowWindow];
  118. if (poUsePipes in P.Options) then
  119. begin
  120. dwFlags:=dwFlags or Startf_UseStdHandles;
  121. end;
  122. if P.FillAttribute<>0 then
  123. begin
  124. dwFlags:=dwFlags or Startf_UseFillAttribute;
  125. dwFillAttribute:=P.FillAttribute;
  126. end;
  127. dwXCountChars:=P.WindowColumns;
  128. dwYCountChars:=P.WindowRows;
  129. dwYsize:=P.WindowHeight;
  130. dwXsize:=P.WindowWidth;
  131. dwy:=P.WindowTop;
  132. dwX:=P.WindowLeft;
  133. end;
  134. end;
  135. Procedure CreatePipes(Var HI,HO,HE : Thandle; Var SI : TStartupInfo; CE : Boolean; APipeBufferSize : Cardinal);
  136. begin
  137. CreatePipeHandles(SI.hStdInput,HI,APipeBufferSize);
  138. CreatePipeHandles(HO,Si.hStdOutput,APipeBufferSize);
  139. if CE then
  140. CreatePipeHandles(HE,SI.hStdError,APipeBufferSize)
  141. else
  142. begin
  143. SI.hStdError:=SI.hStdOutput;
  144. HE:=HO;
  145. end;
  146. end;
  147. Procedure TProcess.Execute;
  148. Var
  149. PName,PDir,PCommandLine : PWidechar;
  150. FEnv: pointer;
  151. FCreationFlags : Cardinal;
  152. FProcessAttributes : TSecurityAttributes;
  153. FThreadAttributes : TSecurityAttributes;
  154. FProcessInformation : TProcessInformation;
  155. FStartupInfo : STARTUPINFO;
  156. HI,HO,HE : THandle;
  157. begin
  158. PName:=Nil;
  159. PCommandLine:=Nil;
  160. PDir:=Nil;
  161. if (FApplicationName='') then
  162. begin
  163. If (FCommandLine='') then
  164. Raise EProcess.Create(SNoCommandline);
  165. PCommandLine:=PWidechar(FCommandLine)
  166. end
  167. else
  168. begin
  169. PName:=PWidechar(FApplicationName);
  170. If (FCommandLine='') then
  171. PCommandLine:=PWidechar(FApplicationName)
  172. else
  173. PCommandLine:=PWidechar(FCommandLine)
  174. end;
  175. If FCurrentDirectory<>'' then
  176. PDir:=PWidechar(FCurrentDirectory);
  177. if FEnvironment.Count<>0 then
  178. FEnv:=StringsToPWideChars(FEnvironment)
  179. else
  180. FEnv:=Nil;
  181. Try
  182. FCreationFlags:=GetCreationFlags(Self);
  183. InitProcessAttributes(Self,FProcessAttributes);
  184. InitThreadAttributes(Self,FThreadAttributes);
  185. InitStartupInfo(Self,FStartUpInfo);
  186. If poUsePipes in FProcessOptions then
  187. CreatePipes(HI,HO,HE,FStartupInfo,Not(poStdErrToOutPut in FProcessOptions),FPipeBufferSize);
  188. Try
  189. If Not CreateProcess (PName,PCommandLine,@FProcessAttributes,@FThreadAttributes,
  190. FInheritHandles,FCreationFlags,FEnv,PDir,@FStartupInfo,
  191. fProcessInformation) then
  192. Raise EProcess.CreateFmt(SErrCannotExecute,[FCommandLine,GetLastError]);
  193. FProcessHandle:=FProcessInformation.hProcess;
  194. FThreadHandle:=FProcessInformation.hThread;
  195. FProcessID:=FProcessINformation.dwProcessID;
  196. Finally
  197. if POUsePipes in FProcessOptions then
  198. begin
  199. FileClose(FStartupInfo.hStdInput);
  200. FileClose(FStartupInfo.hStdOutput);
  201. if Not (poStdErrToOutPut in FProcessOptions) then
  202. FileClose(FStartupInfo.hStdError);
  203. CreateStreams(HI,HO,HE);
  204. end;
  205. end;
  206. FRunning:=True;
  207. Finally
  208. If FEnv<>Nil then
  209. FreeMem(FEnv);
  210. end;
  211. if not (csDesigning in ComponentState) and // This would hang the IDE !
  212. (poWaitOnExit in FProcessOptions) and
  213. not (poRunSuspended in FProcessOptions) then
  214. WaitOnExit;
  215. end;
  216. Function TProcess.WaitOnExit : Boolean;
  217. Var
  218. R : DWord;
  219. begin
  220. R:=WaitForSingleObject (FProcessHandle,Infinite);
  221. Result:=(R<>Wait_Failed);
  222. If Result then
  223. GetExitStatus;
  224. FRunning:=False;
  225. end;
  226. Function TProcess.WaitOnExit(Timeout : DWord) : Boolean;
  227. Var
  228. R : DWord;
  229. begin
  230. R:=WaitForSingleObject (FProcessHandle,Timeout);
  231. Result:=R=0;
  232. If Result then
  233. begin
  234. GetExitStatus;
  235. FRunning:=False;
  236. end;
  237. end;
  238. Function TProcess.Suspend : Longint;
  239. begin
  240. Result:=SuspendThread(ThreadHandle);
  241. end;
  242. Function TProcess.Resume : LongInt;
  243. begin
  244. Result:=ResumeThread(ThreadHandle);
  245. end;
  246. Function TProcess.Terminate(AExitCode : Integer) : Boolean;
  247. begin
  248. Result:=False;
  249. If ExitStatus=Still_active then
  250. Result:=TerminateProcess(Handle,AexitCode);
  251. end;
  252. Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
  253. begin
  254. FShowWindow:=Value;
  255. end;