Introduction
Many tools are out there to get file dates, but this tool will set whatever date you specify to any file(s) or folder(s). By studying this tool, you will learn about:
- manipulating file/system date time
- finding files recursively
- implementing drag & drop feature to an edit box
Setting Date & Time
When you click Apply, the new date & time you had specified will be set to the selected file(s) or folder(s). SetFileTime
API is used to set date and time to a file/folder. Setting date and time to folders and files within a folder is a tricky thing. Here I have used FindFirstFile
and FindNextFile
to find all folders and files recursively while setting new date & time to them. Here is the code for it:
int SetFileDateTime(char *szFilePath,
FILETIME ftCreated,
FILETIME ftModified,
FILETIME ftAccessed)
{
DWORD dwAttr;
dwAttr = GetFileAttributes(szFilePath);
if(g_bIgnoreAttrAndApply)
{
if(FILE_ATTRIBUTE_HIDDEN&dwAttr)
if(!g_bAttrHidden)
return 0;
if(FILE_ATTRIBUTE_READONLY&dwAttr)
if(!g_bAttrReadOnly)
return 0;
if(FILE_ATTRIBUTE_SYSTEM&dwAttr)
if(!g_bAttrSystem)
return 0;
if(FILE_ATTRIBUTE_COMPRESSED&dwAttr)
if(!g_bAttrCompressed)
return 0;
if(FILE_ATTRIBUTE_ENCRYPTED&dwAttr)
if(!g_bAttrEncrypted)
return 0;
SetFileAttributes(szFilePath,FILE_ATTRIBUTE_NORMAL);
}
else
{
if(FILE_ATTRIBUTE_HIDDEN&dwAttr)
return 0;
if(FILE_ATTRIBUTE_READONLY&dwAttr)
return 0;
if(FILE_ATTRIBUTE_SYSTEM&dwAttr)
return 0;
if(FILE_ATTRIBUTE_COMPRESSED&dwAttr)
return 0;
if(FILE_ATTRIBUTE_ENCRYPTED&dwAttr)
return 0;
}
HANDLE hFile = CreateFile(szFilePath,
GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
return 1;
BOOL bVal =
SetFileTime(hFile,&ftCreated,&ftAccessed,&ftModified);
if(!bVal)
{
char *szBuff = (char*)malloc(sizeof(char)*1024);
LPVOID lpMsgBuf;
int err = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL);
sprintf(szBuff,"Unable to set date to \n %s \n\nReason:%s \nError No:%d",
szFilePath,lpMsgBuf,err),
MessageBox(NULL,(LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONERROR);
LocalFree(lpMsgBuf);
}
CloseHandle(hFile);
if(g_bIgnoreAttrAndApply)
SetFileAttributes(szFilePath,dwAttr);
if(!bVal)
return 2;
return 0;
}
int SetDateTimeToFolderFiles(HANDLE hSearchedFile,
char *szPathName,
FILETIME ftCreated,
FILETIME ftModified,
FILETIME ftAccessed)
{
WIN32_FIND_DATA stFindData;
char *szCurFilename = (char*)malloc(sizeof(char)*_MAX_PATH);
char *szCurPathname = (char*)malloc(sizeof(char)*_MAX_PATH);
strcpy(szCurFilename,szPathName);
strcpy(szCurPathname,szPathName);
if((hSearchedFile == NULL)||(hSearchedFile ==INVALID_HANDLE_VALUE))
{
sprintf(szCurFilename,"%s\\*.*",szPathName);
hSearchedFile = FindFirstFile(szCurFilename,&stFindData);
if(hSearchedFile == INVALID_HANDLE_VALUE)
return 0;
}
else
{
if(!FindNextFile(hSearchedFile,&stFindData))
{
FindClose(hSearchedFile);
return 0;
}
}
strcat(szCurPathname,"\\");
strcat(szCurPathname,stFindData.cFileName);
if(stFindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
{// if it is a folder then ....
if((!stricmp(stFindData.cFileName,"."))||
(!stricmp(stFindData.cFileName,".."))||
(!stricmp(stFindData.cFileName,""))||
(!stricmp(stFindData.cFileName,"")))
{
// call it recursively
return SetDateTimeToFolderFiles(hSearchedFile,
szPathName,
ftCreated,
ftModified,
ftAccessed);
}
// call the set function for the found folder
SetFileDateTime(szCurPathname, ftCreated, ftModified, ftAccessed);
// call it recursively
SetDateTimeToFolderFiles( NULL,
szCurPathname,
ftCreated,
ftModified,
ftAccessed);
}
// control will come here only if the found one is a file
// set the date time to the file
SetFileDateTime(szCurPathname, ftCreated, ftModified, ftAccessed);
// call it recursively
return SetDateTimeToFolderFiles(hSearchedFile,
szPathName,
ftCreated,
ftModified,
ftAccessed);
}
Special attributed files cannot be set with new date & time. It should be reset to FILE_ATTRIBUTE_NORMAL
to set new date and time. If the user doesn't check the checkbox Also apply to files with special attributes, then these special attributed files will be ignored while processing. This brings a new feature to this tool. User can ignore the special system files when mass data & time setting is done.
Getting Date & Time
When you click Refresh, the selected folder or file's date & time will be retrieved and populated. The following code will do that...
void CFileDateDlg::OnBtnRefresh()
{
CString cszPath;
m_edtPath.GetWindowText(cszPath);
FILETIME ftCreated, ftModified, ftAccessed;
BOOL bRet = GetFileDateTime(cszPath.GetBuffer(0),
ftCreated,
ftModified,
ftAccessed);
cszPath.ReleaseBuffer();
((CDateTimeCtrl*)GetDlgItem(IDC_DATECREATED))->SetTime(ftCreated);
((CDateTimeCtrl*)GetDlgItem(IDC_DATEMODIFIED))->SetTime(ftModified);
((CDateTimeCtrl*)GetDlgItem(IDC_DATEACCESSED))->SetTime(ftAccessed);
((CDateTimeCtrl*)GetDlgItem(IDC_TIMECREATED))->SetTime(ftCreated);
((CDateTimeCtrl*)GetDlgItem(IDC_TIMEMODIFIED))->SetTime(ftModified);
((CDateTimeCtrl*)GetDlgItem(IDC_TIMEACCESSED))->SetTime(ftAccessed);
}
Conclusion
Hope you will find this very useful. You are always welcome to modify this tool. I also want to remind you that I'm not responsible for any damage caused by this tool. Thanks.