[fpc-pascal] SetFileTime
José Mejuto
joshyfun at gmail.com
Wed May 3 11:35:50 CEST 2023
El 03/05/2023 a las 8:48, Carsten Bager via fpc-pascal escribió:
> I am trying to change the file date on a SYMLINK (not the file that the
> link points to).
> Does anyone know if there is a method for this under Windows.
> Carsten
Hello,
Attached is a dirty implementation of "touch" for junctions that I need
in the past. I think it can help you to do the same over other kind of
links.
Have a nice day.
-------------- next part --------------
program touchjunction;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes, SysUtils, windows, CustApp
{ you can add units after this };
const
FILE_FLAG_OPEN_REPARSE_POINT=DWORD($00200000);
FileTimeBase = -109205.0;
FileTimeStep: Extended = 24.0 * 60.0 * 60.0 * 1000.0 * 1000.0 * 10.0; // 100 nSek per Day
type
{ TTouchJunction }
TTouchJunction = class(TCustomApplication)
protected
procedure DoRun; override;
function DateTimeToFileTime(DateTime: TDateTime): TFileTime;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure WriteHelp; virtual;
end;
{ TTouchJunction }
function TTouchJunction.DateTimeToFileTime(DateTime: TDateTime): TFileTime;
var sysTime: TSYSTEMTIME;
temp: TFILETIME;
begin
DateTimeToSystemTime(DateTime,sysTime);
SystemTimeToFileTime(@sysTime, at temp);
LocalFileTimeToFileTime(@temp, at result);
end;
procedure TTouchJunction.DoRun;
var
ErrorMsg: String;
TheDate,TheTime: string;
TheFile: UTF8String;
TheFileW: WideString;
ParamList: TStringList=nil;
TheHandle: THandle=INVALID_HANDLE_VALUE;
FT: TFormatSettings;
TheFileModify: TDateTime;
lCreationTime, lAccessTime, lModificationTime: FILETIME;
Arroba: Boolean=false;
F: TFileStream;
B: String;
U: UnicodeString;
begin
// quick check parameters
ErrorMsg:=CheckOptions('h', 'help');
if ErrorMsg<>'' then begin
ShowException(Exception.Create(ErrorMsg));
Terminate;
Exit;
end;
// parse parameters
if HasOption('h', 'help') then begin
WriteHelp;
Terminate;
Exit;
end;
if ParamCount=0 then begin
WriteHelp;
Terminate;
Exit;
end;
{ add your program here }
TheFile:=ParamStr(1);
TheDate:=ParamStr(2);
TheTime:=ParamStr(3);
if TheFile<>'' then begin
if TheFile[1]='"' then begin
TheFile:=copy(TheFile,2);
end;
if TheFile[1]='@' then begin
TheFile:=copy(TheFile,2);
Arroba:=true;
end;
if TheFile[1]='"' then begin
TheFile:=copy(TheFile,2);
end;
if TheFile[length(TheFile)]='"' then begin
TheFile:=copy(TheFile,1,Length(TheFile)-1);
end;
if Arroba then begin
if not FileExists(TheFile) then begin
writeln('File "',TheFile,'" does not exists.');
Terminate(1);
exit;
end;
//Each line is a parameter
//so
//Junction Name
//2020-01-01
//19:23:00
ParamList:=TStringList.Create;
try
F:=TFileStream.Create(TheFile,fmOpenRead or fmShareDenyNone);
SetLength(B,F.Size);
F.Read(B[1],F.Size);
FreeAndNil(F);
ParamList.Text:=B;
TheFile:=Utf8String(Utf8decode(ParamList[0]));
TheDate:=ParamList[1];
TheTime:=ParamList[2];
finally
FreeAndNil(ParamList);
end;
end;
end;
FT:=DefaultFormatSettings;
FT.DateSeparator:='-';
FT.LongDateFormat:='YYYY-MM-DD';
FT.ShortDateFormat:='YYYY-MM-DD HH:mm:SS';
TheFileModify:=StrToDateTime(TheDate+' '+TheTime,FT);
TheFileW:=WideString(TheFile);
TheHandle:=CreateFileW(@TheFileW[1], GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
Nil, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OPEN_REPARSE_POINT or FILE_ATTRIBUTE_REPARSE_POINT, INVALID_HANDLE_VALUE);
if TheHandle<>INVALID_HANDLE_VALUE then begin
if GetFileTime(TheHandle, at lCreationTime, at lAccessTime, at lModificationTime) then begin
lModificationTime:=DateTimeToFileTime(TheFileModify);
if not SetFileTime(TheHandle,lCreationTime,lAccessTime,lModificationTime) then begin
writeln('SetFileTime Last Error: ',GetLastError());
CloseHandle(TheHandle);
Terminate(3);
exit;
end else begin
CloseHandle(TheHandle);
writeln ('Touched "'+TheFile+'" with '+DateTimeToStr(TheFileModify));
Terminate(0);
exit;
end;
end else begin
writeln('GetFileTime Last Error: ',GetLastError());
Terminate(2);
exit;
end;
end else begin
writeln('CreateFileW Last Error: ',GetLastError());
Terminate(5);
exit;
end;
// stop program loop
Terminate(0);
end;
constructor TTouchJunction.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
StopOnException:=True;
end;
destructor TTouchJunction.Destroy;
begin
inherited Destroy;
end;
procedure TTouchJunction.WriteHelp;
begin
{ add your help code here }
writeln('Usage: ', ExeName, ' junctionname YYYY-MM-DD HH:MM:SS [-h]');
writeln('Or');
writeln('Usage: ', ExeName, ' @Params-utf8.txt [-h]');
end;
var
Application: TTouchJunction;
begin
Application:=TTouchJunction.Create(nil);
Application.Title:='TouchJunction';
Application.Run;
Application.Free;
end.
More information about the fpc-pascal
mailing list