Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Werkzeuge (https://www.delphipraxis.net/63-sonstige-werkzeuge/)
-   -   GhostScript: Zugriffsverletzung (https://www.delphipraxis.net/204844-ghostscript-zugriffsverletzung.html)

haentschman 6. Jul 2020 08:50


GhostScript: Zugriffsverletzung
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallöle...8-)

Ich habe eine Unit erstellt, welche mir ein erzeugtes PDF nochmal etwas verkleinert. (wegen Datenmenge bei Übertragung). Soweit so weit so gut. Die Klasse funktioniert seit 1,5 Jahren...oder so. Die Funktion die ich benötige, wird bei jedem PDF Druck verwendet.

In einem Programmteil fliegt mir neuerdings die function mit einer Zugriffsverletzung um die Ohren. :evil:

Gegeben:
* eine EXE vom Server
* eine gsdll32.dll vom Server

Problem:
Auf den meisten Arbeitsstationen funktioniert das problemlos. Letzte Woche hatte ich 2 Arbeitsstationen wo es bei einer funktionierte, bei der Anderen Zugriffsverletzung. Am nächsten Tag funktionierte auch die andere nicht...gleiche EXE, gleiche DLL:evil:

Code:
Delphi-Quellcode:
function TGhostscript.LoadDLL(PathDLL: string): Boolean;
var
  CurrentDLLPath: string;
begin
  if PathDLL = '' then
  begin
    CurrentDLLPath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + conDLLName;
  end
  else
  begin
    CurrentDLLPath := PathDLL;
  end;
  FDLLHandle := LoadLibrary(PChar(CurrentDLLPath));
  if FDLLHandle > 0 then
  begin
    FGsInit := GetProcAddress(FDLLHandle, 'gsapi_new_instance');
    Result := (FGsInit(@FGsInstance, nil) = 0);
    if Result then
    begin
      FGsApiInitWithArgs := GetProcAddress(FDLLHandle, 'gsapi_init_with_args');
      FGsApiExit := GetProcAddress(FDLLHandle, 'gsapi_exit');
      FGsApiDeleteInstance := GetProcAddress(FDLLHandle, 'gsapi_delete_instance');
    end
    else
    begin
      FOnError(Self, 'Die Ghostscript Instanz konnte nicht erzeugt werden.');
      Result := False;
    end;
  end
  else
  begin
    FOnError(Self, Format('Die Ghostscript DLL %s wurde nicht geladen.', [QuotedStr(CurrentDLLPath)]));
    Result := False;
  end;
end;

function TGhostscript.PDFShrink(FileName: string): Boolean;
var
  TargetFileName: string;
begin
  if FDLLHandle = 0 then
  begin
    LoadDLL(FDLLPath);
  end;
  try
    TargetFileName := IncludeTrailingPathDelimiter(ExtractFilePath(FileName)) + conFileNameTempPDF;
    SetLength(FParameters, 7);
    FParameters[0] := '';
    FParameters[1] := '-dNOPAUSE';
    FParameters[2] := '-dBATCH';
    FParameters[3] := '-dPDFSETTINGS=/ebook';
    FParameters[4] := '-sDEVICE=pdfwrite';
    FParameters[5] := PAnsiChar(AnsiString('-sOutputFile=' + TargetFileName));
    FParameters[6] := PAnsiChar(AnsiString(FileName));

    Result := (FGsApiInitWithArgs(FGsInstance, Length(FParameters), FParameters) = 0); //(Zeile 118)

  finally
    FGsApiExit(FGsInstance); //(Zeile 121)
  end;

  if Result then
  begin
    if not TToolsIO.IsFileInUse(FileName) then
    begin
      TFile.Delete(FileName);
      RenameFile(TargetFileName, FileName);
    end;
  end
end;
Frage:
1. Wo sollte ich ansetzen?
2. Windows Update verantwortlich?
3. neueste DLL benutzen? (verwendete 1 Jahr alt)

Danke...

PS: In der Entwicklung habe ich den Fehler noch nie gesehen...

DeddyH 6. Jul 2020 11:08

AW: GhostScript: Zugriffsverletzung
 
Ich würde zumindest die Rückgaben von GetProcAddress gegenprüfen und bei Misserfolg loggen o.ä. Außerdem ist LoadDLL eine Funktion, deren Rückgabe Du auch nicht prüfst. Das wären so meine ersten Ansätze.

haentschman 6. Jul 2020 11:33

AW: GhostScript: Zugriffsverletzung
 
Moin...:P
Zitat:

Außerdem ist LoadDLL eine Funktion, deren Rückgabe Du auch nicht prüfst
...Boah ey. :oops:
Das Handle sagt ja nix über das erfolgreiche Init aus...Schande. Baue ich um. :wink:

Unabhängig davon: Warum geht es hier und da nicht?

PS: In der Entwicklung kann ich den Fehler nicht reproduzieren. Alle habe die gleiche EXE und DLL. Da bleibt eigentlich nur loggen...oder?

DeddyH 6. Jul 2020 12:24

AW: GhostScript: Zugriffsverletzung
 
Japp, es genügt ja, wenn Du Fehler/unerwartete Rückgaben loggst.

Delphi.Narium 6. Jul 2020 12:40

AW: GhostScript: Zugriffsverletzung
 
Davor
Delphi-Quellcode:
  FDLLHandle := LoadLibrary(PChar(CurrentDLLPath));
würde ich mal grundsätzlich ein
Delphi-Quellcode:
If FileExists(CurrentDLLPath) then begin
einbauen. Gibt's die DLL nicht, wird eine Fehlermeldung ausgegeben oder geloggt oder ...

Eventuell dauert das Laden der DLL oder der Zugriff auf den Server ... zu lange oder fällt sporadisch aus oder Lesefehler, so dass die DLL in "kaputtem" Zustand geladen wird ...

haentschman 6. Jul 2020 12:55

AW: GhostScript: Zugriffsverletzung
 
:P
Zitat:

Japp, es genügt ja, wenn Du Fehler/unerwartete Rückgaben loggst.
...jetzt logge ich alle Rückgaben. Wenn LoadDLL fehlschlägt wird nicht mehr "verkleinert"
Zitat:

würde ich mal grundsätzlich einIf FileExists(CurrentDLLPath) then
...erledigt. :wink:
Delphi-Quellcode:
function TGhostscript.LoadDLL(PathDLL: string): Boolean;
var
  CurrentDLLPath: string;
begin
  if PathDLL = '' then
  begin
    CurrentDLLPath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + conDLLName;
  end
  else
  begin
    CurrentDLLPath := PathDLL;
  end;

  if TFile.Exists(CurrentDLLPath) then
  begin
    FDLLHandle := LoadLibrary(PChar(CurrentDLLPath));
  end;

  if FDLLHandle > 0 then
  begin
    FGsInit := GetProcAddress(FDLLHandle, 'gsapi_new_instance');
    Result := (FGsInit(@FGsInstance, nil) = 0);
    if Result then
    begin
      FGsApiInitWithArgs := GetProcAddress(FDLLHandle, 'gsapi_init_with_args');
      if not Assigned(FGsApiInitWithArgs) then
      begin
        FOnError(Self, 'GsApiInitWithArgs konnte nicht ermittelt werden.');
        FLog.Log('GsApiInitWithArgs konnte nicht ermittelt werden');
        Result := False;
      end;
      FGsApiExit := GetProcAddress(FDLLHandle, 'gsapi_exit');
      if not Assigned(FGsApiExit) then
      begin
        FOnError(Self, 'GsApiExit konnte nicht ermittelt werden.');
        FLog.Log('GsApiExit konnte nicht ermittelt werden');
        Result := False;
      end;
      FGsApiDeleteInstance := GetProcAddress(FDLLHandle, 'gsapi_delete_instance');
      if not Assigned(FGsApiDeleteInstance) then
      begin
        FOnError(Self, 'GsApiDeleteInstance konnte nicht ermittelt werden.');
        FLog.Log('GsApiDeleteInstance konnte nicht ermittelt werden');
        Result := False;
      end;
    end
    else
    begin
      FOnError(Self, 'Die Ghostscript Instanz konnte nicht erzeugt werden.');
      FLog.Log('Die Ghostscript Instanz konnte nicht erzeugt werden.');
      Result := False;
    end;
  end
  else
  begin
    FOnError(Self, Format('Die Ghostscript DLL %s wurde nicht geladen.', [QuotedStr(CurrentDLLPath)]));
    FLog.Log('Die Ghostscript DLL wurde nicht geladen');
    Result := False;
  end;
end;
Danke erstmal...

Delphi.Narium 6. Jul 2020 13:11

AW: GhostScript: Zugriffsverletzung
 
mmmmmhhhh.... weiß nicht so recht:
Delphi-Quellcode:
if TFile.Exists(CurrentDLLPath) then
begin
  FDLLHandle := LoadLibrary(PChar(CurrentDLLPath));
end;

if FDLLHandle > 0 then
Wat iss denne, wenn FDLLHandle vor dem
Delphi-Quellcode:
if TFile.Exists(CurrentDLLPath) then
'nen Wert > 0 hat?

Von mir aus sowas:
Delphi-Quellcode:
if not TFile.Exists(CurrentDLLPath) then begin
  // Fehlerloggen
  Result := false;
  exit;
end;
aber keinerfalls bei fehlender DLL noch irgendwas in der Routine machen außer Result := false;
Eventuell noch hinter das erste Begin am Anfang der Routine ein
Delphi-Quellcode:
Result := False;
als grundsätzlich erstmal festgelegter Rückgabewert der Funktion, der nur bei Erfolg auf true geändert wird.
Delphi-Quellcode:
function TGhostscript.LoadDLL(PathDLL: string): Boolean;
var
  CurrentDLLPath: string;
begin
  Result := false;
  if PathDLL = '' then
  begin
    CurrentDLLPath := IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) + conDLLName;
  end
  else
  begin
    CurrentDLLPath := PathDLL;
  end;

  if TFile.Exists(CurrentDLLPath) then
  begin
    FDLLHandle := LoadLibrary(PChar(CurrentDLLPath));
    if FDLLHandle > 0 then
    begin
      FGsInit := GetProcAddress(FDLLHandle, 'gsapi_new_instance');
      Result := (FGsInit(@FGsInstance, nil) = 0);
      if Result then
      begin
        FGsApiInitWithArgs := GetProcAddress(FDLLHandle, 'gsapi_init_with_args');
        if not Assigned(FGsApiInitWithArgs) then
        begin
          FOnError(Self, 'GsApiInitWithArgs konnte nicht ermittelt werden.');
          FLog.Log('GsApiInitWithArgs konnte nicht ermittelt werden.');
          Result := False;
        end;
        FGsApiExit := GetProcAddress(FDLLHandle, 'gsapi_exit');
        if not Assigned(FGsApiExit) then
        begin
          FOnError(Self, 'GsApiExit konnte nicht ermittelt werden.');
          FLog.Log('GsApiExit konnte nicht ermittelt werden.');
          Result := False;
        end;
        FGsApiDeleteInstance := GetProcAddress(FDLLHandle, 'gsapi_delete_instance');
        if not Assigned(FGsApiDeleteInstance) then
        begin
          FOnError(Self, 'GsApiDeleteInstance konnte nicht ermittelt werden.');
          FLog.Log('GsApiDeleteInstance konnte nicht ermittelt werden.');
          Result := False;
        end;
      end
      else
      begin
        FOnError(Self, 'Die Ghostscript Instanz konnte nicht erzeugt werden.');
        FLog.Log('Die Ghostscript Instanz konnte nicht erzeugt werden.');
        Result := False;
      end;
    end
    else
    begin
      FOnError(Self, Format('Die Ghostscript DLL %s wurde nicht geladen.', [QuotedStr(CurrentDLLPath)]));
      FLog.Log('Die Ghostscript DLL wurde nicht geladen.');
      Result := False;
    end;
  end
  else
  begin
    FOnError(Self, Format('Die Ghostscript DLL %s wurde nicht gefunden.', [QuotedStr(CurrentDLLPath)]));
    FLog.Log('Die Ghostscript DLL wurde nicht gefunden.');
    Result := False;
  end;
end;

DeddyH 6. Jul 2020 13:36

AW: GhostScript: Zugriffsverletzung
 
Delphi-Quellcode:
FGsInit := GetProcAddress(FDLLHandle, 'gsapi_new_instance');
// Prüfung vergessen ;-)
if not Assigned(FGsInit then
  raise SomeException.Create('gsapi_new_instance nicht implementiert');
Result := (FGsInit(@FGsInstance, nil) = 0);

hoika 6. Jul 2020 13:45

AW: GhostScript: Zugriffsverletzung
 
Hallo,
ich würde auch mal den Virenscanner prüfen.

Ausserdem würde ich mit MadExcept mal eine Exe bauen,
die dir genau sagt, in welcher Zeile die Zugriffsverletzung auftritt.

haentschman 6. Jul 2020 16:41

AW: GhostScript: Zugriffsverletzung
 
Zeile 118 siehe 1 Post...:wink:
Zitat:

// Prüfung vergessen ;-)
...nee oder? Das kommt, wenn man auf mehreren Baustellen unterwegs ist. :?
Zitat:

Wat iss denne, wenn FDLLHandle vor dem if TFile.Exists(CurrentDLLPath) then 'nen Wert > 0 hat?
...ja nix. :wink: Dann ist diese, und nur diese Variable, mit dem Handle der DLL gefüllt. Vor dem Druck wird das Print Objekt, incl. dem GhostScript Objekt erzeugt. Nach dem Ausführen des Druckes (1-3000 Rechnungen) wird das Print Objekt, incl. dem GhostScript Objekt freigeben, und damit das Handle der DLL
Delphi-Quellcode:
FreeLibrary(FDLLHandle);
_
Test:
Delphi-Quellcode:
Result := (FGsApiInitWithArgs(FGsInstance, Length(FParameters), FParameters) = 0);
_
DLL 9.27 = True (Macht eine temporäre Datei und benennt diese dann um)
DLL 9.52 = False (nix)
...selbe Parameter, Namen, Pfade. :?


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:20 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