Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/RTL/Delphi/File Management    [ Add a report in this area ]  
Report #:  73539   Status: Closed
FileAge does not work for open files with share_exclusive (Plattform>=W2K)
Project:  Delphi Build #:  11.0.2902.10471
Version:    11.1 Submitted By:   Samuel Soldat
Report Type:  Basic functionality failure Date Reported:  5/1/2009 2:40:18 AM
Severity:    Commonly encountered problem Last Updated: 3/20/2012 2:24:39 AM
Platform:    All platforms Internal Tracking #:   269238
Resolution: Fixed (Resolution Comments) Resolved in Build: : 14.0.3449.21988
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: None
Description
The FileAge function does not work for files that are opened in SHARE_EXCLUSIVE mode (like the pagefile.sys).

FileAge('C:\pagefile.sys') always return -1 instead of the FileDate.
(Same problem as in FileExists)

(Same problem in Delphi 2009)
Steps to Reproduce:
1. Create a new VCL application
2. Write the following into the Form's OnCreate handler:

begin
  if FileAge('C:\pagefile.sys') <>-1then
    ShowMessage('OK')
  else
    ShowMessage('Failed');
end;

Expected:
A "OK" dialog is displayed

Actual:
A "Failed" dialog is displayed
Workarounds
{--- org from SysUtils ---}

function GetFileAttributesExPreload(lpFileName: PChar; fInfoLevelId: TGetFileExInfoLevels;
  lpFileInformation: Pointer): BOOL; stdcall;
  forward;

var
  GetFileAttributesExFunc: function(lpFileName: PChar; fInfoLevelId: TGetFileExInfoLevels;
    lpFileInformation: Pointer): BOOL; stdcall = GetFileAttributesExPreload;

function GetFileAttributesExEmulated(lpFileName: PChar; fInfoLevelId: TGetFileExInfoLevels;
  lpFileInformation: Pointer): BOOL; stdcall;
var
  Handle: THandle;
  FindData: TWin32FindData;
begin
  Handle := FindFirstFile(lpFileName, FindData);
  if Handle <> INVALID_HANDLE_VALUE then
  begin
    Windows.FindClose(Handle);
    if lpFileInformation <> nil then
    begin
      Move(FindData, lpFileInformation^, SizeOf(TWin32FileAttributeData));
      Result := True;
      Exit;
    end;
  end;
  Result := False;
end;

function GetFileAttributesExPreload(lpFileName: PChar; fInfoLevelId: TGetFileExInfoLevels;
  lpFileInformation: Pointer): BOOL; stdcall;
begin
{$IFDEF UNICODE}
  GetFileAttributesExFunc := GetProcAddress(GetModuleHandle(kernel32), 'GetFileAttributesExW');
{$ELSE}
  GetFileAttributesExFunc := GetProcAddress(GetModuleHandle(kernel32), 'GetFileAttributesExA');
{$ENDIF}
  if not Assigned(GetFileAttributesExFunc) then
    GetFileAttributesExFunc := GetFileAttributesExEmulated;
  Result := GetFileAttributesExFunc(lpFileName, fInfoLevelId, lpFileInformation);
end;
{--- until here ---}

{--- New Section ---}
function GetFileInformation(const FileName: String;
                            var FileInformation: TWin32FileAttributeData): Boolean;
var
  LastError: Cardinal;
begin
  Result := GetFileAttributesExFunc(Pointer(FileName), GetFileExInfoStandard, @FileInformation);
  if (not Result) and
     (@GetFileAttributesExEmulated<>@GetFileAttributesExFunc) then
  begin
    LastError := GetLastError;
    if (LastError <> ERROR_FILE_NOT_FOUND) and
       (LastError <> ERROR_PATH_NOT_FOUND) and
       (LastError <> ERROR_INVALID_NAME) then
      Result := GetFileAttributesExEmulated(Pointer(FileName), GetFileExInfoStandard, @FileInformation);
  end;
  Result := Result and ((FileInformation.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0);
end;

function FileAge(const FileName: string): Integer; overload;
{$IFDEF MSWINDOWS}
var
  FindData: TWin32FileAttributeData;
  LocalFileTime: TFileTime;
begin
  if GetFileInformation(Filename, FindData) then
  begin
      FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
      if FileTimeToDosDateTime(LocalFileTime, LongRec(Result).Hi,
        LongRec(Result).Lo) then Exit;
  end;
  Result := -1;
end;
{$ENDIF}

{$IFDEF MSWINDOWS}
function FileAge(const FileName: string; out FileDateTime: TDateTime): Boolean;
var
  FindData: TWin32FindData;
  LSystemTime: TSystemTime;
  LocalFileTime: TFileTime;
begin
  Result := False;
  if GetFileInformation(Filename, FindData) then
  begin
      Result := True;
      FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
      FileTimeToSystemTime(LocalFileTime, LSystemTime);
      with LSystemTime do
        FileDateTime := EncodeDate(wYear, wMonth, wDay) +
          EncodeTime(wHour, wMinute, wSecond, wMilliSeconds);
    end;
  end;
end;
{$ENDIF}

function FileExists(const FileName: string): Boolean;
var
  FindData: TWin32FileAttributeData;
begin
  Result := GetFileInformation(FileName, FindData);
end;
Attachment
None
Comments

None

Server Response from: ETNACODE01