Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Dateiattribute und -zeitstempel kopieren (https://www.delphipraxis.net/132571-dateiattribute-und-zeitstempel-kopieren.html)

necromundo 15. Apr 2009 10:14


Dateiattribute und -zeitstempel kopieren
 
Hallo zusammen!

Ich bin grade dabei, eine Funktion zu schreiben, die die Attribute und Zeitstempel einer Datei auf eine andere zuvor kopierte Datei überträgt, so dass ich danach zwei identische Dateien habe, inklusiver aller Zeitstempel.
Allerdings gibt es Probleme damit, nach dem Kopieren ist nur das letzte Änderungsdatum und die Attribute gleich, der Rest funktioniert irgendwie nicht! :-(
Hier ist der Code:

Delphi-Quellcode:
function TForm1.transferdateiinfos(source,destination: widestring): boolean;
var
  hFind_s, hFind_d: THandle;
  FindFileData_s, FindFileData_d: WIN32_FIND_DATAW;
begin
  result := false;
  if source[length(source)] = '\' then setlength(source,length(source)-1);
  if destination[length(destination)] = '\' then setlength(destination,length(destination)-1);
  hFind_s := FindFirstFileW(PWideChar(source),FindFileData_s);
  hFind_d := FindFirstFileW(PWideChar(destination),FindFileData_d);
  if (hFind_s <> INVALID_HANDLE_VALUE) and (hFind_d <> INVALID_HANDLE_VALUE) then begin
    try
      findfiledata_d.ftCreationTime := findfiledata_s.ftCreationTime;
      findfiledata_d.ftLastWriteTime := findfiledata_s.ftLastWriteTime;
      findfiledata_d.ftLastAccessTime := findfiledata_s.ftLastAccessTime;
      findfiledata_d.dwFileAttributes := findfiledata_s.dwFileAttributes;
    finally
     Windows.FindClose(hFind_s);
     Windows.FindClose(hFind_d);
    end;
  end;
end;
Hat jemand eine Idee? Oder schonmal eine ähnliche Funktion geschrieben? ;-)
Ganz wichtig ist, dass Widestring-Dateinamen benutzt werden können!

VG, Benny

DeddyH 15. Apr 2009 10:38

Re: Dateiattribute und -zeitstempel kopieren
 
Ich denke, MSDN-Library durchsuchenSetFileTime ist das Richtige dafür.

necromundo 15. Apr 2009 10:45

Re: Dateiattribute und -zeitstempel kopieren
 
ich habe jetzt wie folgt geändert, aber trotzdem stimmen die zeitstempel nicht!

NewCreationTime, NewAccessTime, NewWriteTime: TFileTime;
Delphi-Quellcode:
NewCreationTime := findfiledata_s.ftCreationTime;
NewWriteTime := findfiledata_s.ftLastWriteTime;
NewAccessTime := findfiledata_s.ftLastAccessTime;
result := SetFileTime(hFind_d, @NewCreationTime, @NewAccessTime, @NewWriteTime);

DeddyH 15. Apr 2009 10:51

Re: Dateiattribute und -zeitstempel kopieren
 
Schau Dir mal diesen Thread an, ich hoffe, das hilft Dir weiter: http://www.delphipraxis.net/internal...t.php?t=121857

necromundo 15. Apr 2009 11:00

Re: Dateiattribute und -zeitstempel kopieren
 
ok, ich hab ihn mir angesehen, da gibt es also auch sowas wie getfiletime, äquivalent zu setfiletime, ich habs jetzt so umgeschrieben, aber immernoch der gleiche effekt!

Delphi-Quellcode:
GetFileTime(hFind_s, @NewCreationTime, @NewAccessTime, @NewWriteTime);
SetFileTime(hFind_d, @NewCreationTime, @NewAccessTime, @NewWriteTime);
in dem thread wird aber auch immer das "@" weggelassen, dann bekomme ich aber die compilermeldung, dass _FILETIME und PFileTime inkompatible typen sind!

DeddyH 15. Apr 2009 11:04

Re: Dateiattribute und -zeitstempel kopieren
 
Werden die Funktionen denn überhaupt aufgerufen (Breakpoint)?

necromundo 15. Apr 2009 11:12

Re: Dateiattribute und -zeitstempel kopieren
 
beim step by step kann ich in die funktionen irgendwie nicht reinspringen, und die werte der times ändern sich auch nicht! woran kann das liegen?

die handles bekommen aber einen gültigen wert zugewiesen, also kann da ja nicht der fehler liegen! :-/

p80286 15. Apr 2009 11:15

Re: Dateiattribute und -zeitstempel kopieren
 
Hallo zusammen,

schüchterner Einwurf:
könnte es sein, das LastAccessTime ein "Eigenleben" führt? Jedes mal wenn die Dateizeit gesetzt wird, wird auch LastAccessTime vom System neu gesetzt?

Gruß
K-H

necromundo 15. Apr 2009 11:20

Re: Dateiattribute und -zeitstempel kopieren
 
ja, das hatte ich auch schon überlegt! also dass lastaccesstime jedesmal beim schliessen des handles neu gesetzt wird! aber dann müsste es zumindest mit creationtime klappen, tuts aber auch nicht! :gruebel:

necromundo 15. Apr 2009 11:29

Re: Dateiattribute und -zeitstempel kopieren
 
ich sehe grade, dass die funktionen "getfiletime" und "setfiletime" false zurückliefern! :gruebel: aber warum??

DeddyH 15. Apr 2009 11:31

Re: Dateiattribute und -zeitstempel kopieren
 
Zitat:

Zitat von MSDN
If the function fails, the return value is zero. To get extended error information, call GetLastError.


necromundo 15. Apr 2009 11:38

Re: Dateiattribute und -zeitstempel kopieren
 
hab ich mir grade mal ausgeben lassen, er sagt, das handle ist ungültig!
allerdings düfte er gar nicht in den block kommen, wenn es ungültig wäre!
hier nochmal der aktuelle quelltext:

Delphi-Quellcode:
function TForm1.transferdateiinfos(source,destination: widestring): boolean;
var
  NewCreationTime, NewAccessTime, NewWriteTime: TFileTime;
  hFind_s, hFind_d: THandle;
  FindFileData_s, FindFileData_d: WIN32_FIND_DATAW;
begin
  result := false;
  if source[length(source)] = '\' then setlength(source,length(source)-1);
  if destination[length(destination)] = '\' then setlength(destination,length(destination)-1);
  hFind_s := FindFirstFileW(PWideChar(source),FindFileData_s);
  hFind_d := FindFirstFileW(PWideChar(destination),FindFileData_d);
  if (hFind_s <> INVALID_HANDLE_VALUE) and (hFind_d <> INVALID_HANDLE_VALUE) then begin
    try
      findfiledata_d.dwFileAttributes := findfiledata_s.dwFileAttributes;
      result := GetFileTime(hFind_s, @NewCreationTime, @NewAccessTime, @NewWriteTime);
      ShowMessage(SysErrorMessage(GetLastError));
      result := SetFileTime(hFind_d, @NewCreationTime, @NewAccessTime, @NewWriteTime);
    finally
     Windows.FindClose(hFind_s);
     Windows.FindClose(hFind_d);
    end;
  end;
end;

DeddyH 15. Apr 2009 11:43

Re: Dateiattribute und -zeitstempel kopieren
 
Zu FindFirstFile sagt das MSDN:
Zitat:

If the function fails or fails to locate files from the search string in the lpFileName parameter, the return value is INVALID_HANDLE_VALUE and the contents of lpFindFileData are indeterminate. To get extended error information, call the GetLastError function.

If the function fails because no matching files can be found, the GetLastError function returns ERROR_FILE_NOT_FOUND.
Vermutlich reicht die Abfage auf INVALID_HANDLE_VALUE nicht aus.

necromundo 15. Apr 2009 11:45

Re: Dateiattribute und -zeitstempel kopieren
 
hmmm, nach dem zuweisen des handles, sagt getlasterrror "der vorgang wurde erfolgreich beendet"
merkwürdig, merkwürdig... :gruebel:

ich benutze aber dieses findfirstfilew auch an anderen stellen, um größe, name oder attribute der datei zu bekommen, das funktioniert alles! :?:

p80286 15. Apr 2009 11:50

Re: Dateiattribute und -zeitstempel kopieren
 
Hallo necromundo,

in der Hilfe steht:
Zitat:

The FindFirstFile function opens a search handle and ...
was ich nicht zwangsläufig als Dateihandle interpretiere.
Die eigentlichen Daten stehen ja in WIN32_FIND_DATA .

was funktioniert (nicht schön aber geht):
Delphi-Quellcode:
var
  inf,outf:tfilestream;
  time1,time2,time3 : tfiletime;
begin
  inf:=tfilestream.Create('c:\temp\sha1.txt',fmopenread);
  outf:=tfilestream.Create('c:\temp\sha1_k.txt',fmopenreadwrite);
  GetFileTime(inf.Handle,@time1,@time2,@time3);
  SetFileTime(outf.Handle,@time1,@time2,@time3);
  outf.Free;
  inf.Free;
end;
Gruß
K-H

DeddyH 15. Apr 2009 11:55

Re: Dateiattribute und -zeitstempel kopieren
 
Oder CreateFile verwenden, wie es auch im MSDN steht (was ich selbst auch übersehen habe :oops:)

necromundo 15. Apr 2009 11:56

Re: Dateiattribute und -zeitstempel kopieren
 
ja, das könnte sein! das würde auch erklären, dass es keinen effekt hatte mit der ersten variante, die ich hier gepostet habe! wenn das search handle nicht wieder zurückgeschrieben wird...

aber soweit ich weiss, funktioniert der filestream nicht mit widestrings. :-(
ich habe bis jetzt aber auch noch keine möglichkeit gefunden, ein handle zu erstellen für einen widestring-dateinamen! :-/

necromundo 15. Apr 2009 11:58

Re: Dateiattribute und -zeitstempel kopieren
 
ah! moment!
createfilew gibt es ja! damit könnte ich zumindest das richtige handle zu der datei finden!
werde ich morgen mal probieren, aber jetzt habe ich erst einmal feierabend! ;-)

aber danke schonmal für die konstruktiven beiträge! :)

necromundo 16. Apr 2009 12:55

Re: Dateiattribute und -zeitstempel kopieren
 
So, das Problem ist behoben!
Die Vermutung, dass das letzte Zugriffsdatum sofort geändert wird, wenn die Datei in irgendeiner Weise angepackt wird, hat sich bewahrheitet. Also gestaltet sich der Kopiervorgang einer Datei etwas schwieriger als vermutet, wenn man wirklich alle Zeitstempel beibehalten und auch auf die kopierte Datei übertragen will:

Ich habe eine Datenstruktur angelegt für die Zeitstempel:
Delphi-Quellcode:
TZeitstempel = record
    creation: TFileTime;
    lastchange: TFileTime;
    lastaccess: TFileTime;
  end;
Danach zwei Funktionen zum Ermitteln und Schreiben der Zeitstempel:

Delphi-Quellcode:
function getZeitstempel(datei: widestring): TZeitstempel;
var
  dates: TZeitstempel;
  h: THandle;
begin
  if datei[length(datei)] = '\' then setlength(datei,length(datei)-1);
  h := CreateFileW(PWideChar(datei), $0080, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  GetFileTime(h, @dates.creation, @dates.lastchange, @dates.lastaccess);
  result := dates;
end;

function setZeitstempel(datei: widestring; daten: TZeitstempel): boolean;
var
  h: THandle;
begin
  if datei[length(datei)] = '\' then setlength(datei,length(datei)-1);
  h := CreateFileW(PWideChar(datei), $0100, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  result := SetFileTime(h, @daten.creation, @daten.lastchange, @daten.lastaccess);
end;
Beim CreateFileW, das $0080 bedeutet FILE_READ_ATTRIBUTES und das §0100 FILE_WRITE_ATTRIBUTES, über das Handle kann also nur auf die Dateiattribute zugegriffen werden.

Und der Part mit dem eigentlichen Kopiervorgang sieht dann so aus:

Delphi-Quellcode:
tempzeitstempel := getzeitstempel(quelle);
copyfilew(pwidechar(quelle),pwidechar(ziel),false);
setzeitstempel(quelle,tempzeitstempel);
setzeitstempel(ziel,tempzeitstempel);
Damit ist das Problem gelöst! :-D

Reinhard Kern 16. Apr 2009 15:25

Re: Dateiattribute und -zeitstempel kopieren
 
Zitat:

Zitat von necromundo
...Die Vermutung, dass das letzte Zugriffsdatum sofort geändert wird, wenn die Datei in irgendeiner Weise angepackt wird, hat sich bewahrheitet. Also gestaltet sich der Kopiervorgang einer Datei etwas schwieriger als vermutet, wenn man wirklich alle Zeitstempel beibehalten und auch auf die kopierte Datei übertragen will:
...

Hallo,

das stand so schon im vorigen Jahrhundert in MSDN - es gäbe sonst keine korrekte Kopier- und Backup-Software.

Gruss Reinhard


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