Autor Beitrag
Burgpflanze
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 67

Windows2000 Prof. SP4
Delphi7 Enterprise
BeitragVerfasst: Di 25.03.03 15:07 
Diese kleine Komponente dient zum Umlenken des Standard-Outputs von Shell-Processen, die aus einer Kylix-Anwendung heraus gestartet wurden.

Das Event "OnOutput" liefert den Standard-Output Zeile für Zeile.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
unit ShellProcess;

interface

uses
  Classes, Libc, SysUtils;

type
  EProcessError = class(Exception);

  TOutputEvent = procedure(Sender: TObject; const AOutput: Stringof object;

  TShellProcess = class(TComponent)
  private
    FFileName: String;
    FParams: String;
    FIOFile: PIOFile;
    FOnOutput: TOutputEvent;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function Execute(const AFileName: String = ''const AParams: String = ''): Boolean;
    procedure CloseProcess;
  published
    property FileName: String read FFileName write FFileName;
    property Params: String read FParams write FParams;
    property OnOutput: TOutputEvent read FOnOutput write FOnOutput;
  end;

implementation

uses
  StrUtils;
  
const
  OUT_TO = '2>&1';

{ TShellProcess }

procedure TShellProcess.CloseProcess;
begin
  if Assigned(FIOFile) then
  begin
    pclose(FIOFile);
    FIOFile := nil;
  end;
end;

constructor TShellProcess.Create(AOwner: TComponent);
begin
  inherited;
  FFileName := '';
  FParams := '';
  FIOFile := nil;
end;


destructor TShellProcess.Destroy;
begin
  CloseProcess;
  inherited;
end;

function TShellProcess.Execute(const AFileName, AParams: String): Boolean;
const
  BUF_SIZE = 1000;
var
  line: PChar;
  com, str, txt: String;
  rb: Integer;
begin
  if Assigned(FIOFile) then
  begin
    raise EProcessError.Create('A process is already running.');
    Exit;
  end;

  if AFileName <> '' then FFileName := AFileName;
  if AParams <> '' then FParams := AParams;

  FFileName := Trim(FFileName);
  FParams := Trim(FParams);

  if FFileName = '' then
  begin
    raise EProcessError.Create('Property "FileName" is empty.');
    Exit;
  end;

  com := FFileName + ' ' + FParams;
  if RightStr(com, Length(OUT_TO)) <> OUT_TO then com := com + ' ' + OUT_TO;

  FIOFile := popen(PChar(com), 'r');
  if not Assigned(FIOFile) then
  begin
    raise EProcessError.Create(String(strerror(errno)));
    Exit;
  end;

  GetMem(line, BUF_SIZE);

  while FEOF(FIOFile) = 0 do
  begin
    rb := fread(line, 1, BUF_SIZE, FIOFile);
    SetLength(Txt, Length(txt) + rb);
    MemCpy(@txt[Length(txt) - (rb - 1)], line, rb);

    while Pos(#10, txt) > 0 do
    begin
      str := copy(txt,1,pos(#10,txt)-1);
      if Assigned(FOnOutput) then FOnOutput(Self, str);
      txt := Copy(txt, Pos(#10, txt) + 1, Length(txt));
    end;
  end;

  CloseProcess;
  wait(nil);
  Freemem(line, BUF_SIZE);

  Result := True;
end;

end.