![]() |
SHFileOperation löst Exception aus ?!
Delphi-Quellcode:
Die Funktion CopyDir wird im Programm an verschieden Stellen verwendet. Beim Kopiervorgang eines größeren Verzeichnisses (ca. 6,5 MB in 162 Dateien) löst SHFileOperation hin und wieder eine Exception aus. Entweder Fehler 7 (The storage control blocks were destroyed) oder der Thread in dem der Vorgang abläuft stürzt ganz ab ohne einfangen der Exception. Alleine das wundert mich schon, da ein try .. except Block um die Funktion gebaut ist.
.
. function CopyDir(DirFrom, DirTo: string; Flags : integer = 0; bErrorHandler : boolean = True) : integer; var shellinfo: TSHFileOpStruct; FromBuf, ToBuf : Array [0..255] of char; begin If Not DirectoryExists(DirTo) Then begin Result := -1; Exit; end; Fillchar(shellinfo, Sizeof(shellinfo), 0 ); FillChar(FromBuf, Sizeof(FromBuf), 0 ); FillChar(ToBuf, Sizeof(ToBuf), 0 ); StrPCopy(FromBuf, DirFrom); StrPCopy(ToBuf, DirTo); with shellinfo do begin Wnd := 0; wFunc := FO_COPY; pFrom := @FromBuf; pTo := @ToBuf; fFlags := FOF_SIMPLEPROGRESS or FOF_NOCONFIRMATION; end; Repeat try Result := SHFileOperation(shellinfo); SHFreeNameMappings(Cardinal(shellinfo.hNameMappings)); except Result := GetLastError; end; if Not bErrorHandler then Exit; if Result <> 0 then 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 !', [DirFrom, DirTo, GetFormatErrorMessage(Result)]), mtWarning, [mbAbort, mbRetry], -1) <> mrRetry then break; end; until Result = 0; end; . . Usage: . . CopyDir(IncludeTrailingPathDelimiter(GetCurrentDir) + DIRDATA + '\Dokumentation\*', sTemp); . . ![]() Weiß jemand Rat ? Googlen hat mir jedenfalls nicht geholfen :( |
msi-Installer ?!
Kann es evtl. sein, dass das Problem von dem msi-Installer verursacht wird ? Mein Programm startet nämlich 2 Installationsprogramme mit ShellExecAndWait bevor dieser Fehler auftritt. Wenn man mein angebrochenen Install dann erneut startet, haben die beiden msi-Installer nichts mehr zu installieren und mein Programm läuft Fehler durch.
|
Re: SHFileOperation löst Exception aus ?!
Tja, probier es aus.
|
Re: SHFileOperation löst Exception aus ?!
Moin Orakel,
nur zur Info: Der MSI-Installer kann zwar theoretisch mehrmals gleichzeitig laufen, da es aber Tabllen gibt, die nicht von mehreren Instanzen gleichzeitig genutzt werden können, kann es leicht zu Problemen kommen. |
Re: SHFileOperation löst Exception aus ?!
Ich habe jetzt alle Aufrufe mit Synchronize in den Hauptthread verlegt und die Aufrufe des MSI-Installers testweise ausgeschaltet. Der Fehler tritt immer noch auf !!! Was kann den bloß falsch sein ??? Das Problem tritt auf allen Computern auf, die ich zur Verfügung habe (Win2000, WinXP) und ist unabhängig von der Größe des verfügbaren Speichers.
Wie kann man dieses Problem lösen ??? Sieht schlecht aus, wenn der Kunde sein neu erworbenes Produkt installiert und gleich die oben genannte Fehlermeldung auftritt ... |
Re: SHFileOperation löst Exception aus ?!
Also mir gefällt das Füllen von TSHFileOpStruct nicht.
Du hast 1.) die Struktur nicht mit 0 vorbelegt 2.) feste Puffer benutzt, die sehr leicht überschrieben werden können. => Zerstörung des Stacks Besser so:
Delphi-Quellcode:
FillChar(shellinfo, SizeOf(shellinfo), #0); // zuerst mit #0 füllen
DirFrom := DirFrom+#0+#0 DirTo := DirTo+#0#0; with shellinfo do begin Wnd := GetDesktopWindow; wFunc := FO_COPY; pFrom := PChar(DirFrom); pTo := PChar(DirTo); fFlags := FOF_SIMPLEPROGRESS or FOF_NOCONFIRMATION; end; |
Re: SHFileOperation löst Exception aus ?!
Danke für den Tipp, aber
der Buffer wurde bereits initialisiert
Delphi-Quellcode:
und die statischen Variablen habe ich entfernt
Fillchar(shellinfo, Sizeof(shellinfo), 0 );
Delphi-Quellcode:
Leider ohne Erfolg:
with shellinfo do
begin Wnd := 0; wFunc := FO_COPY; pFrom := PChar(DirFrom + #0 + #0); pTo := PChar(DirTo + #0 + #0); fFlags := FOF_SIMPLEPROGRESS or FOF_NOCONFIRMATION; . . ![]() Hast sonst noch jemand eine Idee ??? |
Re: SHFileOperation löst Exception aus ?!
Statische Variablen gibt es in Delphi nicht, meint ihr Literale oder was meint ihr?
An dieser Stelle solltest du definitiv einen String mit deinen Daten vorbelegen (wie oben gesehen) und dann den String bei pFrom und pTo in folgender Form zuweisen.
Delphi-Quellcode:
Ansonsten werde ich mal kurz drüberschauen.
with shellinfo do
begin Wnd := 0; wFunc := FO_COPY; pFrom := @DirFrom[1]; pTo := @DirTo[1]; fFlags := FOF_SIMPLEPROGRESS or FOF_NOCONFIRMATION; . . Nachtrag: Was soll das denn?
Delphi-Quellcode:
Bei integralen Datentypen weist man immer Werte zu, wozu nullst du denn einen Pointer aus? Oder was ist FromBuf und ToBuf? Wenn es Strings sind, ist es komplett falsch.
FillChar(FromBuf, Sizeof(FromBuf), 0 );
FillChar(ToBuf, Sizeof(ToBuf), 0 ); |
Re: SHFileOperation löst Exception aus ?!
Hi,
mir fällt dieser Ausdruck bei Dir auf:
Delphi-Quellcode:
Also ich glaube nicht, dass Du diesen verwenden muss, wenn Du keine Name Mappings verwendest...
SHFreeNameMappings(Cardinal(shellinfo.hNameMappings));
Ansonsten kannst Du das kopieren ja mal mit meiner ![]() mfG mirage228 |
Re: SHFileOperation löst Exception aus ?!
@Olli:
FromBuf und ToBuf ist in der ursprünglichen Variante verwendet worden (array [0..255] of char). @mirage228: Ich weiß, dass ich keine Mappings verwende. War auch nur ein Versuch, aber der Fehler tritt mit oder ohne SHFreeNameMappings auf :( |
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:
PS: Sorry, hat etwas länger gedauert wegen Mittagbrot ;)
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; Nachtrag: :oops: Fehlerchen im formatierten String korrigiert ... |
Re: SHFileOperation löst Exception aus ?!
@Olli: Since try, aber auch mit Deinem Coding tritt der Fehler noch auf.
Zitat:
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. |
Re: SHFileOperation löst Exception aus ?!
Zitat:
Zitat:
Zitat:
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. |
Re: SHFileOperation löst Exception aus ?!
![]() 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:
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.
CopyDir(IncludeTrailingPathDelimiter(GetCurrentDir) + DIRDATA + '\Dokumentation\*', sTemp);
Workaround:
Delphi-Quellcode:
Fertig :thumb:
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); |
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:
mfG
FOF_NO_CONNECTED_ELEMENTS = $2000; // don't operate on connected elements.
mirage228 |
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 05:19 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz