Einzelnen Beitrag anzeigen

Benutzerbild von MaBuSE
MaBuSE

Registriert seit: 23. Sep 2002
Ort: Frankfurt am Main (in der Nähe)
1.837 Beiträge
 
Delphi 10 Seattle Enterprise
 
#18

AW: Doskonsole nutzen und Rückgabewerte einlesen

  Alt 28. Jul 2021, 12:31
Hallo,
sorry wenn ich diesen alten Beitrag wieder rauskrame, aber mein Problem ist hier wohl am besten aufgehoben, da ich den hier veröffentlichen Quelltext verwende.

Mein Problem (Aufgabenstellung):
Ich möchte die Aufrufe von dcc32 protokollieren, um zu sehen, in welcher Reihenfolge und mit welchen Parametern dcc32 aufgerufen wird.

Umsetzung:
Ich habe einen kleinen Wrapper um dcc32 geschrieben.
Der loggt die Aufrufe und wenn eine dcc32_org.exe (Kopie der originalen dcc32.exe) vorhanden ist, wird diese auch aufgerufen und die Ausgabe geloggt.
(Dazu habe ich die GetConsoleOutput von hier verwendet.)

-> Das funktioniert auch meistens, aber manchmal auch nicht

Mein Problem (der Fehler):
Im Log steht für jeden Eintrag:
Code:
40705308-0001: rem cd /d C:\Temp\DevExpress\VCL\Library\RS27
40705308-0002: "C:\Program Files (x86)\Embarcadero\Studio\21.0\Bin\dcc32.exe" "C:\Temp\DevExpress\VCL\Library\RS27\dxCoreRS27.dpk" -B -U"C:\Temp\DevExpress\VCL\Library\RS27" -I"C:\Temp\DevExpress\VCL\Library\RS27" -R"C:\Program Files (x86)\Embarcadero\Studio\21.0\lib\win32\release;C:\Temp\DevExpress\VCL\Library\RS27" -NU"C:\Temp\DevExpress\VCL\Library\RS27" -LE"C:\Temp\DevExpress\VCL\Library\RS27" -LN"C:\Temp\DevExpress\VCL\Library\RS27"   -NS"WinApi;Vcl;System;System.Win;Vcl.Imaging;Data;Data.Win;Bde;Xml;Xml.Win;Vcl.Shell;VclTee;Datasnap;IBX" -DSHAREPACKAGES -NB"C:\Temp\DevExpress\VCL\Library\RS27" -NH"C:\Temp\DevExpress\VCL\Library\RS27" -JL -W-UNSUPPORTED_CONSTRUCT
40705308-0003:  rem Embarcadero Delphi for Win32 compiler version 34.0
40705308-0004:  rem Copyright (c) 1983,2021 Embarcadero Technologies, Inc.
40705308-0005:  rem Fatal: F1026 File not found: 'Files.dpr'
Alle Aufrufe geben den Fehler
Code:
Fatal: F1026 File not found: 'Files.dpr'
aus, aber die Packages werden erzeugt.

Der Aufruf ohne Wrapper funktioniert und auch der Aufruf von dcc32_org.exe funktioniert ohne Fehler.
Code:
 C:\Temp\DevExpress\VCL\Library\RS27>"C:\Program Files (x86)\Embarcadero\Studio\21.0\Bin\dcc32_org.exe" "C:\Temp\DevExpress\VCL\Library\RS27\dxCoreRS27.dpk" -B -U"C:\Temp\DevExpress\VCL\Library\RS27" -I"C:\Temp\DevExpress\VCL\Library\RS27" -R"C:\Program Files (x86)\Embarcadero\Studio\21.0\lib\win32\release;C:\Temp\DevExpress\VCL\Library\RS27" -NU"C:\Temp\DevExpress\VCL\Library\RS27" -LE"C:\Temp\DevExpress\VCL\Library\RS27" -LN"C:\Temp\DevExpress\VCL\Library\RS27"   -NS"WinApi;Vcl;System;System.Win;Vcl.Imaging;Data;Data.Win;Bde;Xml;Xml.Win;Vcl.Shell;VclTee;Datasnap;IBX" -DSHAREPACKAGES -NB"C:\Temp\DevExpress\VCL\Library\RS27" -NH"C:\Temp\DevExpress\VCL\Library\RS27" -JL -W-UNSUPPORTED_CONSTRUCT
Embarcadero Delphi for Win32 compiler version 34.0
Copyright (c) 1983,2021 Embarcadero Technologies, Inc.
dxCoreRS27.dpk(67)
68 lines, 0.48 seconds, 1273428 bytes code, 209496 bytes data.

Frage:
Hat jemand eine Ahnung woran das liegen könnte?

Danke im Voraus.


Der Quelltext (auf das wesentliche reduziert):
Delphi-Quellcode:
program DCC32_Dummy;

{$APPTYPE CONSOLE}

// Ersatz für DCC32.exe in Delphi Installation um BuildSkripts zu analysieren
// z.B. DevExpress
// Diese Version ruft (falls vorhanden) *_org.exe mit den übergebenen Parametern auf.

uses
  SysUtils, Windows, Classes;

const
  Filename = 'C:\TEMP\DCC32.LOG';
var
  Programmstart: Integer;
  Zeile: integer = 0;

function GetConsoleOutput(const Command : string;
                          Output, Errors : TStringList) : Boolean;
var
  Buffer : array[0..255] of Char;
  CreationFlags : DWORD;
  NumberOfBytesRead : DWORD;
  PipeErrorsRead : THandle;
  PipeErrorsWrite : THandle;
  PipeOutputRead : THandle;
  PipeOutputWrite : THandle;
  ProcessInfo : TProcessInformation;
  SecurityAttr : TSecurityAttributes;
  StartupInfo : TStartupInfo;
  Stream : TMemoryStream;
  sCmd : string;
begin
  //Initialisierung ProcessInfo
  FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);

  //Initialisierung SecurityAttr
  FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
  SecurityAttr.nLength := SizeOf(TSecurityAttributes);
  SecurityAttr.bInheritHandle := True;
  SecurityAttr.lpSecurityDescriptor := nil;

  //Pipes erzeugen
  CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
  CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);

  //Initialisierung StartupInfo
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  StartupInfo.cb := SizeOf(TStartupInfo);
  StartupInfo.hStdInput := 0;
  StartupInfo.hStdOutput := PipeOutputWrite;
  StartupInfo.hStdError := PipeErrorsWrite;
  StartupInfo.wShowWindow := SW_HIDE;
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;

  CreationFlags := CREATE_DEFAULT_ERROR_MODE or
                   CREATE_NEW_CONSOLE or
                   NORMAL_PRIORITY_CLASS;
  sCmd:=Command;
  UniqueString(sCmd);
  if CreateProcess(nil,
                   (PChar(sCmd)),
                   nil,
                   nil,
                   True,
                   CreationFlags,
                   nil,
                   PChar(GetCurrentDir),
                   StartupInfo,
                   ProcessInfo) then
  begin
    Result := True;
    //Write-Pipes schließen
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsWrite);

    //Ausgabe Read-Pipe auslesen
    Stream := TMemoryStream.Create;
    try
      while ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil) do
      begin
        Stream.Write(Buffer, NumberOfBytesRead);
      end;
      Stream.Position := 0;
      Output.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    CloseHandle(PipeOutputRead);

    //Fehler Read-Pipe auslesen
    Stream := TMemoryStream.Create;
    try
      while ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil) do
      begin
        Stream.Write(Buffer, NumberOfBytesRead);
      end;
      Stream.Position := 0;
      Errors.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    CloseHandle(PipeErrorsRead);

    WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    CloseHandle(ProcessInfo.hProcess);
  end
  else
  begin
    Result := False;
    CloseHandle(PipeOutputRead);
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsRead);
    CloseHandle(PipeErrorsWrite);
  end;
end;

{ TMyLog }

type
  TMyLog = class(TObject)
  private
    Log: TextFile;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Add(const s: string);
  end;

constructor TMyLog.Create;
begin
  inherited;
  ForceDirectories(ExtractFilePath(Filename));
  AssignFile(Log, Filename);
  if FileExists(Filename) then
  begin
    Append(Log);
  end
  else
  begin
    ReWrite(Log);
  end;
end;

destructor TMyLog.Destroy;
begin
  CloseFile(Log);
  inherited;
end;

procedure TMyLog.Add(const s: string);
begin
  Inc(Zeile);
  WriteLn(Log, Format('%.8d-%.4d: %s', [ProgrammStart, Zeile, s]));
  Flush(Log);
end;

var
  i, j: Integer;
  App, Params: string;
  sl1, sl2: TStringList;
  MyLog: TMyLog;
begin
  Programmstart := DateTimeToTimeStamp(now).Time;
  try
    MyLog := TMyLog.Create;
    try
      MyLog.Add('rem cd /d '+GetCurrentDir);
      MyLog.Add(CmdLine);
    finally
      MyLog.Free;
    end;

    // Wenn *_org.exe da ist, dann diese mit Parametern starten
    App := ChangeFileExt(ParamStr(0), '_org.exe');
// WriteLn(App);
    if FileExists(App) then
    begin
      for i := 1 to ParamCount do Params := Params + #32 + ParamStr(i);
// WriteLn(Params);
      sl1 := TStringList.Create;
      sl2 := TStringList.Create;
      try
        GetconsoleOutPut(App + ' ' + Params, sl1, sl2);
        MyLog := TMyLog.Create;
        try
          for j := 0 to sl1.Count-1 do
          begin
            MyLog.Add(' rem ' + sl1[j]);
            WriteLn(sl1[j]);
          end;
          for j := 0 to sl2.Count-1 do
          begin
            MyLog.Add(' rem ERROR:' + sl2[j]);
            WriteLn(sl1[j]);
          end;
        finally
          MyLog.Free;
        end;
      finally
        sl1.Free;
        sl2.Free;
      end;
    end;
    except
    on E: Exception do
      Writeln('Es ist ein Fehler aufgetreten:',#13#10,E.ClassName, ': ', E.Message);
  end;
end.
(°¿°) MaBuSE - proud to be a DP member
(°¿°) MaBuSE - proud to be a "Rüsselmops" ;-)
  Mit Zitat antworten Zitat