AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi "SHFileOperation" beschwert sich bei geöffneten Dateien
Thema durchsuchen
Ansicht
Themen-Optionen

"SHFileOperation" beschwert sich bei geöffneten Dateien

Ein Thema von irata · begonnen am 5. Okt 2006 · letzter Beitrag vom 5. Okt 2006
Antwort Antwort
irata

Registriert seit: 5. Okt 2006
4 Beiträge
 
#1

"SHFileOperation" beschwert sich bei geöffneten Da

  Alt 5. Okt 2006, 10:05
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
  Mit Zitat antworten Zitat
Go2EITS

Registriert seit: 25. Jun 2006
519 Beiträge
 
Delphi 7 Personal
 
#2

Re: "SHFileOperation" beschwert sich bei geöffnete

  Alt 5. Okt 2006, 10:23
Tobias zeige mal die Procedure Code mit der
Zitat:
sh.fFlags := fof_Silent or FOF_NOCONFIRMATION or FOF_NOERRORUI;
Eigentlich darf keine Anzeige kommen, Dein Fehler liegt m.E. woanders. Ich glaube es liegt evtl. am Timer. Ach hier mal den Code, bitte.
  Mit Zitat antworten Zitat
irata

Registriert seit: 5. Okt 2006
4 Beiträge
 
#3

Re: "SHFileOperation" beschwert sich bei geöffnete

  Alt 5. Okt 2006, 10:38
Hallo,

hier die "Move" Routine:
Delphi-Quellcode:
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;
und hier die Timer Routine:
Delphi-Quellcode:
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;
Falls noch die anderen Proceduren benötigt werden nur fragen

Danke und Gruss

Tobias
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#4

Re: "SHFileOperation" beschwert sich bei geöffnete

  Alt 5. Okt 2006, 10:58
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.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
irata

Registriert seit: 5. Okt 2006
4 Beiträge
 
#5

Re: "SHFileOperation" beschwert sich bei geöffnete

  Alt 5. Okt 2006, 11:08
Zitat von SirThornberry:
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.
Ähm... das hört sich gut an! Wie öffnet man eine Datei exclusiv?

Bin nicht so der Delphi Crack... Programmiere normal meist in Perl.
  Mit Zitat antworten Zitat
Benutzerbild von MuTzE
MuTzE

Registriert seit: 24. Sep 2003
59 Beiträge
 
#6

Re: "SHFileOperation" beschwert sich bei geöffnete

  Alt 5. Okt 2006, 11:11
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;
  Mit Zitat antworten Zitat
Go2EITS

Registriert seit: 25. Jun 2006
519 Beiträge
 
Delphi 7 Personal
 
#7

Re: "SHFileOperation" beschwert sich bei geöffnete

  Alt 5. Okt 2006, 11:42
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:
// 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;
Das ist die Grundlage, dass Dein Timer auch funktionert.

Und? Klappts?
  Mit Zitat antworten Zitat
irata

Registriert seit: 5. Okt 2006
4 Beiträge
 
#8

Re: "SHFileOperation" beschwert sich bei geöffnete

  Alt 5. Okt 2006, 12:58
Danke für den guten Tipp. Jetzt klappt es!

Obwohl es
Result := hFile <> INVALID_HANDLE_VALUE; heissen müsste!

Und das mit dem Timer disablen könnte ich auch noch testen.


Danke an alle für die guten Tipps!!!
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.116 Beiträge
 
Delphi 11 Alexandria
 
#9

Re: "SHFileOperation" beschwert sich bei geöffnete

  Alt 5. Okt 2006, 13:05
Moin irata,

Zitat von irata:
Obwohl es
Result := hFile <> INVALID_HANDLE_VALUE; heissen müsste!
nein, muss es nicht, denn die Funktion heisst ja schliesslich "IsFileInUse", was genau dann der Fall ist, wenn man kein gültiges Handle erhält.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Go2EITS

Registriert seit: 25. Jun 2006
519 Beiträge
 
Delphi 7 Personal
 
#10

Re: "SHFileOperation" beschwert sich bei geöffnete

  Alt 5. Okt 2006, 13:11
@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
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:31 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