如何在Windows中获取*更改*文件时间?

时间:2014-12-17 20:39:07

标签: python winapi filesystems ntfs

我正在尝试使用FreeNAS CIFS与Windows共享(将文件 Windows 同步到 FreeNAS)并遇到robocopy.exe认为某些文件需要的问题每次运行robocopy.exe时都会再次复制(/ COPY:DAT)。

我最喜欢的文件管理工具Far Manager告诉我“更改时间”是不同的:

Windows上的文件时间: On Windows

FreeNAS(ZFS)支持的CIFS共享上的文件时间: On CIFS share backed by FreeNAS (ZFS)

我完全可以理解“更改时间”已丢失,我很乐意重置Windows驱动器上的更改时间,但我无法找到如何以编程方式执行此操作。

Python的os.stat(filename)返回st_atime,st_mtime和st_ctime,我测试过,这个元组在Windows和FreeNAS之间具有相同的值。据推测,“改变时间”并不存在。

Windows API也只提供3个数字(创建,上次访问和上次写入),但不提供“更改时间”: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724320(v=vs.85).aspx

显然,robocopy.exe和远程管理器都以某种方式从系统中获取4个值。我真的很想避免拆解它们,希望能在这里得到答案。如何获取并设置“更改时间”?

任何解决方案都可以(Python,C ++,WinAPI,可以操作它的外部命令行工具等)。

2 个答案:

答案 0 :(得分:4)

好吧,我似乎已经弄清楚了,感谢cocarin指向远源。 远使用NtQueryInformationFile来获取时间和NtSetInformationFile来设置它们,而FILE_BASIC_INFORMATION结构包含所有4次,包括更改时间。

QueryInformationFile docs:http://msdn.microsoft.com/en-us/library/windows/hardware/ff567052(v=vs.85).aspx(ZwQueryInformationFile)

SetInformationFile docs:http://msdn.microsoft.com/en-us/library/windows/hardware/ff567096(v=vs.85).aspx(ZwSetInformationFile)

FILE_BASIC_INFORMATION docs:http://msdn.microsoft.com/en-us/library/windows/hardware/ff545762(v=vs.85).aspx

typedef struct _FILE_BASIC_INFORMATION {
  LARGE_INTEGER CreationTime;
  LARGE_INTEGER LastAccessTime;
  LARGE_INTEGER LastWriteTime;
  LARGE_INTEGER ChangeTime;        // <--- win!
  ULONG         FileAttributes;
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;

不确定Python是否有任何不错的包装,但这已经足够好了,我可以编写自己的包装器。

答案 1 :(得分:0)

有一个比接受的答案更好的方法,而不必在Windows Vista及更高版本(Server 2008及更高版本)上求助于本机系统Zw*调用。

请查看以下我为演示如何演示的示例代码:

// Get a handle to the file whose change time you want
const WCHAR pathName[]=L"..."; // The name of the file
HANDLE hFile=::CreateFileW(
               pathName, 
               GENERIC_READ, 
               FILE_SHARE_READ /* | FILE_SHARE_WRITE */,
               NULL, 
               OPEN_EXISTING,  // Fail if file does not exist
               FILE_ATTRIBUTE_NORMAL, 
               NULL);

// If file exists and can be read...
if (hFile!=INVALID_HANDLE_VALUE)
{
  FILE_BASIC_INFO fileBasicInfo={};

  // Get the info we are after
  if (::GetFileInformationByHandleEx(
        hFile,
        FileBasicInfo,          // Info class from FILE_INFO_BY_HANDLE_CLASS enum
        &fileBasicInfo,         // Where to store the info
        sizeof(fileBasicInfo))  // Buffer size
  {
      // Use fileBasicInfo.ChangeTime for the file change time
      ...
  }

  ::CloseHandle(hFile);
}

为方便起见,以下是相应的MSDN条目链接:

注意:另外,请查看此宝藏函数所提供的满足您所有高级文件信息需要的其他信息类。例如,FileStandardInfo类为您提供了一些有用的提示,例如实际分配给文件的空间量(例如,用于稀疏文件的实际物理空间使用),链接数,是否正在删除,是否是目录等...