用Visual C++實現改變指定的文件和文件夾的屬性
發表于:2007-07-14來源:作者:點擊數:
標簽:
摘要: 文件的屬性包括文件的產生修改和訪問時間以及讀寫隱現等,在DOS下文件的屬性可以用DOS命令加以修改,在 WINDOWS 下,可以通過右鍵的屬性改變一組文件和文件夾的讀寫屬性,但是卻不能修改文件的產生修改和訪問時間,并且不能修改子目錄下的文件和文件夾
摘要: 文件的屬性包括文件的產生修改和訪問時間以及讀寫隱現等,在DOS下文件的屬性可以用DOS命令加以修改,在
WINDOWS下,可以通過右鍵的屬性改變一組文件和文件夾的讀寫屬性,但是卻不能修改文件的產生修改和訪問時間,并且不能修改子目錄下的文件和文件夾的屬性。本文基于
Windows的API設計了通用的文件和文件夾的屬性(包括文件的產生修改和訪問時間以及讀寫隱現等)的修改方法,并實現了其Visual C++程序編碼。
---- 文件的屬性的修改具有廣泛的使用價值,修改文件的讀寫隱現等屬性,可以實現文件的保護和控制,尤其是修改文件的產生修改和訪問時間,可以避免因防病毒更改系統時間而造成的文件修改時間的紊亂所形成的不便,例如,對
程序員來說,編譯時,系統有可能又重新編譯那些修改時間紊亂的文件,造成不必要的麻煩。
---- 一、應用的API函數
---- 1、API中的文件函數組提供了文件讀寫、屬性設置的眾多API函數,在本編碼中用到的該函數組中的函數有:
HANDLE CreateFile( LPCTSTR, DWORD, DWORD,LPSECURITY_ATTRIBUTES,
DWORD,DWORD,HANDLE );
---- 該函數產生或者打開一個系統對象,并返回一個用以訪問該對象的句柄,這些對象可以是文件、文件夾、管道等。
HANDLE FindFirstFile( LPCTSTR, LPWIN32_FIND_DATA );
該函數在指定目錄尋找與指定文件名匹配的文件和文件夾,并返回一個查詢句柄?! ?br>
BOOL FindNextFile( HANDLE,LPWIN32_FIND_DATA );
該函數繼續一個由查詢句柄指定的查詢過程?! ?br>
BOOL FindClose( HANDLE );
該函數關閉指定的查詢句柄,結束指定的查詢?! ?br>
DWORD GetFileAttributes( LPCTSTR );
該函數檢取指定的文件的屬性信息?! ?br>
BOOL SetFileAttributes( LPCTSTR,DWORD );
該函數設置指定的文件的屬性信息?! ?br>
---- 2、API中的時間函數組提供了有關時間轉換的眾多API函數,在本編碼中用到的該函數組中的函數有:
BOOL SystemTimeToFileTime( CONST SYSTEMTIME *,LPFILETIME );
該函數將系統時間轉換成文件時間,文件時間是一個64位長度的數,
表示從1601年1月1日起的時間偏移,以千萬分之一秒為單位?! ?br>
BOOL LocalFileTimeToFileTime(CONST FILETIME *,LPFILETIME );
該函數將本時區的文件時間轉換成格林威治時間的文件時間?! ?br>
BOOL SetFileTime( HANDLE,CONST FILETIME*,CONST FILETIME *,CONST FILETIME * );
該函數設置文件產生修改和訪問的時間?! ?br>
---- 二、編碼實現
---- 1、首先建立一個基于對話框的工程,在對話框窗體中放置以下控制并通過類管理向導為這些控制添加適當變量:
文件名編輯框,輸入要改變的文件的全路徑,文件名中可以有通配符*和?。變量類型CString,名稱m_FILENAME;
修改包括子目錄文件的檢查框,變量類型BOOL,名稱m_DIRECTORY;
修改文件訪問時間檢查框,變量類型BOOL,名稱m_A
CCESS;
文件訪問時間日編輯框,變量類型BOOL,名稱m_ADAY;
文件訪問時間月編輯框,變量類型BOOL,名稱m_AMONTH;
文件訪問時間年編輯框,變量類型BOOL,名稱m_AYEAR;修改文件產生時間檢查框,變量類型BOOL,名稱m_CREATE;
文件產生時間日編輯框,變量類型BOOL,名稱m_CDAY;
文件產生時間時編輯框,變量類型BOOL,名稱m_CHOUR;
文件產生時間分編輯框,變量類型BOOL,名稱m_C
MINUTE;
文件產生時間月編輯框,變量類型BOOL,名稱m_CMONTH;
文件產生時間秒編輯框,變量類型BOOL,名稱m_CSECOND;
文件產生時間年編輯框,變量類型BOOL,名稱m_CYEAR;
修改文件修改時間檢查框,變量類型BOOL,名稱m_MODIFY;
文件修改時間日編輯框,變量類型BOOL,名稱m_
MDAY;
文件修改時間時編輯框,變量類型BOOL,名稱m_MHOUR;
文件修改時間分編輯框,變量類型BOOL,名稱m_MMINUTE;
文件修改時間月編輯框,變量類型BOOL,名稱m_MMONTH;
文件修改時間秒編輯框,變量類型BOOL,名稱m_MSECOND;
文件修改時間年編輯框,變量類型BOOL,名稱m_MYEAR;
修改文件屬性檢查框,變量類型BOOL,名稱m_PROPERTY;
文件隱藏屬性檢查框,變量類型BOOL,名稱m_HIDE;
文件只讀屬性檢查框,變量類型BOOL,名稱m_READ;
文件存檔屬性檢查框,變量類型BOOL,名稱m_SAVE;
文件系統屬性檢查框,變量類型BOOL,名稱m_SYSTEM;
執行更改的按鈕,點擊該按鈕后執行選定的更改操作?! ?br>
以上成員變量可在對話類的構造函數中用當前系統時間予以初始化?! ?br>
---- 2、在對話類中加入以下成員:
char filter[16];
int ChangeTheProperty(LPSTR Filename,BYTE bFlag=0) ;
其中成員變量filter用以存放帶通配符的文件名?! ?br>
成員函數ChangeTheProperty中實現了帶通配符的文件的屬性的改變,考慮到要遍歷子目錄,
該函數采用了遞歸調用,并請注意參數bFlag,其缺省值為0,
1表示調用發生自子目錄。其實現如下:
int CChangePropertyDlg::Change
TheProperty(LPSTR FileName,BYTE bFlag)
{
////存放路徑
char pathname[MAX_PATH];
////存放全路徑文件名
char allname[MAX_PATH];
////初始化pathname
int num=strlen(FileName);
for(int i=num-1;i>=0;i--){
if(FileName[i]=='\\')
break;
}
if(i==-1)
return 0;
strncpy(pathname,FileName,i+1);
pathname[i+1]='\0';
////查找并修改所有子目錄下符合條件的文件
DWORD stat=0;
WIN32_FIND_DATA fileinfo;
if(bFlag){
char DFileName[MAX_PATH];
strcpy(DFileName,pathname);
strcat(DFileName,"*.*");
HANDLE handle=FindFirstFile
(DFileName, &fileinfo);
if(handle==INVALID_HANDLE_VALUE)
return 0;
do{
if(fileinfo.cFileName[0]=='.')
continue;
strcpy(allname,pathname);
strcat(allname,fileinfo.cFileName);
//檢取文件屬性,可以使用
fileinfo的dwFileAttributes成員
stat=GetFileAttributes(allname);
if(stat==0xffffffff){
MessageBox("警告,獲取文件信息時出錯!!",
allname, MB_OK|MB_ICONINFORMATION);
continue;
}
//如果查詢到的是文件夾
if(stat&FILE_ATTRIBUTE_
DIRECTORY && m_DIRECTORY){
char temp[MAX_PATH];
sprintf(temp,"%s%s\\%s",
pathname,
fileinfo.cFileName,filter);
//遞歸改變該子目錄下的文件
ChangeTheProperty(temp,1);
}
}while(FindNextFile
(handle, &fileinfo));
FindClose(handle);
}
////查找并修改符合條件的文件和文件夾
HANDLE handle=FindFirstFile
( FileName, &fileinfo );
if(handle==INVALID_HANDLE_VALUE)
return 0;
do{
if(fileinfo.cFileName[0]=='.')
continue;
strcpy(allname,pathname);
strcat(allname,fileinfo.cFileName);
//檢取文件屬性
stat=GetFileAttributes(allname);
if(stat==0xffffffff){
MessageBox("警告,
獲取文件信息時出 錯!!",
allname,MB_OK|MB_
ICONINFORMATION);
continue;
}
//設置文件屬性
BOOL tt=SetFileAttributes(allname,0);
if(!tt){
MessageBox("警告,
文件信息出錯!!",
allname,MB_OK|MB_
ICONINFORMATION);
continue;
}
HANDLE hd=CreateFile(allname,
GENERIC_WRITE, FILE_SHARE_WRITE,
NULL,OPEN_EXISTING,
FILE_FLAG_BACKUP_SEM
ANTICS,NULL);
if(hd!=INVALID_HANDLE_VALUE){
SYSTEMTIME st[3];
GetLocalTime(&st[0]);
st[1]=st[0];st[2]=st[0];
FILETIME ft[3];
FILETIME lft[3];
BYTE ff[3];
ff[0]=0;ff[1]=0;ff[2]=0;
//改變文件訪問時間
if(m_ACCESS){
ff[0]=1;
st[0].wDay =m_ADAY;st[0].
wMonth=m_AMONTH;
st[0].wYear=m_AYEAR;
BOOL bb=SystemTime
ToFileTime(&st[0],&ft[0]);
bb=LocalFileTime
oFileTime(&ft[0],&lft[0]);
}
//改變文件產生時間
if(m_CREATE){
ff[1]=1;
st[1].wDay=m_CDAY;st[1].
wHour=m_CHOUR;st[1].
wMinute=m_CMINUTE;
st[1].wMonth=m_
CMONTH;st[1].
wSecond=m_CSECOND;
st[1].wYear=m_CYEAR;
BOOL bb=SystemTime
ToFileTime(&st[1],&ft[1]);
bb=LocalFileTime
ToFileTime(&ft[1],&lft[1]);
}
//改變文件修改時間
if(m_MODIFY){
ff[2]=1;
st[2].wDay=m_MDAY;st[2].
wHour=m_MHOUR;st[2].
wMinute=m_MMINUTE;
st[2].wMonth=m_MMONTH
;st[2].
wSecond=m_MSECOND;
st[2].wYear=m_MYEAR;
BOOL bb=System
TimeToFileTime(&st[2],&ft[2]);
bb=LocalFileTime
ToFileTime(&ft[2],&lft[2]);
}
//改變文件時間
BOOL tt=SetFile
Time(hd,ff[1]?&lft[1]:
NULL,ff[0]?&lft[0]:
NULL,ff[2]?&lft[2]:NULL);
if(!tt){
MessageBox("警告,文件信息出錯!!",
allname,MB_OK|MB_ICONINFORMATION);
}
CloseHandle(hd);
}
//改變文件屬性
if(m_PROPERTY){
if(m_HIDE)
stat|=FILE_
ATTRIBUTE_HIDDEN;
else
stat&=~FILE_
ATTRIBUTE_HIDDEN;
if(m_READ)
stat|=FILE_
ATTRIBUTE_READONLY;
else
stat&=~FILE_
ATTRIBUTE_READONLY;
if(m_SAVE)
stat|=FILE_
ATTRIBUTE_ARCHIVE;
else
stat&=~FILE_
ATTRIBUTE_ARCHIVE;
if(m_SYSTEM)
stat|=FILE_
ATTRIBUTE_SYSTEM;
else
stat&=~FILE_
ATTRIBUTE_SYSTEM;
}
//設置文件屬性
tt=SetFileAttributes(allname,stat);
if(!tt){
MessageBox("警告,
文件信息出錯!!",allname,
MB_OK|MB_
ICONINFORMATION);
continue;
}
//查找并修改當前目錄
下所有符合條件的文件
if(stat&FILE_
ATTRIBUTE_DIRECTORY
&& !bFlag){//m_DIRECTORY
char temp[128];
sprintf(temp,"%s%s\\%s",
pathname,fileinfo.cFileName,filter);
//遞歸改變該子目錄下的文件
ChangeTheProperty(temp,1);
continue;
}
}while(FindNextFile( handle, &fileinfo ));
FindClose(handle);
return 1;
}
---- 3、在執行更改的按鈕的BN_CLICKED消息處理器中加入以下代碼,這段代碼首先解析了輸入的文件名全路徑,并初始化了filter成員變量:
UpdateData(TRUE);
int num=m_FILENAME.GetLength();
for(int i=num-1;i>=0;i--){
if(m_FILENAME.GetAt(i)=='\\')
break;
}
if(i!=-1){
CString ss=m_FILENAME.Right( num-1-i );
strcpy(filter,ss.GetBuffer(15) );
ss.ReleaseBuffer();
ChangeTheProperty
( m_FILENAME.GetBuffer(128)) ;
m_FILENAME.ReleaseBuffer();
}
---- 4、編譯連接后,在文件名編輯框中輸入要改變的文件的帶通配符的全路徑,設置文件的創建修改訪問時間以及只讀隱藏等屬性,點擊該按鈕后執行選定的更改操作。
---- 三、本編碼在NT4.0平臺,用VC++6.0編譯,效果良好,符合預期。
原文轉自:http://www.anti-gravitydesign.com