Windows下文件的監控


Windows 2000 引入了兩個新接口,FindFirstChangeNotification 和 ReadDirectoryChangesW 。 FindFirstChangeNotification 很容易使用,但沒有給出變更文件的信息。即便如此,這個函數對某些應用程序還是很有用的,比如傳真服務和 SMTP 服務可以通過拖拽一個文件到一個目錄來接受任務隊列。ReadDirectoryChangesW 會給出變更的內容和方式, 不過相對的,在使用上也更復雜一些。

1.FindFirstChangeNotification()函數

功能:創建一個改變通知句柄,並設置通知條件,即發生某種修改時,該通知句柄將被促發生效。該函數僅僅負責對文件修改作出通知,並不記錄和反饋修改信息。

返回值:成功時返回指向改變通知的句柄,失敗時返回INVALID_HANDLE_VALUE,可以用GetLastError()函數得到。

例子:部分代碼如下

//使用FindFirstChangeNotification和FindNextChangeNotification實現文件監控
CString Monitor1()
{
HANDLE hEvent;//監控句柄
//char* path[MAX_PATH+1] ;//監控目錄
static int m_nCount = 0; //當前操作的序號
CString str;

//GetCurrentDirectory(MAX_PATH, (LPWSTR)path);
hEvent = FindFirstChangeNotification("E:\\",TRUE,FILE_NOTIFY_CHANGE_FILE_NAME| //查看指定目錄下任何文件名的改變
FILE_NOTIFY_CHANGE_DIR_NAME| //查看指定目錄下任何目錄名的改變
FILE_NOTIFY_CHANGE_SIZE| //查看指定文件大小的改變
FILE_NOTIFY_CHANGE_ATTRIBUTES);//查看指定目錄下文件屬性的改變
if (hEvent == INVALID_HANDLE_VALUE)
{
//ExitProcess(GetLastError());//獲取錯誤
//return;
str.Format("%s %s", "error", GetLastError());
return str;
}
//while (TRUE)//循環監控
{
DWORD nobj;
nobj= WaitForSingleObject(hEvent,INFINITE);//等待,文件夾任何動作,都返回0,顧不能知道具體動作和具體哪個文件發生了變化
if (nobj)
{
;
}
m_nCount++;
str.Format("%d %s", m_nCount, "文件發生了變化!");
printf("文件發生了變化\r\n");

//繼續監控
if(FALSE==FindNextChangeNotification(hEvent))
{
//ExitProcess(GetLastError());
//return;
str.Format("%s %s", "error", GetLastError());
return str;
}
}
return str;
}

2.ReadDirectoryChangesW()函數

功能:監控文件修改,並記錄文件修改的相關信息,如修改的文件名,何種類型的修改等。

返回值:如果函數成功,返回值就是非0。對於同步調用,這意味着操作成功,對於異步調用,這意味着操作成功地排隊。如果函數失敗,返回值是0。如果操作目錄或文件系統不支持這個操作,函數將返回ERROR_INVALID_FUNCTION,可以使用GetLastError()函數獲取。

例子:部分代碼如下

//使用ReadDirectoryChangesW實現文件監控
CString Monitor2()
{
DWORD cbBytes;
char cFileName[1024]; //設置文件名
char cNewFileName[1024]; //設置文件重命名后的名字
char cNotify[1024];
static int m_nCount = 0; //當前操作的序號
TCHAR *pDirectory = "E:\\";//m_strAddress.GetBuffer(m_strAddress.GetLength());

CString str;
HANDLE dirHandle;
dirHandle = CreateFile(
pDirectory,
GENERIC_READ | GENERIC_WRITE | FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);

memset(cNotify, 0, strlen(cNotify));

FILE_NOTIFY_INFORMATION *pNotify = (FILE_NOTIFY_INFORMATION*)cNotify;

//若網絡重定向或目標文件系統不支持該操作,函數失敗,同時調用GetLastError()返回ERROR_INVALID_FUNCTION
if(dirHandle == INVALID_HANDLE_VALUE)
{
str.Format("%s %s", "error", GetLastError());
return str;
}

if(ReadDirectoryChangesW(
dirHandle,
&cNotify,
1024,
true,
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME
//| FILE_NOTIFY_CHANGE_CREATION
//| FILE_NOTIFY_CHANGE_LAST_WRITE
| FILE_NOTIFY_CHANGE_SIZE,
&cbBytes,NULL,NULL))
{
//轉換文件名為多字節字符串
if(pNotify->FileName)
{
memset(cFileName, 0, strlen(cFileName));
WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength/2, cFileName, 99, NULL, NULL);
}

//獲取重命名的文件名
if(pNotify->NextEntryOffset != 0 && (pNotify->FileNameLength > 0 && pNotify->FileNameLength < MAX_PATH))
{
PFILE_NOTIFY_INFORMATION p = (PFILE_NOTIFY_INFORMATION)((char*)pNotify + pNotify->NextEntryOffset);
memset(cNewFileName, 0, sizeof(cNewFileName));
WideCharToMultiByte(CP_ACP, 0, p->FileName, p->FileNameLength/2, cNewFileName, 99, NULL, NULL);
}

//設置類型過濾器,監聽文件創建、更改、刪除、重命名等
switch(pNotify->Action)
{
case FILE_ACTION_ADDED:
m_nCount++;
str.Format("%d %s %s", m_nCount, "file add:", cFileName);
//AfxMessageBox(str);
break;
case FILE_ACTION_MODIFIED:
m_nCount++;
str.Format("%d %s %s", m_nCount, "file modified:", cFileName);
//AfxMessageBox(str);
break;
case FILE_ACTION_REMOVED:
m_nCount++;
str.Format("%d %s %s", m_nCount, "file removed:", cFileName);
//AfxMessageBox(str);
break;
case FILE_ACTION_RENAMED_OLD_NAME:
m_nCount++;
str.Format("%d %s %s %s %s", m_nCount, "file renamed:", cFileName, "->", cNewFileName);
//AfxMessageBox(str);
break;

default:
//MessageBox("unknow command!");
break;
}
CloseHandle(dirHandle);
}
return str;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM