unit DbgIntfProcess; {$mode objfpc}{$H+} // New FPC 331 TProcess to allow StdIn/StdOut redirection {$UnDef HAS_NEW_PROCESS}{$UnDef USES_NEW_PROCESS} {$IF FPC_Fullversion>=30301} {$define HAS_NEW_PROCESS} {$ELSE} {$IFDEF WINDOWS} {$define USES_NEW_PROCESS} {$define HAS_NEW_PROCESS} {$ENDIF} {$IFDEF WINCE} {$undef USES_NEW_PROCESS} {$undef HAS_NEW_PROCESS} {$ENDIF} {$IFDEF LINUX} {$define USES_NEW_PROCESS} {$define HAS_NEW_PROCESS} {$ENDIF} {$ENDIF} interface uses Classes, SysUtils, {$IFDEF USES_NEW_PROCESS} process331 in 'fcl-proc331/process331.pp' {$ELSE} process {$ENDIF} ; const // forwards poRunSuspended = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poRunSuspended; poWaitOnExit = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poWaitOnExit; poUsePipes = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poUsePipes; poStderrToOutPut = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poStderrToOutPut; poNoConsole = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poNoConsole; poNewConsole = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poNewConsole; poDefaultErrorMode = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poDefaultErrorMode; poNewProcessGroup = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poNewProcessGroup; poDebugProcess = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poDebugProcess; poDebugOnlyThisProcess = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poDebugOnlyThisProcess; poDetached = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poDetached; poPassInput = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poPassInput; poRunIdle = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} poRunIdle; swoNone = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoNone; swoHIDE = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoHIDE; swoMaximize = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoMaximize; swoMinimize = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoMinimize; swoRestore = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoRestore; swoShow = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoShow; swoShowDefault = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoShowDefault; swoShowMaximized = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoShowMaximized; swoShowMinimized = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoShowMinimized; swoshowMinNOActive = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoshowMinNOActive; swoShowNA = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoShowNA; swoShowNoActivate = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoShowNoActivate; swoShowNormal = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} swoShowNormal; suoUseShowWindow = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} suoUseShowWindow; suoUseSize = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} suoUseSize; suoUsePosition = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} suoUsePosition; suoUseCountChars = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} suoUseCountChars; suoUseFillAttribute = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} suoUseFillAttribute; type TDescriptorType = (dtStdIn, dtStdOut, dtStdErr); // forwards EProcess = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} EProcess; TProcessOptions = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} TProcessOptions; TStartupOptions = {$IFDEF USES_NEW_PROCESS} process331. {$ELSE} process. {$ENDIF} TStartupOptions; { TProcessWithRedirect } TProcessWithRedirect = class(TProcess) public procedure SetRedirection(AType: TDescriptorType; const AFile: String; AnOverwrite: Boolean); procedure ApplyWin7Fix; end; TNotifyProcessEndMethod = procedure(AnError: String) of object; { TNotifyProcessEnd } TNotifyProcessEnd = class(TThread) private fEvent: TNotifyProcessEndMethod; fProcess: TProcessWithRedirect; FErrMsg: String; protected procedure Execute; override; procedure DoEvent; public constructor Create(pProcess: TProcessWithRedirect; pEvent: TNotifyProcessEndMethod); end; const DBG_PROCESS_HAS_REDIRECT = {$IFDEF HAS_NEW_PROCESS} True {$ELSE} False {$ENDIF}; implementation { TProcessWithRedirect } procedure TProcessWithRedirect.SetRedirection(AType: TDescriptorType; const AFile: String; AnOverwrite: Boolean); {$IFDEF HAS_NEW_PROCESS} const FMODE: array [boolean] of TFileWriteMode = (fwmAppend, fwmTruncate); var d: TIODescriptor; {$ENDIF} begin if AFile = '' then exit; {$IFDEF HAS_NEW_PROCESS} case AType of dtStdIn: d := InputDescriptor; dtStdOut: d := OutputDescriptor; dtStdErr: d := ErrorDescriptor; end; d.FileName := AFile; d.FileWriteMode := FMODE[AnOverwrite]; {$ELSE} Assert(False, 'SetRedirections not available'); {$ENDIF} end; procedure TProcessWithRedirect.ApplyWin7Fix; begin {$IFDEF WINDOWS} {$IFDEF HAS_NEW_PROCESS} if (InputDescriptor.IOType <> iotDefault) or (OutputDescriptor.IOType <> iotDefault) or (ErrorDescriptor.IOType <> iotDefault) then begin if (InputDescriptor.IOType = iotDefault) then begin InputDescriptor.IOType := iotHandle; InputDescriptor.CustomHandle := 3; InputDescriptor.CustomHandleIsInheritable := True; InputDescriptor.AutoCloseCustomHandle := False; end; if (OutputDescriptor.IOType = iotDefault) then begin OutputDescriptor.IOType := iotHandle; OutputDescriptor.CustomHandle := 7; OutputDescriptor.CustomHandleIsInheritable := True; OutputDescriptor.AutoCloseCustomHandle := False; end; if (ErrorDescriptor.IOType = iotDefault) then begin ErrorDescriptor.IOType := iotHandle; ErrorDescriptor.CustomHandle := 11; ErrorDescriptor.CustomHandleIsInheritable := True; ErrorDescriptor.AutoCloseCustomHandle := False; end; end; {$ENDIF} {$ENDIF} end; { TNotifyProcessEnd } procedure TNotifyProcessEnd.Execute; begin try fProcess.Execute; except on E: Exception do FErrMsg := E.Message; end; Synchronize(@DoEvent); fProcess.Free; end; procedure TNotifyProcessEnd.DoEvent; begin fEvent(FErrMsg); end; constructor TNotifyProcessEnd.Create(pProcess: TProcessWithRedirect; pEvent: TNotifyProcessEndMethod); begin inherited Create(True); fProcess := pProcess; fProcess.Options := fProcess.Options + [poWaitOnExit]; fEvent := pEvent; FreeOnTerminate := True; Start; end; end.