![]() |
"SHFileOperation" beschwert sich bei geöffneten Da
Hallo,
ich habe ein kleines Delphi Programm geschrieben, welches alle paar Minuten ein Verzeichnis auf neue Dateien überprüft, und wenn welche da sind, werden diese per Indy "TIdMultiPartFormDataStream" an einen Web-Server übertragen werden. Nun will ich natürlich nur Dateien übertragen, die auch wirklich komplett geschrieben wurden. Bei grösseren Dateien kann dies ja einen Moment dauern. Daher verschiebe ich die Dateien aus dem Verzeichnis erst in ein Temp-Verzeichnis und von da aus auf den Web-Server. Zum Verschieben der Dateien benutzte ich "SHFileOperation". Mit sh.fFlags := fof_Silent or FOF_NOCONFIRMATION or FOF_NOERRORUI; Allerdings erscheint trotzdem immer eine Message-Box, mit "<datei> kann nicht kopiert werden: Die Datei wird von einer anderen Person bzw. einem anderen Programm verwendet." Und genau diesen Fehler möchte ich gerne umgehen. Falls es zu dem Fehler kommt, soll einfach eine Exception ausgelöst werden und dann mit der nächsten Datei fortgefahren werden. Und diese Datei dann im nächsten Schritt übertragen werden. Momentan blockiert das ganze Programm, solange die Fehlermeldung nicht bestätigt wurde... Hat da irgendwer einen Tipp!?!?! Danke und Gruss Tobias |
Re: "SHFileOperation" beschwert sich bei geöffnete
Tobias zeige mal die Procedure Code mit der
Zitat:
|
Re: "SHFileOperation" beschwert sich bei geöffnete
Hallo,
hier die "Move" Routine:
Delphi-Quellcode:
und hier die Timer Routine:
function TFmMain.MoveFile(const AOldName, ANewName: string ): boolean;
var sh: TSHFileOpStruct; begin try FillChar(sh, sizeOf(TSHFileOpStruct), 0); sh.Wnd := Application.Handle; sh.wFunc := fo_Move; sh.pFrom := PChar(AOldName + #0); sh.pTo := PChar(ANewName + #0); sh.fFlags := fof_Silent or FOF_NOCONFIRMATION or FOF_NOERRORUI; Result := ShFileOperation(sh) = 0; except Result := false; end; end;
Delphi-Quellcode:
Falls noch die anderen Proceduren benötigt werden nur fragen ;-)
procedure TFmMain.ExportTimerTimer(Sender: TObject);
begin if ( not FmOption.checkOptions( CheckExport ) ) then LogExport( 'Options empty, please check!' ) else if ( not FmOption.RegExpEnable ) then else DoExport(); end; procedure TFmMain.doExport(); var Search: TSearchRec; FileList: TStringList; FilePath: String; i: integer; begin if ( DoingExport ) then else begin DoingExport := true; ExportCounter := ExportCounter + 1; FileList := TStringList.Create(); if ( FindFirst( FmOption.RegExpPath + '\*.*', faAnyFile, Search ) = 0 ) then begin try repeat if ( (Search.Name <> '.') and (Search.Name <> '..')) then begin FileList.Add( Search.Name ); end; until FindNext( Search ) <> 0; finally FindClose( Search ); end; end; FileList.Sort(); for i := 0 to FileList.Count - 1 do begin FilePath := FmOption.RegExpPath + '\' + FileList[i]; exportFile( FilePath, true ); end; DoingExport := false; if (ExportCounter mod 10 = 0 ) then LogExport( '--- Mark ---' ); end; end; procedure TFmMain.exportFile( const filepath: string;const remove: boolean ); var FileName, FileTmp, Path: string; Stream: TIdMultiPartFormDataStream; Resp: TMemoryStream; result: Boolean; begin filename := ExtractFileName( filepath ); Stream := TIdMultiPartFormDataStream.Create; Resp := TMemoryStream.Create(); result := true; Resp.Clear(); Resp.Seek( 0, soFromBeginning ); try if ( remove ) then begin Path := FmOption.RegTmpPath; FileTmp := FmOption.RegTmpPath + '\' + FileName; if ( not MoveFile( FilePath, FileTmp ) ) then begin LogExport( '[Error] Can''t move file ' + FilePath + ' to ' + FileTmp ); result := false; end; end else begin Path := ExtractFilePath( FilePath ); FileTmp := FilePath; end; if ( result ) then begin chdir( Path ); Stream.AddFile( 'file', FileName, 'text/plain' ); HTTPClient.Request.Username := FmOption.RegUsername; HTTPClient.Request.Password := FmOption.RegPassword; HTTPClient.Request.BasicAuthentication := true; HTTPClient.Post( 'https://' + FmOption.RegServer + '/files/import', Stream, Resp ); lbExpLastFile.Caption := 'Last filename: ' + FileName; lbExpLastFile.Width := 220; end; except on e : exception do begin LogExport( '[Error] sending file ' + FileName ); result := false; end; end; Stream.Destroy(); Resp.Seek(0,soFromBeginning); Resp.Free; if ( result ) then if ( remove and not RemoveFile( FileTmp ) ) then LogExport( '[Error] Can''t delete file ' + FileTmp ) else LogExport( 'Export: ' + FileName ) else if ( remove and not MoveFile( FileTmp, FilePath ) ) then LogExport( '[Error] Can''t export file and move file ' + FileTmp + ' to ' + FilePath ) else LogExport( '[Error] Can''t export file ' + FileName ); end; Danke und Gruss Tobias |
Re: "SHFileOperation" beschwert sich bei geöffnete
also das verschieben finde ich recht unpraktisch. Versuche doch einfach die Dateien exclusiv zu öffnen. Schlägt dies fehl ist die Datei in Verwendung. Wenn es nicht fehl schlägt kannst du die Datei direkt hochladen.
|
Re: "SHFileOperation" beschwert sich bei geöffnete
Zitat:
Bin nicht so der Delphi Crack... Programmiere normal meist in Perl. |
Re: "SHFileOperation" beschwert sich bei geöffnete
Probiers mal damit:
Delphi-Quellcode:
function IsFileInUse(Path: string): boolean;
var hFile: THandle; begin Result := False; if not FileExists(Path) then Exit; hFile := CreateFile(pchar(Path), GENERIC_READ or GENERIC_WRITE or GENERIC_EXECUTE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); Result := hFile = INVALID_HANDLE_VALUE; if not Result then CloseHandle(hFile); end; |
Re: "SHFileOperation" beschwert sich bei geöffnete
Nimm mal Mutzes Vorschlag.
Mit Deiner Timerroutine komme ich nicht klar. Der Timer hat generell eine Schwäche. Wenn er usgeführt wird, und die Procedure nicht fertig mit kopieren ist, wird der Timer, ohne Rücksicht auf die ausgeführte Proceduren/Funktionen wieder nach der abgelaufenen Zeit von vorne beginnen. Wenn dann die Aktionen noch im Gange sind, wie z. B. kopieren, bekommst Du Probleme. Lösung: In der Timer Routine am Anfang: Timer1.Enabled:=False; und am Ende der Timer Routine: Timer1.Enabled:=True; Wirkt Wunder! Und wenn Du noch ein IsFileInUse(Path) verwendest, bist Du auf der sicheren Seite:
Delphi-Quellcode:
Das ist die Grundlage, dass Dein Timer auch funktionert.
// Natürlich ist Timer1.enabled:=False; bei Dir in der Procedure zuvor wie oben gesetzt!
if IsFileInUse(Path) then begin Timer1.enabled:=True; //Sonst bleibt der Timer aus... Exit; //Raus aus der Procedur/Function end; Und? Klappts? |
Re: "SHFileOperation" beschwert sich bei geöffnete
Danke für den guten Tipp. Jetzt klappt es!
Obwohl es
Delphi-Quellcode:
heissen müsste!
Result := hFile <> INVALID_HANDLE_VALUE;
Und das mit dem Timer disablen könnte ich auch noch testen. Danke an alle für die guten Tipps!!! |
Re: "SHFileOperation" beschwert sich bei geöffnete
Moin irata,
Zitat:
|
Re: "SHFileOperation" beschwert sich bei geöffnete
@Seehase
Na da bin aber froh, wunderte mich schon. @irata Na das mit dem Timer erspart Ärger: Du musstest sonst alle Proceduren/Functionen, die im Timer aufgerufen werden, prüfen, ob sie noch in "arbeit" sind. Alles viel zu schwammig. Besser: Timer aus, alles abarbeiten, Timer an. Fertig. Ganz einfach. CU! Go2EITS |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:38 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