VC++文件监控之ReadDirectoryChangesW

我这里只介绍采用ReadDirectoryChangesW对文件目录实施监控

关键代码

CfgdsgDlg * dlg = (CfgdsgDlg*)lparam;

  HANDLE hDir;
  char notify[1024];
  DWORD cbBytes,i;
  char AnsiChar[3];
  wchar_t UnicodeChar[2];
  CString path;

  FILE_NOTIFY_INFORMATION *pnotify=(FILE_NOTIFY_INFORMATION *)notify;
  FILE_NOTIFY_INFORMATION *tmp; 

  GetCurrentDirectory(MAX_PATH,path.GetBuffer(MAX_PATH+1));
  hDir = CreateFile( path, FILE_LIST_DIRECTORY,
    FILE_SHARE_READ |
    FILE_SHARE_WRITE |
    FILE_SHARE_DELETE, NULL,
    OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS |
    FILE_FLAG_OVERLAPPED, NULL);
  if (hDir == INVALID_HANDLE_VALUE)
  { 

    dlg->m_edit.ReplaceSel("hDir:INVALID_HANDLE_VALUE\r\n");
    return 0;
  } 

  while (TRUE)
  {
    if(ReadDirectoryChangesW(hDir, &notify, sizeof(notify),
      FALSE, FILE_NOTIFY_CHANGE_FILE_NAME| FILE_NOTIFY_CHANGE_LAST_WRITE,
      &cbBytes, NULL, NULL))
    { 

      tmp = pnotify; 

      switch(tmp->Action)
      {
      case FILE_ACTION_ADDED: 

        dlg->m_edit.ReplaceSel("Directory/File added (添加文件)- \r\n");
        break;
      case FILE_ACTION_REMOVED:
        dlg->m_edit.ReplaceSel("Directory/File removed (删除文件)- \r\n");
        break;
      case FILE_ACTION_MODIFIED:
        dlg->m_edit.ReplaceSel("Directory/File modified (修改文件内容)- \r\n");
        break;
      case FILE_ACTION_RENAMED_OLD_NAME:
        dlg->m_edit.ReplaceSel("Directory/File old name (修改文件名字)- \r\n");
        break;
      case FILE_ACTION_RENAMED_NEW_NAME:
        dlg->m_edit.ReplaceSel("Directory/File new name - \r\n");
        break;
      default:
        break;
      }
    }
  }

FILE_NOTIFY_INFORMATION //可以确定是那个文件进行的修改

typedef struct _FILE_NOTIFY_INFORMATION {
DWORD NextEntryOffset;
DWORD Action;//动作
DWORD FileNameLength;//文件名字的长度
WCHAR FileName[1];//文件名字
} FILE_NOTIFY_INFORMATION,
*PFILE_NOTIFY_INFORMATION;

ReadDirectoryChangesW 返回类型(见MSDN)

Value Meaning

FILE_ACTION_ADDED
0x00000001


The file was added to the directory.


FILE_ACTION_REMOVED
0x00000002


The file was removed from the directory.


FILE_ACTION_MODIFIED
0x00000003


The file was modified. This can be a change in the time stamp or attributes.


FILE_ACTION_RENAMED_OLD_NAME
0x00000004


The file was renamed and this is the old name.


FILE_ACTION_RENAMED_NEW_NAME
0x00000005


The file was renamed and this is the new name.

效果如下:

不足的地方:

只能检测到指定目录和下一级目录,超过目录级数,该函数检测不到。

ReadDirectoryChangesW 监控文件夹 (一个简单的监控示例程序)

.h文件

// .h文件
#pragma once

typedef void (*PFN_NotifyAction)(DWORD dwAction, LPWSTR szFile, DWORD dwLength);

class CDirectoryWatch
{
public:
	CDirectoryWatch(void);
	virtual ~CDirectoryWatch(void);

public:
	BOOL StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction);
	BOOL StopDirectoryWatch(void);

private:
	static UINT __cdecl ThreadProc(LPVOID lParam);
	static UINT __cdecl DirectoryWatch(LPVOID lParam);

private:
	HANDLE m_hFile;
	CWinThread* m_pThread;
	TCHAR m_szDirectory[MAX_PATH];
};

.cpp文件

// .cpp文件
#include "StdAfx.h"
#include "DirectoryWatch.h"
#include <strsafe.h>

typedef enum
{
	MSG_STARTWATCH = (WM_USER + 0x11),
	MSG_STOPWATCH,
	MSG_EXITTHREAD
};

#define MAX_BUFFER_SIZE	(1024)

typedef struct _tagWATCHPARAMETERS
{
	_tagWATCHPARAMETERS()
	{
		hFile = INVALID_HANDLE_VALUE;
		hEvent = NULL;
		memset(&ol, 0, sizeof(OVERLAPPED));
		pBuffer = NULL;
		dwBufferSize = 0;
		bExit = FALSE;
		pFn_NotifyAction = NULL;
	}
	HANDLE hFile;
	HANDLE hEvent;
	OVERLAPPED ol;
	BYTE* pBuffer;
	DWORD dwBufferSize;
	BOOL bExit;
	PFN_NotifyAction pFn_NotifyAction;
}WATCH_PARAMETERS, *PWATCH_PARAMETERS;

CDirectoryWatch::CDirectoryWatch() : m_hFile(INVALID_HANDLE_VALUE), m_pThread(NULL)
{
	memset(m_szDirectory, 0, sizeof(m_szDirectory));

	m_pThread = AfxBeginThread(ThreadProc, NULL, 0, CREATE_SUSPENDED, 0, NULL);
	if(NULL == m_pThread)
	{
		TRACE("Error Code : %d\n", GetLastError());
		return ;
	}
	m_pThread->m_bAutoDelete = FALSE;
	m_pThread->ResumeThread();
}

CDirectoryWatch::~CDirectoryWatch()
{
	if(INVALID_HANDLE_VALUE != m_hFile)
	{
		CloseHandle(m_hFile);
		m_hFile = INVALID_HANDLE_VALUE;
	}

	if((NULL != m_pThread) && (NULL != m_pThread->m_hThread))
	{

		m_pThread->PostThreadMessage(MSG_EXITTHREAD, 0, 0);
		WaitForSingleObject(m_pThread->m_hThread, INFINITE);
		delete m_pThread;
		m_pThread = NULL;
	}
}

BOOL CDirectoryWatch::StartDirectoryWatch(LPCTSTR lpszDirectory, PFN_NotifyAction pFn_NotifyAction)
{
	if(NULL == m_pThread)
	{
		return FALSE;
	}

	if(NULL == lpszDirectory)
	{
		return FALSE;
	}

	if(NULL == pFn_NotifyAction)
	{
		return FALSE;
	}

	if(!PathFileExists(lpszDirectory))
	{
		TRACE("Error Code : %d\n", GetLastError());
		return FALSE;
	}

	if(!PathIsDirectory(lpszDirectory))
	{
		TRACE("Error Code : %d\n", GetLastError());
		return FALSE;
	}

	if(0 == _tcslen(m_szDirectory))
	{
		StringCchPrintf(m_szDirectory, _countof(m_szDirectory), _T("%s"), lpszDirectory);
	}
	else if(CSTR_EQUAL != CompareStringOrdinal(m_szDirectory, -1, lpszDirectory, -1, TRUE))
	{
		TRACE("Not Change Directory.\n");
		return FALSE;
	}

	if(INVALID_HANDLE_VALUE == m_hFile)
	{
		m_hFile = CreateFile(lpszDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
			NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
		if(INVALID_HANDLE_VALUE == m_hFile)
		{
			TRACE("Error Code : %d\n", GetLastError());
			return FALSE;
		}
	}

	return m_pThread->PostThreadMessage(MSG_STARTWATCH, (WPARAM)m_hFile, (LPARAM)pFn_NotifyAction);
}

BOOL CDirectoryWatch::StopDirectoryWatch()
{
	if(NULL != m_pThread)
	{
		return m_pThread->PostThreadMessage(MSG_STOPWATCH, 0, 0);
	}

	return FALSE;
}

UINT __cdecl CDirectoryWatch::DirectoryWatch(LPVOID lParam)
{
	WATCH_PARAMETERS* pParam = (WATCH_PARAMETERS*)lParam;
	if(NULL == pParam)
	{
		return 0;
	}
	HANDLE& hFile = pParam->hFile;
	BYTE* pBuffer = pParam->pBuffer;
	DWORD dwBufferSize = pParam->dwBufferSize;
	OVERLAPPED& ol = pParam->ol;
	HANDLE& hEvent = pParam->hEvent;
	BOOL& bExit = pParam->bExit;
	PFN_NotifyAction pFn_NotifyAction = pParam->pFn_NotifyAction;
	DWORD dwBytesReturn = 0;
	DWORD dwRet = WAIT_FAILED;
	DWORD dwOffSet = 0;
	TCHAR szFile[MAX_PATH] = {0};
	while(TRUE)
	{
		if(WAIT_OBJECT_0 != WaitForSingleObject(hEvent, INFINITE))
		{
			TRACE("Error Code : %d\n", GetLastError());
			break;
		}

		if(bExit)
		{
			break;
		}

		if(!ReadDirectoryChangesW(hFile, pBuffer, dwBufferSize, TRUE,
			FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES
			| FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS
			| FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY, &dwBytesReturn, &ol, NULL))
		{
			TRACE("Error Code : %d\n", GetLastError());
			break;
		}
		if(!GetOverlappedResult(hFile, &ol, &dwBytesReturn, TRUE))
		{
			TRACE("Error Code : %d\n", GetLastError());
			break;
		}
		FILE_NOTIFY_INFORMATION* pFileNotify = (FILE_NOTIFY_INFORMATION*)pBuffer;

		do
		{
			if(pFn_NotifyAction && (WAIT_OBJECT_0 == WaitForSingleObject(hEvent, 0)))
			{
				pFn_NotifyAction(pFileNotify->Action, pFileNotify->FileName, (pFileNotify->FileNameLength) / sizeof(WCHAR));
			}

			dwOffSet = pFileNotify->NextEntryOffset;
			pFileNotify = (FILE_NOTIFY_INFORMATION*)((BYTE*)pFileNotify + dwOffSet);
		} while (dwOffSet);
	}
	TRACE0("DirectoryWatch Thread Exit ... \n");
	return 0;
}

UINT __cdecl CDirectoryWatch::ThreadProc(LPVOID lParam)
{
	WATCH_PARAMETERS* pParam = new WATCH_PARAMETERS;

	if(NULL == pParam)
	{
		goto __CLEANUP__;
	}

	BYTE* pBuffer = new BYTE[MAX_BUFFER_SIZE];
	if(NULL == pBuffer)
	{
		goto __CLEANUP__;
	}
	memset(pBuffer, 0, MAX_BUFFER_SIZE);
	pParam->pBuffer = pBuffer;
	pParam->dwBufferSize = MAX_BUFFER_SIZE;
	HANDLE hWatchEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if(NULL == hWatchEvent)
	{
		goto __CLEANUP__;
	}
	pParam->ol.hEvent = hWatchEvent;
	CWinThread* pThread = NULL;
	HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	if(NULL == hEvent)
	{
		goto __CLEANUP__;
	}
	pParam->hEvent = hEvent;
	MSG msg;
	while(GetMessage(&msg, NULL, 0, 0))
	{
		switch(msg.message)
		{
		case MSG_STARTWATCH:
			{
				HANDLE hFile = (HANDLE)(msg.wParam);
				PFN_NotifyAction pFn_NotifyAction = (PFN_NotifyAction)(msg.lParam);
				if((INVALID_HANDLE_VALUE == hFile) && (NULL == pFn_NotifyAction))
				{
					break;
				}
				if(NULL == pThread)
				{
					pParam->hFile = hFile;
					pParam->pFn_NotifyAction = pFn_NotifyAction;
					pThread = AfxBeginThread(DirectoryWatch, (LPVOID)pParam, 0, CREATE_SUSPENDED, NULL);
					if(NULL == pThread)
					{
						goto __CLEANUP__;
					}
					pThread->m_bAutoDelete = FALSE;
					pThread->ResumeThread();
				}
				SetEvent(hEvent);
			}
			break;

		case MSG_STOPWATCH:
			{
				ResetEvent(hEvent);
			}
			break;

		case MSG_EXITTHREAD:
			{
				SetEvent(hEvent);
				pParam->bExit = FALSE;

				if((NULL != pThread) && (NULL != pThread->m_hThread))
				{
					WaitForSingleObject(pThread->m_hThread, INFINITE);
					delete pThread;
					pThread = NULL;
				}
				goto __CLEANUP__;
			}

		default:
			break;
		}
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

__CLEANUP__:
	if(NULL != hWatchEvent)
	{
		CloseHandle(hWatchEvent);
		hWatchEvent = NULL;
	}
	if(NULL != pBuffer)
	{
		delete[] pBuffer;
		pBuffer = NULL;
	}
	if(NULL != pParam)
	{
		delete pParam;
		pParam = NULL;
	}
	TRACE0("ThreadProc Thread Exit ...\n");
	return 0;
}

测试代码

// 测试代码

#include "stdafx.h"

#include "DirectoryWatch.h"

void NotifyAction(DWORD dwAction, LPWSTR szFile, DWORD dwLength)
{
	switch(dwAction)
	{
	case FILE_ACTION_ADDED:
		wprintf(L"FILE_ACTION_ADDED: \n\t");
		break;

	case FILE_ACTION_REMOVED:
		wprintf(L"FILE_ACTION_REMOVED: \n\t");
		break;

	case FILE_ACTION_MODIFIED:
		wprintf(L"FILE_ACTION_MODIFIED: \n\t");
		break;

	case FILE_ACTION_RENAMED_OLD_NAME:
		wprintf(L"FILE_ACTION_RENAMED_OLD_NAME: \n\t");
		break;

	case FILE_ACTION_RENAMED_NEW_NAME:
		wprintf(L"FILE_ACTION_RENAMED_NEW_NAME: \n\t");
		break;

	default:
		break;
	}
	WCHAR szPath[MAX_PATH] = {0};
	wmemcpy(szPath, szFile, min(dwLength, MAX_PATH));
	wprintf(L"%s\n", szPath);
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	CDirectoryWatch watch;
	wprintf(L"Start Directory Watch ...\n");
	watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction);
	Sleep(30 * 1000);
	watch.StopDirectoryWatch();
	wprintf(L"Stop Directory Watch ...\n");

	Sleep(10 * 1000);

	wprintf(L"Start Directory Watch ...\n");
	watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction);
	Sleep(30 * 1000);
	watch.StopDirectoryWatch();
	wprintf(L"Stop Directory Watch ...\n");
	Sleep(30 * 1000);
	wprintf(L"Process Exit ...\n");
	return 0;
}

效果如下图所示:

使用ReadDirectoryChangesW API监控文件系统的改变

在C++中若想要监控档案系统改变有很多方法,可以用FindFirstChangeNotification取得档案变更、或是Hook底层的API等方法来实现,这边使用ReadDirectoryChangesW API来实现,该API使用前必须先加入Kernel32.lib。

并加入Windows.h的标头档

#include "Windows.h"

这些步骤做完后在程式中就可以看到ReadDirectoryChangesW API了,其函式原型如下:

BOOL WINAPI ReadDirectoryChangesW(
 __in     HANDLE hDirectory,
 __out    LPVOID lpBuffer,
 __in     DWORD nBufferLength,
 __in     BOOL bWatchSubtree,
 __in     DWORD dwNotifyFilter,
 __out_opt  LPDWORD lpBytesReturned,
 __inout_opt LPOVERLAPPED lpOverlapped,
 __in_opt   LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

该API必须带入八个参数,hDirectory带入的是要监控的目录Handle、lpBuffer带入的是用来回传变动资料的空间、nBufferLength是lpBuffer空间的大小、bWatchSubtree是指定是否侦测子目录、dwNotifyFilter是指定监控的目录有哪些动作时需要通知、lpBytesReturned是用来回传变动资料内含的长度、lpOverlapped可用来在非同步环境下使用重叠IO用、lpCompletionRoutine则是当监控完成或取消时所呼叫的回调函式。

其中dwNotifyFilter的值可设定的有FILE_NOTIFY_CHANGE_FILE_NAME、FILE_NOTIFY_CHANGE_DIR_NAME、FILE_NOTIFY_CHANGE_ATTRIBUTES、FILE_NOTIFY_CHANGE_SIZE、FILE_NOTIFY_CHANGE_LAST_WRITE、FILE_NOTIFY_CHANGE_LAST_ACCESS、FILE_NOTIFY_CHANGE_CREATION、与FILE_NOTIFY_CHANGE_SECURITY,详细所代表的意义可参阅ReadDirectoryChangesW function

了解了函式原型后,就可以开始进入实际的使用。刚有提到说在ReadDirectoryChangesW API函式必须要带入的第一个参数是要监控的目录Handle,所以我们必须透过CreateFile API取得要监控的目录Handle,像是下面这样:

HANDLE hDirectoryHandle  = NULL;
hDirectoryHandle = ::CreateFileA(
  file,
  FILE_LIST_DIRECTORY,
  FILE_SHARE_READ
  | FILE_SHARE_WRITE
  | FILE_SHARE_DELETE,
  NULL,
  OPEN_EXISTING,
  FILE_FLAG_BACKUP_SEMANTICS
  | FILE_FLAG_OVERLAPPED,
  NULL); 

if(hDirectoryHandle == INVALID_HANDLE_VALUE)
  return;

取得监控的目录Handle后,将其带入ReadDirectoryChangesw API,顺带带入像是回传变动资料的Buffer空间、与要监控的变动类型等必要参数。像是下面这样:

int    nBufferSize      = 1024;
char*  buffer        = new char[nBufferSize];
DWORD dwBytes = 0;

memset(buffer, 0, nBufferSize);

if(!::ReadDirectoryChangesW(
  hDirectoryHandle,
  buffer,
  nBufferSize,
  bIncludeSubdirectories,
  FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME,
  &dwBytes,
  NULL,
  NULL) || GetLastError() == ERROR_INVALID_HANDLE)
{
  break;
}

if(!dwBytes)
{
  printf("Buffer overflow~~\r\n");
}

这边需注意到的是,若是变动的资料太多,提供的存储空间不足以存放时,回传的变动资料长度会是0,此时所有变动资料都会丢失。这样的情况多半只会出在一瞬间大量的变动,可以增大存储空间或是减少监控的变动类型,以减少回传的资料量,避免溢位的发生。

若是运行没发生问题,变动的资料会存放在当初塞进去的存储空间,该空间的资料其实是FILE_NOTIFY_INFORMATION structure的型态存在,因此我们可将存储空间的资料转换成PFILE_NOTIFY_INFORMATION。裡面的Action是我们所关注的变动类型,FileName是变动的档案名称,档案名称的部分是没有结尾符号的,必须要搭配FileNameLength去截取。另外变动的资料有时候不止一笔,因此我们必须在这边用迴圈搭配NextEntryOffset去重覆运行处理流程,处理所有变动的资料。

PFILE_NOTIFY_INFORMATION record = (PFILE_NOTIFY_INFORMATION)buffer;
DWORD cbOffset = 0;

do
{
  switch (record->Action)
  {
  case FILE_ACTION_ADDED:
    printf("FILE_ACTION_ADDED:");
    break;
  case FILE_ACTION_REMOVED:
    printf("FILE_ACTION_REMOVED:");
    break;
  case FILE_ACTION_MODIFIED:
    printf("FILE_ACTION_MODIFIED:");
    break;
  case FILE_ACTION_RENAMED_OLD_NAME:
    printf("FILE_ACTION_RENAMED_OLD_NAME:");
    break;

  case FILE_ACTION_RENAMED_NEW_NAME:
    printf("FILE_ACTION_RENAMED_NEW_NAME:");
    break;

  default:
    break;
  }    

  char fileBuffer[512];

  WideCharToMultiByte(CP_ACP, 0, record->FileName, record->FileNameLength, fileBuffer, record->FileNameLength, NULL, NULL);
  printf(fileBuffer);
  printf("\r\n");

  cbOffset = record->NextEntryOffset;
  record = (PFILE_NOTIFY_INFORMATION)((LPBYTE) record + cbOffset);
}while(cbOffset);

这边示范一个简易的使用范例,实际使用时最好还是搭配执行绪处理:

// ConsoleApplication10.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "Windows.h"

void MonitorDir(char* file, bool bIncludeSubdirectories = false)
{
  int    nBufferSize      = 1024;
  char*  buffer        = new char[nBufferSize];
  HANDLE hDirectoryHandle  = NULL;

  hDirectoryHandle = ::CreateFileA(
    file,
    FILE_LIST_DIRECTORY,
    FILE_SHARE_READ
    | FILE_SHARE_WRITE
    | FILE_SHARE_DELETE,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_BACKUP_SEMANTICS
    | FILE_FLAG_OVERLAPPED,
    NULL); 

  if(hDirectoryHandle == INVALID_HANDLE_VALUE)
    return;

  while(1)
  {
    DWORD dwBytes = 0;

    memset(buffer, 0, nBufferSize);

    if(!::ReadDirectoryChangesW(
      hDirectoryHandle,
      buffer,
      nBufferSize,
      bIncludeSubdirectories,
      FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME,
      &dwBytes,
      NULL,
      NULL) || GetLastError() == ERROR_INVALID_HANDLE)
    {
      break;
    }

    if(!dwBytes)
    {
      printf("Buffer overflow~~\r\n");
    }

    PFILE_NOTIFY_INFORMATION record = (PFILE_NOTIFY_INFORMATION)buffer;
    DWORD cbOffset = 0;

    do
    {
      switch (record->Action)
      {
      case FILE_ACTION_ADDED:
        printf("FILE_ACTION_ADDED:");
        break;
      case FILE_ACTION_REMOVED:
        printf("FILE_ACTION_REMOVED:");
        break;
      case FILE_ACTION_MODIFIED:
        printf("FILE_ACTION_MODIFIED:");
        break;
      case FILE_ACTION_RENAMED_OLD_NAME:
        printf("FILE_ACTION_RENAMED_OLD_NAME:");
        break;

      case FILE_ACTION_RENAMED_NEW_NAME:
        printf("FILE_ACTION_RENAMED_NEW_NAME:");
        break;

      default:
        break;
      }    

      char fileBuffer[512];

      WideCharToMultiByte(CP_ACP, 0, record->FileName, record->FileNameLength, fileBuffer, record->FileNameLength, NULL, NULL);
      printf(fileBuffer);
      printf("\r\n");

      cbOffset = record->NextEntryOffset;
      record = (PFILE_NOTIFY_INFORMATION)((LPBYTE) record + cbOffset);
    }while(cbOffset);
  }

  delete buffer;

  if(hDirectoryHandle)
    CloseHandle(hDirectoryHandle);
}

int _tmain(int argc, _TCHAR* argv[])
{
  MonitorDir("C:\\Users\\larry\\Desktop\\新增資料夾");

运行后去对监控的目录操作~可得到类似如下的结果:

(0)

相关推荐

  • VC++文件监控之FindFirstChangeNotification

    原因: 因为ReadDirectoryChangesW 上次测试发现不能多级目录监控, 所以尝试用FindFirstChangeNotification来实施文件监控. 关键代码: CFolderMonitorDlg *dlg = (CFolderMonitorDlg*)lParam; HANDLE hEvent;//监控句柄 CString path ;//监控目录 GetCurrentDirectory(MAX_PATH,path.GetBuffer(MAX_PATH+1)); hEvent

  • c++文件监控之FileSystemWatcher

    具体代码如下: #using <System.dll> #include <iostream> using namespace std; using namespace System; using namespace System::IO; using namespace System::Security::Permissions; public ref class Watcher { private: // Define the event handlers. static vo

  • VC++文件监控之ReadDirectoryChangesW

    我这里只介绍采用ReadDirectoryChangesW对文件目录实施监控 关键代码 CfgdsgDlg * dlg = (CfgdsgDlg*)lparam; HANDLE hDir; char notify[1024]; DWORD cbBytes,i; char AnsiChar[3]; wchar_t UnicodeChar[2]; CString path; FILE_NOTIFY_INFORMATION *pnotify=(FILE_NOTIFY_INFORMATION *)not

  • FTP服务器详解之监控ftp服务器、上传文件到ftp服务器、ftp文件监控的方法

    现在FTP文件服务器的使用极为普遍,可以方便地将文件实时存储在FTP文件服务器上,那么如何搭建FTP文件服务器呢,以及如何监控FTP文件服务器文件访问操作日志情况呢?详细如下: 第1页:FTP服务器的作用 FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务.FTP服务器常常被用来进行文件共享和传输,是互联网领域必不可少的一环. FTP服务器的作用 FTP服务器是为了解决文件传输障碍问题而产生的.那么FT

  • JAVA 文件监控 WatchService的示例方法

    概述 java1.7中 提供了WatchService来监控系统中文件的变化.该监控是基于操作系统的文件系统监控器,可以监控系统是所有文件的变化,这种监控是无需遍历.无需比较的,是一种基于信号收发的监控,因此效率一定是最高的:现在Java对其进行了包装,可以直接在Java程序中使用OS的文件系统监控器了. 使用场景 场景一:比如系统中的配置文件,一般都是系统启动的时候只加载一次,如果想修改配置文件,还须重启系统.如果系统想热加载一般都会定时轮询对比配置文件是否修改过,如果修改过重新加载. 场景二

  • C#使用FileSystemWatcher控件实现的文件监控功能示例

    本文实例讲述了C#使用FileSystemWatcher控件实现的文件监控功能.分享给大家供大家参考,具体如下: FileSystemWatcher 可以使用FileSystemWatcher组件监视文件系统,并对文件系统的改变作出反应.通过使用FileSystemWatcher组件,在特定的文件或目录被创建.修改或删除时,可以快速和便捷地启动业务流程. 例如,如果一组用户在合作处理一个存储在服务器共享目录下的文档时,可以使用FileSystemWatcher组件编写应用程序来监视对共享目录的更

  • python中watchdog文件监控与检测上传功能

    引言 上一篇介绍完了观察者模式的原理,本篇想就此再介绍一个小应用,虽然我也就玩了一下午,是当时看observer正好找到的,以及还有Django-observer,但Django很久没用了,所以提下这个作为一个笔记. watchdog介绍 Watchdog的中文的"看门狗",有保护的意思.最早引入Watchdog是在单片机系统中,由于单片机的工作环境容易受到外界磁场的干扰,导致程序"跑飞",造成整个系统无法正常工作,因此,引入了一个"看门狗",对

  • c#实现数据同步的方法(使用文件监控对象filesystemwatcher)

    最近在项目中有这么个需求,就是得去实时获取某个在无规律改变的文本文件中的内容.首先想到的是用程序定期去访问这个文件,因为对实时性要求很高,间隔不能超过1S,而且每次获取到文本内容都要去分发给WEB服务器做别的操作,而那个文本的写入有时候会频繁,1秒可能多次,但是也有可能在相当长一段时间内是没有任何写入的. 这样一来如果每秒都去访问文件的话,一个是IO问题,还有就是每次操作都会引起后端一系列程序的反应,文本在长时间内无写入的话,一秒一次的触发一系列徒劳的事情太不可取了. 最终发现了c#中的File

  • python中文件变化监控示例(watchdog)

    在python中文件监控主要有两个库,一个是pyinotify ( https://github.com/seb-m/pyinotify/wiki),一个是watchdog(http://pythonhosted.org/watchdog/).pyinotify依赖于Linux平台的inotify,后者则对不同平台的的事件都进行了封装.因为我主要用于Windows平台,所以下面着重介绍watchdog(推荐大家阅读一下watchdog实现源码,有利于深刻的理解其中的原理). watchdog在不

  • 使用Inotify 监控目录与文件的方法详解

    1. 监控路径并打印所有发生在该路径的事件. 代码如下: 复制代码 代码如下: #include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/inotify.h>#include <unistd.h>#define EVENT_NUM 12char *event_str[EVENT_NUM] = { "IN_ACCESS", "IN_MOD

随机推荐