process.pp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$h+}
  13. unit process;
  14. interface
  15. Uses Classes,
  16. pipes,
  17. {$ifdef Unix}
  18. {$ifdef ver1_0}
  19. Linux,
  20. {$else}
  21. unix,
  22. {$endif}
  23. {$else}
  24. Windows,
  25. {$endif}
  26. SysUtils;
  27. Type
  28. TProcessOption = (poRunSuspended,poWaitOnExit,
  29. poUsePipes,poStderrToOutPut,
  30. poNoConsole,poNewConsole,
  31. poDefaultErrorMode,poNewProcessGroup,
  32. poDebugProcess,poDebugOnlyThisProcess);
  33. TShowWindowOptions = (swoNone,swoHIDE,swoMaximize,swoMinimize,swoRestore,swoShow,
  34. swoShowDefault,swoShowMaximized,swoShowMinimized,
  35. swoshowMinNOActive,swoShowNA,swoShowNoActivate,swoShowNormal);
  36. TStartupOption = (suoUseShowWindow,suoUseSize,suoUsePosition,
  37. suoUseCountChars,suoUseFillAttribute);
  38. TProcessPriority = (ppHigh,ppIdle,ppNormal,ppRealTime);
  39. TProcessOptions = Set of TPRocessOption;
  40. TstartUpoptions = set of TStartupOption;
  41. {$ifdef unix}
  42. Const
  43. STARTF_USESHOWWINDOW = 1; // Ignored
  44. STARTF_USESIZE = 2;
  45. STARTF_USEPOSITION = 4;
  46. STARTF_USECOUNTCHARS = 8; // Ignored
  47. STARTF_USEFILLATTRIBUTE = $10;
  48. STARTF_RUNFULLSCREEN = $20; // Ignored
  49. STARTF_FORCEONFEEDBACK = $40; // Ignored
  50. STARTF_FORCEOFFFEEDBACK = $80; // Ignored
  51. STARTF_USESTDHANDLES = $100; // Ignored
  52. STARTF_USEHOTKEY = $200; // Ignored
  53. Type
  54. PProcessInformation = ^TProcessInformation;
  55. TProcessInformation = record
  56. hProcess: THandle;
  57. hThread: THandle;
  58. dwProcessId: DWORD;
  59. dwThreadId: DWORD;
  60. end;
  61. PStartupInfo = ^TStartupInfo;
  62. TStartupInfo = Record
  63. cb: DWORD;
  64. lpReserved: Pointer;
  65. lpDesktop: Pointer;
  66. lpTitle: Pointer;
  67. dwX: DWORD;
  68. dwY: DWORD;
  69. dwXSize: DWORD;
  70. dwYSize: DWORD;
  71. dwXCountChars: DWORD;
  72. dwYCountChars: DWORD;
  73. dwFillAttribute: DWORD;
  74. dwFlags: DWORD;
  75. wShowWindow: Word;
  76. cbReserved2: Word;
  77. lpReserved2: PByte;
  78. hStdInput: THandle;
  79. hStdOutput: THandle;
  80. hStdError: THandle;
  81. end;
  82. PSecurityAttributes = ^TSecurityAttributes;
  83. TSecurityAttributes = Record
  84. nlength : Integer;
  85. lpSecurityDescriptor : Pointer;
  86. BinheritHandle : Boolean;
  87. end;
  88. Const piInheritablePipe : TSecurityAttributes = (
  89. nlength:SizeOF(TSecurityAttributes);
  90. lpSecurityDescriptor:Nil;
  91. Binherithandle:True);
  92. piNonInheritablePipe : TSecurityAttributes = (
  93. nlength:SizeOF(TSecurityAttributes);
  94. lpSecurityDescriptor:Nil;
  95. Binherithandle:False);
  96. {$endif}
  97. Type
  98. TProcess = Class (TComponent)
  99. Private
  100. {$ifndef unix}
  101. FAccess : Cardinal;
  102. {$endif}
  103. FApplicationName : string;
  104. FChildErrorStream : TOutPutPipeStream;
  105. FChildInputSTream : TInputPipeStream;
  106. FChildOutPutStream : TOutPutPipeStream;
  107. FConsoleTitle : String;
  108. FProcessOptions : TProcessOptions;
  109. FStartUpOptions : TStartupOptions;
  110. FCommandLine : String;
  111. FCurrentDirectory : String;
  112. FDeskTop : String;
  113. FEnvironment : Tstrings;
  114. FExitCode : Cardinal;
  115. FHandle : THandle;
  116. FShowWindow : TShowWindowOptions;
  117. FInherithandles : LongBool;
  118. FParentErrorStream : TInputPipeStream;
  119. FParentInputSTream : TInputPipeStream;
  120. FParentOutputStream : TOutPutPipeStream;
  121. FRunning : Boolean;
  122. FThreadAttributes : PSecurityAttributes;
  123. FProcessAttributes : PSecurityAttributes;
  124. FProcessInformation : TProcessInformation;
  125. FPRocessPriority : TProcessPriority;
  126. FStartupInfo : TStartupInfo;
  127. Procedure FreeStreams;
  128. Function GetExitStatus : Integer;
  129. Function GetHandle : THandle;
  130. Function GetRunning : Boolean;
  131. Function GetProcessAttributes : TSecurityAttributes;
  132. Function GetThreadAttributes : TSecurityAttributes;
  133. Procedure SetProcessAttributes (Value : TSecurityAttributes);
  134. Procedure SetThreadAttributes (Value : TSecurityAttributes);
  135. Function GetWindowRect : TRect;
  136. Procedure SetWindowRect (Value : TRect);
  137. Procedure SetFillAttribute (Value : Cardinal);
  138. Procedure SetShowWindow (Value : TShowWindowOptions);
  139. Procedure SetWindowColumns (Value : Cardinal);
  140. Procedure SetWindowHeight (Value : Cardinal);
  141. Procedure SetWindowLeft (Value : Cardinal);
  142. Procedure SetWindowRows (Value : Cardinal);
  143. Procedure SetWindowTop (Value : Cardinal);
  144. Procedure SetWindowWidth (Value : Cardinal);
  145. procedure CreateStreams;
  146. function GetCreationFlags: Cardinal;
  147. function GetStartupFlags: Cardinal;
  148. procedure SetApplicationname(const Value: String);
  149. procedure SetPRocessOptions(const Value: TProcessOptions);
  150. procedure SetActive(const Value: Boolean);
  151. procedure SetEnvironment(const Value: TStrings);
  152. {$ifdef unix}
  153. function PeekLinuxExitStatus: Boolean;
  154. {$endif}
  155. Public
  156. Constructor Create (AOwner : TComponent);override;
  157. Destructor Destroy; override;
  158. Procedure Execute; virtual;
  159. Function Resume : Integer; virtual;
  160. Function Suspend : Integer; virtual;
  161. Function Terminate (AExitCode : Integer): Boolean; virtual;
  162. Function WaitOnExit : DWord;
  163. Property WindowRect : Trect Read GetWindowRect Write SetWindowRect;
  164. Property StartupInfo : TStartupInfo Read FStartupInfo;
  165. Property ProcessAttributes : TSecurityAttributes Read GetProcessAttributes Write SetProcessAttributes;
  166. Property ProcessInformation : TProcessInformation Read FPRocessInformation;
  167. Property Handle : THandle Read FProcessInformation.hProcess;
  168. Property ThreadHandle : THandle Read FprocessInformation.hThread;
  169. Property Input : TOutPutPipeStream Read FParentOutPutStream;
  170. Property OutPut : TInputPipeStream Read FParentInputStream;
  171. Property StdErr : TinputPipeStream Read FParentErrorStream;
  172. Property ExitStatus : Integer Read GetExitStatus;
  173. Property InheritHandles : LongBool Read FInheritHandles Write FInheritHandles;
  174. Property ThreadAttributes : TSecurityAttributes Read GetThreadAttributes Write SetThreadAttributes;
  175. Published
  176. Property Active : Boolean Read Getrunning Write SetActive;
  177. Property ApplicationName : String Read FApplicationname Write SetApplicationname;
  178. Property CommandLine : String Read FCommandLine Write FCommandLine;
  179. Property ConsoleTitle : String Read FConsoleTitle Write FConsoleTitle;
  180. Property CurrentDirectory : String Read FCurrentDirectory Write FCurrentDirectory;
  181. Property DeskTop : String Read FDeskTop Write FDeskTop;
  182. Property Environment : TStrings Read FEnvironment Write SetEnvironment;
  183. Property FillAttribute : Cardinal Read FStartupInfo.dwFillAttribute Write SetFillAttribute;
  184. Property Options : TProcessOptions Read FProcessOptions Write SetPRocessOptions;
  185. Property Priority : TProcessPriority Read FProcessPriority Write FProcessPriority;
  186. Property StartUpOptions : TStartUpOptions Read FStartUpOptions Write FStartupOptions;
  187. Property Running : Boolean Read GetRunning;
  188. Property ShowWindow : TShowWindowOptions Read FShowWindow Write SetShowWindow;
  189. Property WindowColumns : Cardinal Read FStartupInfo.dwXCountchars Write SetWindowColumns;
  190. Property WindowHeight : Cardinal Read FStartupInfo.dwYsize Write SetWindowHeight;
  191. Property WindowLeft : Cardinal Read FStartupInfo.dwx Write SetWindowLeft;
  192. Property WindowRows : Cardinal Read FStartupInfo.dwYcountChars Write SetWindowRows;
  193. Property WindowTop : Cardinal Read FStartupInfo.dwy Write SetWindowTop ;
  194. Property WindowWidth : Cardinal Read FStartupInfo.dwXsize Write SetWindowWidth;
  195. end;
  196. {$ifdef unix}
  197. Const
  198. PriorityConstants : Array [TProcessPriority] of Integer =
  199. (20,20,0,-20);
  200. Const
  201. GeometryOption : String = '-geometry';
  202. TitleOption : String ='-title';
  203. {$else}
  204. Const
  205. PriorityConstants : Array [TProcessPriority] of Cardinal =
  206. (HIGH_PRIORITY_CLASS,IDLE_PRIORITY_CLASS,
  207. NORMAL_PRIORITY_CLASS,REALTIME_PRIORITY_CLASS);
  208. {$endif}
  209. implementation
  210. Constructor TProcess.Create (AOwner : TComponent);
  211. begin
  212. Inherited;
  213. {$ifndef unix}
  214. FAccess:=PROCESS_ALL_ACCESS;
  215. {$endif}
  216. FProcessPriority:=ppNormal;
  217. FShowWindow:=swoNone;
  218. FStartupInfo.cb:=SizeOf(TStartupInfo);
  219. FInheritHandles:=True;
  220. FEnvironment:=TStringList.Create;
  221. end;
  222. Destructor TProcess.Destroy;
  223. begin
  224. If assigned (FProcessAttributes) then Dispose (FPRocessAttributes);
  225. If assigned (FThreadAttributes) then Dispose (FThreadAttributes);
  226. FEnvironment.Free;
  227. FreeStreams;
  228. Inherited;
  229. end;
  230. Procedure TProcess.FreeStreams;
  231. var FreedStreams: TList;
  232. procedure FreeStream(var AnObject: TObject);
  233. begin
  234. if FreedStreams.IndexOf(AnObject)<0 then
  235. begin
  236. FreedStreams.Add(AnObject);
  237. AnObject.Free;
  238. end;
  239. AnObject:=nil;
  240. end;
  241. begin
  242. FreedStreams:=TList.Create;
  243. try
  244. FreeStream(FParentErrorStream);
  245. FreeStream(FParentInputStream);
  246. FreeStream(FParentOutputStream);
  247. FreeStream(FChildErrorStream);
  248. FreeStream(FChildInputStream);
  249. FreeStream(FChildOutputStream);
  250. finally
  251. FreedStreams.Free;
  252. end;
  253. end;
  254. Function TProcess.GetExitStatus : Integer;
  255. begin
  256. If FRunning then
  257. {$ifdef unix}
  258. PeekLinuxExitStatus;
  259. {$else}
  260. GetExitCodeProcess(Handle,FExitCode);
  261. {$endif}
  262. Result:=FExitCode;
  263. end;
  264. Function TProcess.GetHandle : THandle;
  265. begin
  266. {$ifndef unix}
  267. If FHandle=0 Then
  268. FHandle:=OpenProcess (FAccess,True,FProcessInformation.dwProcessId);
  269. {$endif}
  270. Result:=FHandle
  271. end;
  272. Function TProcess.GetProcessAttributes : TSecurityAttributes;
  273. Var P : PSecurityAttributes;
  274. begin
  275. IF not Assigned(FProcessAttributes) then
  276. begin
  277. // Provide empty dummy value;
  278. New(p);
  279. Fillchar(p^,Sizeof(TSecurityAttributes),0);
  280. Result:=p^;
  281. end
  282. else
  283. REsult:=FProcessAttributes^;
  284. end;
  285. {$ifdef unix}
  286. Function TProcess.PeekLinuxExitStatus : Boolean;
  287. begin
  288. Result:=WaitPID(Handle,@FExitCode,WNOHANG)=Handle;
  289. If Result then
  290. FExitCode:=wexitstatus(FExitCode)
  291. else
  292. FexitCode:=0;
  293. end;
  294. {$endif}
  295. Function TProcess.GetRunning : Boolean;
  296. begin
  297. IF FRunning then
  298. begin
  299. {$ifdef unix}
  300. FRunning:=Not PeekLinuxExitStatus;
  301. {$else}
  302. Frunning:=GetExitStatus=Still_Active;
  303. {$endif}
  304. end;
  305. Result:=FRunning;
  306. end;
  307. Function TProcess.GetThreadAttributes : TSecurityAttributes;
  308. Var P : PSecurityAttributes;
  309. begin
  310. IF not Assigned(FThreadAttributes) then
  311. begin
  312. // Provide empty dummy value;
  313. New(p);
  314. Fillchar(p^,Sizeof(TSecurityAttributes),0);
  315. Result:=p^;
  316. end
  317. else
  318. Result:=FThreadAttributes^;
  319. end;
  320. Procedure TProcess.SetProcessAttributes (Value : TSecurityAttributes);
  321. begin
  322. If not Assigned (FProcessAttributes) then
  323. New(FProcessAttributes);
  324. FPRocessAttributes^:=VAlue;
  325. end;
  326. Procedure TProcess.SetThreadAttributes (Value : TSecurityAttributes);
  327. begin
  328. If not Assigned (FThreadAttributes) then
  329. New(FThreadAttributes);
  330. FThreadAttributes^:=VAlue;
  331. end;
  332. Procedure TProcess.CreateStreams;
  333. begin
  334. FreeStreams;
  335. CreatePipeStreams (FChildInputSTream,FParentOutPutStream); //,@piInheritablePipe,1024);
  336. CreatePipeStreams (FParentInputStream,FChildOutPutStream); //,@piInheritablePipe,1024);
  337. if Not (poStdErrToOutPut in FProcessOptions) then
  338. CreatePipeStreams (FParentErrorStream,FChildErrorStream) //,@piInheritablePipe,1024)
  339. else
  340. begin
  341. FChildErrorStream:=FChildOutPutStream;
  342. FParentErrorStream:=FParentInputStream;
  343. end;
  344. FStartupInfo.dwFlags:=FStartupInfo.dwFlags or Startf_UseStdHandles;
  345. FStartupInfo.hStdInput:=FChildInputStream.Handle;
  346. FStartupInfo.hStdOutput:=FChildOutPutStream.Handle;
  347. FStartupInfo.hStdError:=FChildErrorStream.Handle;
  348. end;
  349. Function TProcess.GetCreationFlags : Cardinal;
  350. begin
  351. Result:=0;
  352. {$ifndef unix}
  353. if poNoConsole in FProcessOptions then
  354. Result:=Result or Detached_Process;
  355. if poNewConsole in FProcessOptions then
  356. Result:=Result or Create_new_console;
  357. if poNewProcessGroup in FProcessOptions then
  358. Result:=Result or CREATE_NEW_PROCESS_GROUP;
  359. If poRunSuspended in FProcessOptions Then
  360. Result:=Result or Create_Suspended;
  361. if poDebugProcess in FProcessOptions Then
  362. Result:=Result or DEBUG_PROCESS;
  363. if poDebugOnlyThisProcess in FProcessOptions Then
  364. Result:=Result or DEBUG_ONLY_THIS_PROCESS;
  365. if poDefaultErrorMode in FProcessOptions Then
  366. Result:=Result or CREATE_DEFAULT_ERROR_MODE;
  367. result:=result or PriorityConstants[FProcessPriority];
  368. {$endif}
  369. end;
  370. Function TProcess.GetStartupFlags : Cardinal;
  371. begin
  372. Result:=0;
  373. if poUsePipes in FProcessOptions then
  374. Result:=Result or Startf_UseStdHandles;
  375. if suoUseShowWindow in FStartupOptions then
  376. Result:=Result or startf_USESHOWWINDOW;
  377. if suoUSESIZE in FStartupOptions then
  378. Result:=Result or startf_usesize;
  379. if suoUsePosition in FStartupOptions then
  380. Result:=Result or startf_USEPOSITION;
  381. if suoUSECOUNTCHARS in FStartupoptions then
  382. Result:=Result or startf_usecountchars;
  383. if suoUsefIllAttribute in FStartupOptions then
  384. Result:=Result or startf_USEFILLATTRIBUTE;
  385. end;
  386. Type
  387. {$ifndef unix}
  388. PPChar = ^PChar;
  389. {$endif}
  390. TPCharArray = Array[Word] of pchar;
  391. PPCharArray = ^TPcharArray;
  392. Function StringsToPCharList(List : TStrings) : PPChar;
  393. Var
  394. I : Integer;
  395. S : String;
  396. begin
  397. I:=(List.Count)+1;
  398. GetMem(Result,I*sizeOf(PChar));
  399. PPCharArray(Result)^[List.Count]:=Nil;
  400. For I:=0 to List.Count-1 do
  401. begin
  402. S:=List[i];
  403. Result[i]:=StrNew(PChar(S));
  404. end;
  405. end;
  406. Procedure FreePCharList(List : PPChar);
  407. Var
  408. I : integer;
  409. begin
  410. I:=0;
  411. While List[i]<>Nil do
  412. begin
  413. StrDispose(List[i]);
  414. Inc(I);
  415. end;
  416. FreeMem(List);
  417. end;
  418. {$ifdef unix}
  419. Procedure CommandToList(S : String; List : TStrings);
  420. Function GetNextWord : String;
  421. Const
  422. WhiteSpace = [' ',#8,#10];
  423. Literals = ['"',''''];
  424. Var
  425. Wstart,wend : Integer;
  426. InLiteral : Boolean;
  427. LastLiteral : char;
  428. begin
  429. WStart:=1;
  430. While (WStart<=Length(S)) and (S[WStart] in WhiteSpace) do
  431. Inc(WStart);
  432. WEnd:=WStart;
  433. InLiteral:=False;
  434. LastLiteral:=#0;
  435. While (Wend<=Length(S)) and (Not (S[Wend] in WhiteSpace) or InLiteral) do
  436. begin
  437. if S[Wend] in Literals then
  438. If InLiteral then
  439. InLiteral:=Not (S[Wend]=LastLiteral)
  440. else
  441. begin
  442. InLiteral:=True;
  443. LastLiteral:=S[Wend];
  444. end;
  445. inc(wend);
  446. end;
  447. Result:=Copy(S,WStart,WEnd-WStart);
  448. Result:=StringReplace(Result,'"','',[rfReplaceAll]);
  449. Result:=StringReplace(Result,'''','',[rfReplaceAll]);
  450. While (WEnd<=Length(S)) and (S[Wend] in WhiteSpace) do
  451. inc(Wend);
  452. Delete(S,1,WEnd-1);
  453. end;
  454. Var
  455. W : String;
  456. begin
  457. While Length(S)>0 do
  458. begin
  459. W:=GetNextWord;
  460. If (W<>'') then
  461. List.Add(W);
  462. end;
  463. end;
  464. Function MakeCommand(Var AppName,CommandLine : String;
  465. StartupOptions : TStartUpOptions;
  466. ProcessOptions : TProcessOptions;
  467. StartupInfo : TStartupInfo) : PPchar;
  468. Const
  469. SNoCommandLine = 'Cannot execute empty command-line';
  470. Var
  471. S : TStringList;
  472. G : String;
  473. begin
  474. if (AppName='') then
  475. begin
  476. If (CommandLine='') then
  477. Raise Exception.Create(SNoCommandline)
  478. end
  479. else
  480. begin
  481. If (CommandLine='') then
  482. CommandLine:=AppName;
  483. end;
  484. S:=TStringList.Create;
  485. try
  486. CommandToList(CommandLine,S);
  487. if poNewConsole in ProcessOptions then
  488. begin
  489. S.Insert(0,'-e');
  490. If (AppName<>'') then
  491. begin
  492. S.Insert(0,AppName);
  493. S.Insert(0,'-title');
  494. end;
  495. if suoUseCountChars in StartupOptions then
  496. With StartupInfo do
  497. begin
  498. S.Insert(0,Format('%dx%d',[dwXCountChars,dwYCountChars]));
  499. S.Insert(0,'-geometry');
  500. end;
  501. S.Insert(0,'xterm');
  502. end;
  503. if (AppName<>'') then
  504. begin
  505. S.Add(TitleOption);
  506. S.Add(AppName);
  507. end;
  508. With StartupInfo do
  509. begin
  510. G:='';
  511. if (suoUseSize in StartupOptions) then
  512. g:=format('%dx%d',[dwXSize,dwYsize]);
  513. if (suoUsePosition in StartupOptions) then
  514. g:=g+Format('+%d+%d',[dwX,dwY]);
  515. if G<>'' then
  516. begin
  517. S.Add(GeometryOption);
  518. S.Add(g);
  519. end;
  520. end;
  521. Result:=StringsToPcharList(S);
  522. AppName:=S[0];
  523. Finally
  524. S.free;
  525. end;
  526. end;
  527. Function CreateProcess (PName,PCommandLine,PDir : String;
  528. FEnv : PPChar;
  529. StartupOptions : TStartupOptions;
  530. ProcessOptions : TProcessOptions;
  531. const FStartupInfo : TStartupInfo;
  532. Var ProcessInfo : TProcessInformation) : boolean;
  533. Var
  534. PID : Longint;
  535. Argv : PPChar;
  536. fd : Integer;
  537. begin
  538. Result:=True;
  539. Argv:=MakeCommand(Pname,PCommandLine,StartupOptions,ProcessOptions,FStartupInfo);
  540. if (pos('/',PName)<>1) then
  541. PName:=FileSearch(Pname,GetEnv('PATH'));
  542. Pid:=fork;
  543. if Pid=0 then
  544. begin
  545. { We're in the child }
  546. if (PDir<>'') then
  547. ChDir(PDir);
  548. if PoUsePipes in ProcessOptions then
  549. begin
  550. dup2(FStartupInfo.hStdInput,0);
  551. dup2(FStartupInfo.hStdOutput,1);
  552. dup2(FStartupInfo.hStdError,2);
  553. end
  554. else if poNoConsole in ProcessOptions then
  555. begin
  556. fd:=FileOpen('/dev/null',fmOpenReadWrite);
  557. dup2(fd,0);
  558. dup2(fd,1);
  559. dup2(fd,2);
  560. end;
  561. if (poRunSuspended in ProcessOptions) then
  562. sigraise(SIGSTOP);
  563. if FEnv<>Nil then
  564. Execve(PChar(PName),Argv,Fenv)
  565. else
  566. Execv(Pchar(PName),argv);
  567. Halt(127);
  568. end
  569. else
  570. begin
  571. FreePcharList(Argv);
  572. // Copy process information.
  573. ProcessInfo.hProcess:=PID;
  574. ProcessInfo.hThread:=PID;
  575. ProcessInfo.dwProcessId:=PID;
  576. ProcessInfo.dwThreadId:=PID;
  577. end;
  578. end;
  579. {$endif}
  580. {$ifdef unix}
  581. Function GetLastError : Integer;
  582. begin
  583. Result:=-1;
  584. end;
  585. {$endif}
  586. Procedure TProcess.Execute;
  587. Var
  588. {$ifndef unix}
  589. PName,PDir,PCommandLine : PChar;
  590. {$endif}
  591. FEnv : PPChar;
  592. FCreationFlags : Cardinal;
  593. begin
  594. If poUsePipes in FProcessOptions then
  595. CreateStreams;
  596. FCreationFlags:=GetCreationFlags;
  597. FStartupInfo.dwFlags:=GetStartupFlags;
  598. {$ifndef unix}
  599. PName:=Nil;
  600. PCommandLine:=Nil;
  601. PDir:=Nil;
  602. If FApplicationName<>'' then
  603. PName:=Pchar(FApplicationName);
  604. If FCommandLine<>'' then
  605. PCommandLine:=Pchar(FCommandLine);
  606. If FCurrentDirectory<>'' then
  607. PDir:=Pchar(FCurrentDirectory);
  608. {$endif}
  609. if FEnvironment.Count<>0 then
  610. FEnv:=StringsToPcharList(FEnvironment)
  611. else
  612. FEnv:=Nil;
  613. FInheritHandles:=True;
  614. {$ifdef unix}
  615. if Not CreateProcess (FApplicationName,FCommandLine,FCurrentDirectory,FEnv,
  616. FStartupOptions,FProcessOptions,FStartupInfo,
  617. fProcessInformation) then
  618. {$else}
  619. If Not CreateProcess (PName,PCommandLine,FProcessAttributes,FThreadAttributes,
  620. FInheritHandles,FCreationFlags,FEnv,PDir,FStartupInfo,
  621. fProcessInformation) then
  622. {$endif}
  623. Raise Exception.CreateFmt('Failed to execute %s : %d',[FCommandLine,GetLastError]);
  624. if POUsePipes in FProcessOptions then
  625. begin
  626. FileClose(FStartupInfo.hStdInput);
  627. FileClose(FStartupInfo.hStdOutput);
  628. if Not (poStdErrToOutPut in FProcessOptions) then
  629. FileClose(FStartupInfo.hStdError);
  630. end;
  631. {$ifdef unix}
  632. Fhandle:=fprocessinformation.hProcess;
  633. {$endif}
  634. FRunning:=True;
  635. If FEnv<>Nil then
  636. FreePCharList(FEnv);
  637. if not (csDesigning in ComponentState) and // This would hang the IDE !
  638. (poWaitOnExit in FProcessOptions) and
  639. not (poRunSuspended in FProcessOptions) then
  640. WaitOnExit;
  641. end;
  642. Function TProcess.WaitOnExit : Dword;
  643. begin
  644. {$ifdef unix}
  645. Result:=Dword(WaitPid(Handle,@FExitCode,0));
  646. If Result=Handle then
  647. FExitCode:=WexitStatus(FExitCode);
  648. {$else}
  649. Result:=WaitForSingleObject (FprocessInformation.hProcess,Infinite);
  650. If Result<>Wait_Failed then
  651. GetExitStatus;
  652. {$endif}
  653. FRunning:=False;
  654. end;
  655. Function TProcess.Suspend : Longint;
  656. begin
  657. {$ifdef unix}
  658. If kill(Handle,SIGSTOP)<>0 then
  659. Result:=-1
  660. else
  661. Result:=1;
  662. {$else}
  663. Result:=SuspendThread(ThreadHandle);
  664. {$endif}
  665. end;
  666. Function TProcess.Resume : LongInt;
  667. begin
  668. {$ifdef unix}
  669. If kill(Handle,SIGCONT)<>0 then
  670. Result:=-1
  671. else
  672. Result:=0;
  673. {$else}
  674. Result:=ResumeThread(ThreadHandle);
  675. {$endif}
  676. end;
  677. Function TProcess.Terminate(AExitCode : Integer) : Boolean;
  678. begin
  679. Result:=False;
  680. {$ifdef unix}
  681. Result:=kill(Handle,SIGTERM)=0;
  682. If Result then
  683. begin
  684. If Running then
  685. Result:=Kill(Handle,SIGKILL)=0;
  686. end;
  687. GetExitStatus;
  688. {$else}
  689. If ExitStatus=Still_active then
  690. Result:=TerminateProcess(Handle,AexitCode);
  691. {$endif}
  692. end;
  693. Procedure TProcess.SetFillAttribute (Value : Cardinal);
  694. begin
  695. FStartupInfo.dwFlags:=FStartupInfo.dwFlags or Startf_UseFillAttribute;
  696. FStartupInfo.dwFillAttribute:=Value;
  697. end;
  698. Procedure TProcess.SetShowWindow (Value : TShowWindowOptions);
  699. {$ifndef unix}
  700. Const
  701. SWC : Array [TShowWindowOptions] of Cardinal =
  702. (0,SW_HIDE,SW_Maximize,SW_Minimize,SW_Restore,SW_Show,
  703. SW_ShowDefault,SW_ShowMaximized,SW_ShowMinimized,
  704. SW_showMinNOActive,SW_ShowNA,SW_ShowNoActivate,SW_ShowNormal);
  705. {$endif}
  706. begin
  707. FShowWindow:=Value;
  708. if Value<>swoNone then
  709. FStartupInfo.dwFlags:=FStartupInfo.dwFlags or Startf_UseShowWindow
  710. else
  711. FStartupInfo.dwFlags:=FStartupInfo.dwFlags and not Startf_UseShowWindow;
  712. {$ifndef unix}
  713. FStartupInfo.wShowWindow:=SWC[Value];
  714. {$endif}
  715. end;
  716. Procedure TProcess.SetWindowColumns (Value : Cardinal);
  717. begin
  718. if Value<>0 then
  719. Include(FStartUpOptions,suoUseCountChars);
  720. FStartupInfo.dwXCountChars:=Value;
  721. end;
  722. Procedure TProcess.SetWindowHeight (Value : Cardinal);
  723. begin
  724. if Value<>0 then
  725. include(FStartUpOptions,suoUsePosition);
  726. FStartupInfo.dwYsize:=Value;
  727. end;
  728. Procedure TProcess.SetWindowLeft (Value : Cardinal);
  729. begin
  730. if Value<>0 then
  731. Include(FStartUpOptions,suoUseSize);
  732. FStartupInfo.dwx:=Value;
  733. end;
  734. Procedure TProcess.SetWindowTop (Value : Cardinal);
  735. begin
  736. if Value<>0 then
  737. Include(FStartUpOptions,suoUsePosition);
  738. FStartupInfo.dwy:=Value;
  739. end;
  740. Procedure TProcess.SetWindowWidth (Value : Cardinal);
  741. begin
  742. If (Value<>0) then
  743. Include(FStartUpOptions,suoUseSize);
  744. FStartupInfo.dwxsize:=Value;
  745. end;
  746. Function TProcess.GetWindowRect : TRect;
  747. begin
  748. With Result do
  749. With FStartupInfo do
  750. begin
  751. Left:=dwx;
  752. Right:=dwx+dwxSize;
  753. Top:=dwy;
  754. Bottom:=dwy+dwysize;
  755. end;
  756. end;
  757. Procedure TProcess.SetWindowRect (Value : Trect);
  758. begin
  759. Include(FStartupOptions,suouseSize);
  760. Include(FStartupOptions,suoUsePosition);
  761. With Value do
  762. With FStartupInfo do
  763. begin
  764. dwx:=Left;
  765. dwxSize:=Right-Left;
  766. dwy:=Top;
  767. dwySize:=Bottom-top;
  768. end;
  769. end;
  770. Procedure TProcess.SetWindowRows (Value : Cardinal);
  771. begin
  772. FStartupInfo.dwFlags:=FStartupInfo.dwFlags or Startf_UseCountChars;
  773. FStartupInfo.dwYCountChars:=Value;
  774. end;
  775. procedure TProcess.SetApplicationname(const Value: String);
  776. begin
  777. FApplicationname := Value;
  778. If (csdesigning in ComponentState) and
  779. (FCommandLine='') then
  780. FCommandLine:=Value;
  781. end;
  782. procedure TProcess.SetProcessOptions(const Value: TProcessOptions);
  783. begin
  784. FProcessOptions := Value;
  785. If poNewConsole in FPRocessOptions then
  786. Exclude(FProcessoptions,poNoConsole);
  787. if poRunSuspended in FProcessOptions then
  788. Exclude(FPRocessoptions,poWaitOnExit);
  789. end;
  790. procedure TProcess.SetActive(const Value: Boolean);
  791. begin
  792. if (Value<>GetRunning) then
  793. If Value then
  794. Execute
  795. else
  796. Terminate(0);
  797. end;
  798. procedure TProcess.SetEnvironment(const Value: TStrings);
  799. begin
  800. FEnvironment.Assign(Value);
  801. end;
  802. end.
  803. {
  804. $Log$
  805. Revision 1.15 2003-05-08 20:04:16 armin
  806. * Dont close FStartupInfo.hStdError if options include poStdErrToOutPut
  807. Revision 1.14 2003/04/27 21:21:42 sg
  808. * Added typecast to prevent range check error in TProcess.WaitOnExit
  809. Revision 1.13 2002/09/07 15:15:25 peter
  810. * old logs removed and tabs fixed
  811. }