Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Probleme beim setzen des Änderungsdatums einer Datei (https://www.delphipraxis.net/102529-probleme-beim-setzen-des-aenderungsdatums-einer-datei.html)

gkoeder 30. Okt 2007 15:46


Probleme beim setzen des Änderungsdatums einer Datei
 
Hallo!

Ich muss bei einer größeren Anzahl von Office-Dateien die Metainformation "Kommentar" befüllen. Wichtig ist hierbei, dass das Datum der letzten Änderung an der Datei gleich bleibt (wird intern für Auswertungen herangezogen). Ich habe soweit ein kleines Tool zusammengebastelt, wo diese Aufgabenstellung erfüllt.

Der einfachheit halber verwende ich Funktionen aus der JCL. Der grundsätzliche Aufbau ist wie folgt:

Delphi-Quellcode:
var
 LineCounter: Integer;
 OldFileTime: tFileTime;
 OldDateTime: tDateTime;
 CurrentFileTime: tFiletime;
 CurrentDateTime: tDateTime;
 CurrentFile: String;
begin
 ...
 // Aktuellen Dateinamen in String schreiben zur besseren Übersichtlichkeit
 CurrentFile := Memo_FileList.Lines[LineCounter];
 // Überprüfen, ob die referenzierte Datei auch wirklich existiert
 if FileExists(CurrentFile) = True then
   Begin
     // Aktuelles Änderungsdatum der Datei erfassen
     // GetFileLastWrite returns the date/time that the specified file was last written
     // to. The return value is a UTC based TFileTime value which can be converted to
     // the familiar TDateTime by using FileTimeToDateTime function.
     OldFileTime := GetFileLastWrite(CurrentFile);
     OldDateTime := FileTimeToDateTime(OldFileTime);
     // Änderung an den Dateieigenschaften vornehmen
     If SetFileSummaryInfo(CurrentFile, FMTID_DocSummaryInformation, PIDDSI_CATEGORY, GetCategoryType) = False
     Then Memo_Log.Lines.Add('Setzen der Kategorie fehlgeschlagen: ' + CurrentFile);

     // Änderungsdatum wieder in Datei zurückschreiben (UTC-Format)
     // const DateTime: TDateTime ->
     // The date and time to set the file's last write stamp to. You must supply
     // the UTC based date and time. To convert from a local date and time use the
     // LocalDateTimeToDateTime function from JclDateTime.
     SetFileLastWrite(CurrentFile, OldDateTime);
   end else
   Begin
     Memo_Log.Lines.Add('Datei nicht gefunden: ' + CurrentFile);
   end;
 end;
Das ganze funktioniert auch eigentlich ganz gut. Das Problem besteht lediglich beim setzen des Änderungsdatums. Bei lokalen Dateien wird Datum/Uhrzeit korrekt gesetzt. Sobald ich aber Dateien auf einem Netzwerklaufwerk bearbeite (Windows 2k3 Server), dann stellt sich die Uhrzeit der letzten Änderung der Datei 2h vor. Das Datum wird korrekt übernommen. :shock:
Ich hab schon verschiedene Varianten und Funktionen ausprobiert - egal, immer ist der Timestamp nachher 2h älter. Hat jemand eine Ahnung, woran das liegen könnte (und wieso hier eine Unterscheidung zwischen lokalen Dateien und Dateien auf Netzwerklaufwerken vorliegt)? :?:

Vielen Dank vorab!

Gruß
Gerald

Luckie 30. Okt 2007 15:48

Re: Probleme beim setzen des Änderungsdatums einer Datei
 
Berücksichtigst du auch Sommer, Winterzeit und die Zeitzonen? Stimmt die Zeit vom Server?

gkoeder 30. Okt 2007 16:23

Re: Probleme beim setzen des Änderungsdatums einer Datei
 
Zitat:

Zitat von Luckie
Berücksichtigst du auch Sommer, Winterzeit und die Zeitzonen? Stimmt die Zeit vom Server?

Sommer- und Winterzeit (eigentlich die ganzen Zeiteinstellungen) werden per Policy verteilt und ist bei allen System identisch. Der Windows-Server befindet sich im gleichen LAN wie der Client - Zeitzonen oder ähnliches sollten auch kein Problem darstellen.

himitsu 30. Okt 2007 16:32

Re: Probleme beim setzen des Änderungsdatums einer Datei
 
hab hier keine JCL installiert, aber da GetFileLastWrite die Zeit als TFileTime ausgibt und SetFileLastWrite diese als TDateTime entgegennimmt, vermute ich mal das die Intern noch einiges machen ... müßte mal wer nachsehn, ob die JCL da nicht was an der Zeit manipuliert.

versuch es mal direkt mit der WinAPI:
Delphi-Quellcode:
var
LineCounter: Integer;
CurrentFile: String;
FileHandle: THandle;
OldFileTime: tFileTime;
begin
...
// Aktuellen Dateinamen in String schreiben zur besseren Übersichtlichkeit
CurrentFile := Memo_FileList.Lines[LineCounter];
// Überprüfen, ob die referenzierte Datei auch wirklich existiert
if FileExists(CurrentFile) then
   Begin
     // Aktuelles Änderungsdatum der Datei erfassen
     FileHandle := CreateFile(PChar(CurrentFile), GENERIC_READ,
       FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, nil);
     GetFileTime(FileHandle, nil, nil, OldFileTime);
     CloseHandle(FileHandle);

     // Änderung an den Dateieigenschaften vornehmen
     If not SetFileSummaryInfo(CurrentFile, FMTID_DocSummaryInformation, PIDDSI_CATEGORY, GetCategoryType) Then
       Memo_Log.Lines.Add('Setzen der Kategorie fehlgeschlagen: ' + CurrentFile);

     // Änderungsdatum wieder in Datei zurückschreiben (UTC-Format)
     FileHandle := CreateFile(PChar(CurrentFile), GENERIC_WRITE,
       FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, nil);
     SetFileTime(FileHandle, nil, nil, OldFileTime);
     CloseHandle(FileHandle);
   end else
   Begin
     Memo_Log.Lines.Add('Datei nicht gefunden: ' + CurrentFile);
   end;
end;
PS: dieses =true und =false ... wäre besser, wenn du dir solche Vergleiche abgewöhnst
(gibt dazu einige Threads im Forum, warum sowas Probleme beeiten könnte)
und dann hab ich das =false erst übersehn und hab mich grad gewundert warum die Fehlermeldung "Setzen der Kategorie fehlgeschlagen" bei 'nem "positivem"Ergebnis ausgelöst wird. (if not xyz = wenn nicht xy ... versteht sich och leichter ^^)



theoretisch sollte sich die Zeit nicht ändern, denn selbst wenn die Zeit in 'ner falschen Zeitzone ausgelesen wird, wird dieses beim Schreiben in der falschen Zeitzohne wieder behoben, denn:


SetFileTime und GetFileTime lesen unter NTFS die Zeit in der lokale Zeit aus,
wobei diese Zeit auf der Platte in UTC gespichert ist und bei Auslsen umgewandelt wird

beim Schreiben dann genau andersrum, also die übergebene Zeit wird von Lokal nach UTC umgewandelt und gespeichert.

unter FAT wird diese Umwandlung zwar auch gemacht (microsoft hat leider keine Extra Funktion dafür bereit gestellt, oder mal neue FAT-Treiber), allerdings wird dort die Zeit in LocalTime gespeichert.
(weßhalb auch zur Zeitumstellung sich die Zeiten z.B. auf USB-Sticks ändern)


so, aber jetzt warum es eigentlich egal ist:
die Zeitzone wird zwar beim Auslesen geändert, aber beim Schreiben wird diese Änderung rückgängig gemacht und da hier die Zeit in der Vaiable gleich bleibt, sollte somit die Originalzeit wiederhergestellt werden.

ebenso sollte es beim LAN sein, denn egal wie die Zeit da drüben ist, sie wird von da ausgelesen und auch wieder dahin zurückgeschrieben.

es könnte natürlich auch sein, daß die nötigen Treiber für den Zugriff über's LAN was ändern,
also falls GetFileLastWrite und SetFileLastWrite nüschts "falsch" machen.

gkoeder 30. Okt 2007 17:26

Re: Probleme beim setzen des Änderungsdatums einer Datei
 
Hab gerade die WinAPI-Funktionen ausprobiert und das setzen des korrekten Dateidatums und Uhrzeit funktioniert nun perfekt! Danke für den Hinweis und die Lösung!

Zitat:

Zitat von himitsu
...
versuch es mal direkt mit der WinAPI:
Delphi-Quellcode:
var
LineCounter: Integer;
CurrentFile: String;
FileHandle: THandle;
OldFileTime: tFileTime;
begin
...
// Aktuellen Dateinamen in String schreiben zur besseren Übersichtlichkeit
CurrentFile := Memo_FileList.Lines[LineCounter];
// Überprüfen, ob die referenzierte Datei auch wirklich existiert
if FileExists(CurrentFile) then
   Begin
     // Aktuelles Änderungsdatum der Datei erfassen
     FileHandle := CreateFile(PChar(CurrentFile), GENERIC_READ,
       FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, nil);
     GetFileTime(FileHandle, nil, nil, OldFileTime);
     CloseHandle(FileHandle);

     // Änderung an den Dateieigenschaften vornehmen
     If not SetFileSummaryInfo(CurrentFile, FMTID_DocSummaryInformation, PIDDSI_CATEGORY, GetCategoryType) Then
       Memo_Log.Lines.Add('Setzen der Kategorie fehlgeschlagen: ' + CurrentFile);

     // Änderungsdatum wieder in Datei zurückschreiben (UTC-Format)
     FileHandle := CreateFile(PChar(CurrentFile), GENERIC_WRITE,
       FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, nil);
     SetFileTime(FileHandle, nil, nil, OldFileTime);
     CloseHandle(FileHandle);
   end else
   Begin
     Memo_Log.Lines.Add('Datei nicht gefunden: ' + CurrentFile);
   end;
end;
...

Zitat:

Zitat von himitsu
PS: dieses =true und =false ... wäre besser, wenn du dir solche Vergleiche abgewöhnst
(gibt dazu einige Threads im Forum, warum sowas Probleme beeiten könnte)
und dann hab ich das =false erst übersehn und hab mich grad gewundert warum die Fehlermeldung "Setzen der Kategorie fehlgeschlagen" bei 'nem "positivem"Ergebnis ausgelöst wird. (if not xyz = wenn nicht xy ... versteht sich och leichter ^^)

Hmm ... ich verwende diese Vergleiche relativ häufig, um auf die Rückgabewerte entsprechend reagieren zu können. Wie kann ich dies besser machen bzw. kannst Du mir einen entsprechenden Thread nennen?

Danke!

Gruß
Gerald

DeddyH 30. Okt 2007 17:52

Re: Probleme beim setzen des Änderungsdatums einer Datei
 
Zitat:

Zitat von gkoeder
Wie kann ich dies besser machen ...

Delphi-Quellcode:
//statt
if FileExists(bla) = true then...
//besser
if FileExists(bla) then...

//und statt
if FileExists(bla) = false then...
//besser
if not FileExists(bla) then...

himitsu 31. Okt 2007 02:01

Re: Probleme beim setzen des Änderungsdatums einer Datei
 
und einer der Threads wäre wohl
http://www.delphipraxis.net/internal...ght=true+false


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