Windows 沒有直接提供修改資料夾(目錄)時間的介面,但 CreateFile 設定 FILE_FLAG_BACKUP_SEMANTICS 旗標後,即可取得目錄的控制代碼,進而使用原本針對檔案的 GetFileTime / SetFileTime 讀寫建立、存取、修改時間。此技巧常用於完整備份還原系統,確保根目錄與子目錄時間戳一致。
HANDLE hDir = CreateFile(
dirPath, // 目錄完整路徑
GENERIC_READ | GENERIC_WRITE, // 讀寫權限
FILE_SHARE_READ | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING, // 必須為 OPEN_EXISTING
FILE_FLAG_BACKUP_SEMANTICS, // 關鍵旗標:允許開啟目錄
NULL);
if (hDir == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError(); // 處理錯誤
return FALSE;
}
BOOL GetDirTime(LPCTSTR dirPath, SYSTEMTIME& stLocal)
{
HANDLE hDir = CreateFile(dirPath, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_DELETE,
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hDir == INVALID_HANDLE_VALUE) return FALSE;
FILETIME ftCreate, ftAccess, ftWrite;
BOOL ok = GetFileTime(hDir, &ftCreate, &ftAccess, &ftWrite);
CloseHandle(hDir);
if (!ok) return FALSE;
// UTC → 本地時間 → SYSTEMTIME
FILETIME ftLocal;
FileTimeToLocalFileTime(&ftWrite, &ftLocal);
FileTimeToSystemTime(&ftLocal, &stLocal);
return TRUE;
}
BOOL SetDirTime(LPCTSTR dirPath, const SYSTEMTIME& stLocal)
{
HANDLE hDir = CreateFile(dirPath, GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_DELETE,
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hDir == INVALID_HANDLE_VALUE) return FALSE;
FILETIME ftCreate, ftAccess, ftWrite;
SystemTimeToFileTime(&stLocal, &ftCreate);
SystemTimeToFileTime(&stLocal, &ftAccess);
SystemTimeToFileTime(&stLocal, &ftWrite);
BOOL ok = SetFileTime(hDir, &ftCreate, &ftAccess, &ftWrite);
CloseHandle(hDir);
return ok;
}
SYSTEMTIME st;
if (GetDirTime(_T("D:\\BackupRoot"), st)) {
// 視需求修改 st,或直接保持原樣
// st.wYear = 2023; st.wMonth = 1; st.wDay = 1; ...
SetDirTime(_T("D:\\BackupRoot"), st);
}
同樣的 GetFileTime/SetFileTime 適用於檔案(不需 FILE_FLAG_BACKUP_SEMANTICS)。可撰寫統一介面 SetItemTime(path, st, isDirectory) 簡化呼叫端。