Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Zugriffsverletzung bei Benutzung von Pipes (https://www.delphipraxis.net/158038-zugriffsverletzung-bei-benutzung-von-pipes.html)

Neutral General 3. Feb 2011 09:14

Zugriffsverletzung bei Benutzung von Pipes
 
Hallo,

Ich kann grad nicht verstehen, warum mir mein Code Probleme macht...
Ich öffne .bat Dateien und lesen deren Ausgabe aus und Leite Eingaben wieder an die Batch weiter.

Mein Code ist im Prinzip relativ übersichtlich:

Delphi-Quellcode:
procedure TForm1.btStartClick(Sender: TObject);
var si: TStartupInfo;
    pi: TProcessInformation;
    cnt, br: Cardinal;
    Buff: Pointer;
    SA: TSecurityAttributes;
    Dest: AnsiString;
begin
  if od.Execute then
  begin
    edBatch.Text := od.FileName;

    SA.nLength := SizeOf(TSecurityAttributes);
    SA.lpSecurityDescriptor := nil;
    SA.bInheritHandle := true;

    CreatePipe(FPipeOutRead,FPipeOutWrite,@SA,0);
    CreatePipe(FPipeInRead,FPipeInWrite,@SA,0);

    FillChar(si,SizeOf(TStartupInfo),0);
    si.cb := SizeOf(TStartupInfo);
    si.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
    si.wShowWindow := SW_HIDE;
    si.hStdOutput := FPipeOutWrite;
    si.hStdError := FPipeOutWrite;
    si.hStdInput := FPipeInRead;

    CreateProcess(nil,PChar(od.FileName),nil,nil,true,CREATE_NEW_CONSOLE,nil,nil,si,pi);
    try
      repeat
        cnt := 0;
        PeekNamedPipe(FPipeOutRead,nil,0,nil,@cnt,nil);
        if cnt > 0 then
        begin
          GetMem(Buff,cnt);
          try
            FillChar(Buff^,cnt,0);
            ReadFile(FPipeOutRead,Buff^,cnt,br,nil);
            if br > 0 then
            begin
              SetLength(Dest,br);
              try
                OemToCharA(Buff,@Dest[1]);
                Memo1.Lines.Text := Memo1.Lines.Text + String(Dest); // <----
              finally
                SetLength(Dest,0);
              end;
            end;
          finally
            FreeMem(Buff);
          end;
        end;
        Application.ProcessMessages;
      until FClosing;
    finally
      CloseHandle(pi.hThread);
      CloseHandle(pi.hProcess);

      CloseHandle(FPipeOutRead);
      CloseHandle(FPipeOutWrite);
      CloseHandle(FPipeInRead);
      CloseHandle(FPipeInWrite);
    end;
  end;
end;

procedure TForm1.btEingabeClick(Sender: TObject);
var br: Cardinal;
    InStr: AnsiString;
begin
  InStr := AnsiString(edEingabe.Text) + #13#10;
  WriteFile(FPipeInWrite,InStr[1],Length(InStr),br,nil);
  edEingabe.Clear;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  FClosing := true;
end;
Jetzt kommt es manchmal (Ich schreibe hektisch Daten in die Pipe (btEingabeClick)) dazu, dass an der im Code markierten Stelle eine AV auftritt. Kann aber nicht nachvollziehen warum. Der Debugger will mir auch nicht den Inhalt von "Dest" anzeigen.
Dann kommt es in 99% aller Fälle dazu, dass ich eine Zugriffsverletzung bekomme wenn ich das Programm beende. Das kann ich leider auch nicht verstehen :(

Kann mir da vllt. jemand helfen?

Edit: Sehe grade meine Pipe-Handles sind nicht optimal per try-finally geschützt, aber das sollte für mein Problem keine Bedeutung haben.

Gruß
Neutral General

p80286 3. Feb 2011 09:36

AW: Zugriffsverletzung bei Benutzung von Pipes
 
Warum machst Du es nicht so:
Delphi-Quellcode:
Memo1.Lines.Add(Dest);
und vertraust auf eine implizite Umwandlung?

Gruß
K-H

Dezipaitor 3. Feb 2011 09:54

AW: Zugriffsverletzung bei Benutzung von Pipes
 
Schau mal hier:
Delphi-Quellcode:
CreateProcess(nil,PChar(od.FileName),nil,nil,true,CREATE_NEW_CONSOLE,nil,nil,si,pi);
Du verwendest sicher Delphi >= 2009? Dann ist CreateProcess = CreateProcessW.

Zitat:

Zitat von http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.

Du brauchst also ne extra Stringvariable dafür.

Neutral General 3. Feb 2011 09:57

AW: Zugriffsverletzung bei Benutzung von Pipes
 
Zitat:

Zitat von p80286 (Beitrag 1079264)
Warum machst Du es nicht so:
Delphi-Quellcode:
Memo1.Lines.Add(Dest);
und vertraust auf eine implizite Umwandlung?

Gruß
K-H

Weil mir Lines.Add einen Zeilenumbruch einfügt, den ich nicht will.

Zitat:

Zitat von Dezipaitor (Beitrag 1079270)
Schau mal hier:
Delphi-Quellcode:
CreateProcess(nil,PChar(od.FileName),nil,nil,true,CREATE_NEW_CONSOLE,nil,nil,si,pi);
Du verwendest sicher Delphi >= 2009? Dann ist CreateProcess = CreateProcessW.

Zitat:

Zitat von http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.

Du brauchst also ne extra Stringvariable dafür.

Das kann ich machen. Allerdings kracht es ja nicht bei CreateProcess sondern irgendwann während der Prozess schon läuft und ich die Pipes auslese und reinschreibe.

p80286 3. Feb 2011 10:42

AW: Zugriffsverletzung bei Benutzung von Pipes
 
Na dann nimm halt OemToCharW und verdoppele die Länge, bzw definiere Dest gleich als String .

Gruß
K-H

Das man denInhalt von Dest nicht sehen kann stört mich, hast Du mal versucht Dest vorher zu initialisieren?


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:34 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz