Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi SHFileOperation löst Exception aus ?! (https://www.delphipraxis.net/46892-shfileoperation-loest-exception-aus.html)

Olli 12. Okt 2005 11:45

Re: SHFileOperation löst Exception aus ?!
 
So, habe es mir angeguckt und mit dem Lesen der Doku scheinst du's ja nicht gerade zu halten :zwinker:

Du kannst mir sicher beispielsweise plausibel machen, wieso du SHFreeNameMappings() verwendest?!

Und wie du Typen (DWORD und Integer zB) und Bedeutungen durcheinanderwürfelst ist eine wahre Freude. So benutzt du Integer als Rückgabetyp, weist aber einen GetLastError()-Wert zu, wobei dieser DWORD ist - bei nichtvorhandenem Verzeichnis wird's -1. Putzigerweise weist du dem gleichen Rückgabewert auch noch das Ergebnis von SHFileOperation() zu, obwohl dort eindeutig steht, daß 0 bedeutet erfolgreich (entspricht GetLastError) und alles andere bedeutet nicht erfolgreich. Dort steht aber nirgends, daß der Rückgabewert ein Fehlercode ist!

Probiere mal, ob folgendes funktioniert.
Delphi-Quellcode:
function CopyDir(DirFrom, DirTo, ProgessTitle: string; Flags: Integer = 0; bErrorHandler: Boolean = True): DWORD;
var
  shellinfo: TSHFileOpStruct;
begin
  // Bail out if the target directory does not exist
  if not DirectoryExists(DirTo) then
  begin
    Result := ERROR_PATH_NOT_FOUND;
    Exit;
  end;

  // Initialize structure
  ZeroMemory(@shellinfo, sizeof(shellinfo));
  // Finalize the strings to be appropriately terminated
  DirFrom := DirFrom + #0#0;
  DirTo := DirTo + #0#0;

  with shellinfo do
  begin
    Wnd := GetDesktopWindow();
    wFunc := FO_COPY; // Copy action
    pFrom := @DirFrom[1]; // Source file(s)/directories
    pTo := @DirTo[1]; // Target directory
    fFlags := FOF_SIMPLEPROGRESS or FOF_NOCONFIRMATION or Flags;
    Flags := fFlags; // For cleaner code
    lpszProgressTitle := @ProgessTitle[1];
  end;

  try
    while ((SHFileOperation(shellinfo) <> NO_ERROR) and (bErrorHandler)) do
    begin
      if MessageDlg(Format('Das Verzeichnis'#13#10#13#10
        + '''%s'''#13#10#13#10
        + 'kann nicht nach'#13#10#13#10
        + '''%s'''#13#10#13#10
        + 'kopiert werden.'#13#10#13#10
        + 'Grund: %s'#13#10#13#10
        + 'Soll der Vorgang erneut versucht werden ?'#13#10#13#10
        + 'Wenn Sie ''Abbrechen'' drücken, muss das Verzeichnis'#13#10
        + 'oder die Dateien manuell kopiert werden !',
        [PChar(DirFrom), PChar(DirTo), GetFormatErrorMessage(GetLastError())]),
        mtWarning, [mbAbort, mbRetry], -1) <> mrRetry then
        break;
    end;
  finally
    if (Flags and FOF_WANTMAPPINGHANDLE <> 0) then
      SHFreeNameMappings(THandle(shellinfo.hNameMappings));
    Result := GetLastError();
  end;
end;
PS: Sorry, hat etwas länger gedauert wegen Mittagbrot ;)

Nachtrag: :oops: Fehlerchen im formatierten String korrigiert ...

Orakel-von-Delphi 12. Okt 2005 12:23

Re: SHFileOperation löst Exception aus ?!
 
@Olli: Since try, aber auch mit Deinem Coding tritt der Fehler noch auf.

Zitat:

Integer -2147483648..2147483647 32 Bit, mit Vorzeichen

.
.

DWORD (Double Word) repräsentiert einen vorzeichenlosen 4-Byte-Integer. Er wird primär für Windows-API-Aufrufe eingesetzt. Die C++ Version ist nur unter Windows verfügbar.
Ich konnte mir auch nicht vorstellen, dass nur wg. dem Unterschied signed/unsigned der Fehler in Erscheinung tritt, da die Länge der Variablen gleich ist :)

Ich bitte oben noch mal genau zu lesen: Das Problem tritt nicht immer auf ! Aber immer beim letzten Kopiervorgang mit über 100 Dateien und ca. 6.5 MB. Die Funktion "CopyDir" wir vorher min. 5x ohne Probleme aufgerufen.

Olli 12. Okt 2005 12:33

Re: SHFileOperation löst Exception aus ?!
 
Zitat:

Zitat von Orakel-von-Delphi
Zitat:

Integer -2147483648..2147483647 32 Bit, mit Vorzeichen

.
.

DWORD (Double Word) repräsentiert einen vorzeichenlosen 4-Byte-Integer. Er wird primär für Windows-API-Aufrufe eingesetzt. Die C++ Version ist nur unter Windows verfügbar.

Das ist, denke ich, allen hier klar. Was du mir mit der C++-Version sagen willst, weiß ich noch nicht ... :roll:

Zitat:

Zitat von Orakel-von-Delphi
Ich konnte mir auch nicht vorstellen, dass nur wg. dem Unterschied signed/unsigned der Fehler in Erscheinung tritt, da die Länge der Variablen gleich ist :)

Die meisten Buffer-Overflow-Löcher basieren auf solchen Dingen ... obwohl es hier unwahrscheinlich war. Dein Code enthielt aber formale Fehler, auf die ich dich aufmerksam machen wollte. Ob es deswegen klappt ist erstmal zweitrangig, denn da können wir uns jetzt dran machen ;)

Zitat:

Zitat von Orakel-von-Delphi
Ich bitte oben noch mal genau zu lesen: Das Problem tritt nicht immer auf ! Aber immer beim letzten Kopiervorgang mit über 100 Dateien und ca. 6.5 MB. Die Funktion "CopyDir" wir vorher min. 5x ohne Probleme aufgerufen.

In diesem Falle sieht es für mich nach 2 Möglichkeiten aus:
1. Die API-Funktion ist fehlerhaft implementiert - dann kannst du nichts machen.
2. Das was bei dir drumherum steht ist von Relevanz und kann das verursachen. In diesem Fall mußt du wohl den Code rausrücken. Denn keiner hier kann deinen Fehler sonst nachvollziehen.

Orakel-von-Delphi 12. Okt 2005 14:59

Re: SHFileOperation löst Exception aus ?!
 
http://bugtrack.sporleder.de/image/ordner_lnk_datei.JPG

Problem solved !

Ich habe mir jetzt mal den Order angesehen, der kopiert wird. Man glaubt wirklich kaum, was die Ursache ist :wall:

Im Order existiert eine html-Datei, die mit einem Ordner verküpft ist (was man erst sieht, wenn man versucht eines von beiden umzubenennen). Der Witz an der Sache ist, dass die Dateien für den Installer auf einer Server-Platte stehen und mit einem Command-Batch (mehrere xcopy-Befehle) auf die lokale Platte kopiert werden. Von dort aus wird dann der eigentliche Installer zusammengestellt und wiederum auf eine andere Server-Platte kopiert. Bei diesen Aktionen wandert die blöde Verknüpfung Datei-Ordner immer mit. Und genau da liegt auch die Ursache für den Fehler:

Der Ordner wurde mit

Delphi-Quellcode:
CopyDir(IncludeTrailingPathDelimiter(GetCurrentDir) + DIRDATA + '\Dokumentation\*', sTemp);
kopiert. Dabei kommt SHFileOperation offenbar in eine Rekursion, weil es so dämlich programmiert worden ist die betriebssystemeigenen Eigenarten des Dateisystems zu erkennen. Dabei werden dann wohl die "Speichersteuerblöcke" zerstört.

Workaround:

Delphi-Quellcode:
CopyDir(IncludeTrailingPathDelimiter(GetCurrentDir) + DIRDATA + '\Dokumentation\*.pdf' + #0 +
                 IncludeTrailingPathDelimiter(GetCurrentDir) + DIRDATA + '\Dokumentation\*.htm' + #0 +
                 IncludeTrailingPathDelimiter(GetCurrentDir) + DIRDATA + '\Dokumentation\*.html' + #0 +
                 IncludeTrailingPathDelimiter(GetCurrentDir) + DIRDATA + '\Dokumentation\*.doc' + #0 +
                 IncludeTrailingPathDelimiter(GetCurrentDir) + DIRDATA + '\Dokumentation\*.rtf',
                 sTemp);
Fertig :thumb:

mirage228 12. Okt 2005 15:43

Re: SHFileOperation löst Exception aus ?!
 
Hi,

hast Du in diesem Fall mal den FOF_NO_CONNECTED_ELEMENTS (siehe PSDK) ausprobiert?

Ich meine, dass dieser in Delphi nicht definiert ist.
Also einfach selber deklarieren oder meine Unit von oben verwenden:
Delphi-Quellcode:
 FOF_NO_CONNECTED_ELEMENTS = $2000; // don't operate on connected elements.
mfG
mirage228

Orakel-von-Delphi 12. Okt 2005 16:00

Re: SHFileOperation löst Exception aus ?!
 
Schon klar, aber dann musste man erst einmal auf einen Blick erkennen, dass beide miteinander verbunden sind. Der Explorer klärt einen über diese Tatsache erst bei dem Versuch, die Datei od. den Ordner umzubenennen, auf.
Und der Explorer, xcopy etc. kopieren ja auch ohne zu meckern ...


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:48 Uhr.
Seite 2 von 2     12   

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