2011-08-25 76 views
1

Microsoft提供了一个documented方法,用于防止上次访问时间被文件句柄上的操作更新。我用这种方法在本地成功访问文件,但不是远程访问。这是否也适用于远程文件?记录SetFileTime()过程以保留LastAccessTime不适用于UNC路径

#include <windows.h> 
#include <tchar.h> 
#include <stdio.h> 
#include <assert.h> 

#include <string> 

#define FAIL(x) { printf(x" FAILED: %d\n", GetLastError()); exit(-1); } 

static std::wstring GetDateTimeString(SYSTEMTIME* datetime) 
{ 
    TCHAR buffer[256]; 
    TCHAR* current = buffer; 

    int idx = GetDateFormat(LOCALE_SYSTEM_DEFAULT,NULL, datetime, L"dd-MMM-yyyy", current, 256); 

    if(idx > 0) 
    { 
     buffer[idx -1] = ' '; 
     current += idx; 
     int idx2 = GetTimeFormat(LOCALE_SYSTEM_DEFAULT,NULL, datetime, L"HH:mm:ss", current, 256 - idx); 
     if(idx2 > 0) 
     { 
      current += idx2 - 1; 
      _sntprintf(current, 256 - (idx + idx2), L".%d", datetime->wMilliseconds); 
     } 
     else 
      FAIL("GetTimeFormat"); 
    } 
    else 
     FAIL("GetDateFormat"); 

    return std::wstring(buffer); 
} 

static void ReportLastAccessTime(TCHAR* path) 
{ 
    WIN32_FILE_ATTRIBUTE_DATA data; 

    if(GetFileAttributesEx(path, GetFileExInfoStandard, &data)) 
    { 
     SYSTEMTIME accessSysTime; 

     if(FileTimeToSystemTime(&data.ftLastAccessTime, &accessSysTime)) 
     { 
      SYSTEMTIME nowSysTime; 
      GetSystemTime(&nowSysTime); 
      printf("(%S) LastAccess=%S\n", GetDateTimeString(&nowSysTime).c_str(), GetDateTimeString(&accessSysTime).c_str()); 
     } 
     else 
      FAIL("FileTimeToSystemTime"); 
    } 
    else 
     FAIL("GetFileAttributesEx"); 
} 

static void TestPreservingLastAccessTime(TCHAR* path) 
{ 
    printf("Checking times before opening the file handle...\n"); 
    ReportLastAccessTime(path); 

    HANDLE hFile = CreateFile(
      path, 
      GENERIC_READ | FILE_WRITE_ATTRIBUTES, 
      FILE_SHARE_READ, 
      NULL, 
      OPEN_EXISTING, 
      0, 
      NULL); 

    if(hFile != INVALID_HANDLE_VALUE) 
    { 
     static const FILETIME ftLeaveUnchanged = { 0xFFFFFFFF, 0xFFFFFFFF }; 

     printf("Handle open, SetFileTime -1...\n"); 
     if(SetFileTime(hFile, NULL, &ftLeaveUnchanged, NULL)) 
     { 
      char buf[512]; 
      DWORD numRead = 0; 

      printf("Checking times after opening handle and SetFileTime...\n"); 
      ReportLastAccessTime(path); 

      printf("Reading the file...\n"); 
      long total = 0; 

      while (ReadFile(hFile, buf, sizeof(buf), &numRead, NULL)) 
      { 
       if (numRead == 0) break; 
       total += numRead; 
       printf("Read: %d bytes (total=%d)\n", numRead, total); 
       Sleep(1000); 
      } 

      printf("Checking times after reading the file...\n"); 
      ReportLastAccessTime(path); 

      printf("Sleeping 30\n"); 
      Sleep(30 * 1000); 

      printf("Checking times after reading the file before closing the file...\n"); 
      ReportLastAccessTime(path); 

      printf("Closing the file\n"); 
      CloseHandle(hFile); 

      printf("Sleeping 30\n"); 
      Sleep(30 * 1000); 

      printf("Checking times after closing the file...\n"); 
      ReportLastAccessTime(path); 
     } 
     else 
     { 
      CloseHandle(hFile); 
      FAIL("SetFileTime"); 
     } 
    } 
    else 
     FAIL("CreateFile"); 
} 

int _tmain(int argc, TCHAR* argv[]) 
{ 
    TCHAR* localPath = L"C:\\tmp\\file.txt"; 
    TCHAR* uncPath = L"\\\\localhost\\C$\\tmp\\file.txt"; 

    printf("Testing local path: %S\n", localPath); 
    TestPreservingLastAccessTime(localPath); 

    printf("Sleeping 30\n"); 
    Sleep(30 * 1000); 

    printf("Testing UNC path: %S\n", uncPath); 
    TestPreservingLastAccessTime(uncPath); 

    return 0; 
} 

的运行上面的结果:你不知道

Testing local path: C:\tmp\file.txt 
Checking times before opening the file handle... 
(08-Nov-2011 21:06:18.432) LastAccess=08-Nov-2011 19:50:20.833 
Handle open, SetFileTime -1... 
Checking times after opening handle and SetFileTime... 
(08-Nov-2011 21:06:18.432) LastAccess=08-Nov-2011 19:50:20.833 
Reading the file... 
Read: 512 bytes (total=512) 
.... 
Read: 512 bytes (total=7680) 
Checking times after reading the file... 
(08-Nov-2011 21:06:33.432) LastAccess=08-Nov-2011 19:50:20.833 
Sleeping 30 
Checking times after reading the file before closing the file... 
(08-Nov-2011 21:07:03.432) LastAccess=08-Nov-2011 19:50:20.833 
Closing the file 
Sleeping 30 
Checking times after closing the file... 
(08-Nov-2011 21:07:33.432) LastAccess=08-Nov-2011 19:50:20.833 
Sleeping 30 
Testing UNC path: \\localhost\C$\tmp\file.txt 
Checking times before opening the file handle... 
(08-Nov-2011 21:08:03.448) LastAccess=08-Nov-2011 19:50:20.833 
Handle open, SetFileTime -1... 
Checking times after opening handle and SetFileTime... 
(08-Nov-2011 21:08:03.448) LastAccess=08-Nov-2011 19:50:20.833 
Reading the file... 
Read: 512 bytes (total=512) 
.... 
Read: 512 bytes (total=7680) 
Checking times after reading the file... 
(08-Nov-2011 21:08:18.448) LastAccess=08-Nov-2011 19:50:20.833 
Sleeping 30 
Checking times after reading the file before closing the file... 
(08-Nov-2011 21:08:48.448) LastAccess=08-Nov-2011 19:50:20.833 
Closing the file 
Sleeping 30 
Checking times after closing the file... 
(08-Nov-2011 21:09:18.448) LastAccess=08-Nov-2011 21:08:48.448 

回答

0

请求是

#define FSCTL_READ_FILE_USN_DATA  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 58, METHOD_NEITHER, FILE_ANY_ACCESS) // Read the Usn Record for a file 

这是docomented here

如果这是手柄送你正在使用SET_FILE_INFO之前,那么这将解释你为什么不能Ødiable上次访问时间改变。