转载:http://www.cnblogs.com/doublesnke/archive/2011/08/16/2141374.html

VC++实施文件监控:实例和详解

相关帮助: http://hi.baidu.com/jiahaosoft/blog/item/b441d1218eebece0d6cae274.html

我这里只介绍采用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.

效果如下:

不足的地方:

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

2. 转载:http://blog.csdn.net/visualeleven/article/details/7562014

 // .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文件
#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, , sizeof(OVERLAPPED));
pBuffer = NULL;
dwBufferSize = ;
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, , sizeof(m_szDirectory)); m_pThread = AfxBeginThread(ThreadProc, NULL, , CREATE_SUSPENDED, , 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, , );
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( == _tcslen(m_szDirectory))
{
StringCchPrintf(m_szDirectory, _countof(m_szDirectory), _T("%s"), lpszDirectory);
}
else if(CSTR_EQUAL != CompareStringOrdinal(m_szDirectory, -, lpszDirectory, -, 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, , );
} return FALSE;
} UINT __cdecl CDirectoryWatch::DirectoryWatch(LPVOID lParam)
{
WATCH_PARAMETERS* pParam = (WATCH_PARAMETERS*)lParam;
if(NULL == pParam)
{
return ;
}
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 = ;
DWORD dwRet = WAIT_FAILED;
DWORD dwOffSet = ;
TCHAR szFile[MAX_PATH] = {};
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, )))
{
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 ;
} 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, , 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, , ))
{
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, , 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 ;
}
 // 测试代码

 #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] = {};
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( * );
watch.StopDirectoryWatch();
wprintf(L"Stop Directory Watch ...\n"); Sleep( * ); wprintf(L"Start Directory Watch ...\n");
watch.StartDirectoryWatch(_T("F:\\11"), NotifyAction);
Sleep( * );
watch.StopDirectoryWatch();
wprintf(L"Stop Directory Watch ...\n");
Sleep( * );
wprintf(L"Process Exit ...\n");
return ;
}

效果如下图所示:

2011-11-13

[C++]使用ReadDirectoryChangesW API監控檔案系統的改變

[C++]使用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            = ;
char* buffer = new char[nBufferSize];
DWORD dwBytes = ; memset(buffer, , 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 = ; 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[]; WideCharToMultiByte(CP_ACP, , 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 = ;
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()
{
DWORD dwBytes = ; memset(buffer, , 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 = ; 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[]; WideCharToMultiByte(CP_ACP, , 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\\新增資料夾");
 

運行後去對監控的目錄操作~可得到類似如下的結果:

VC++ 监控指定目录改变的更多相关文章

  1. python多线程监控指定目录

    import win32file import tempfile import threading import win32con import os dirs=["C:\\WINDOWS\ ...

  2. 使用WatchService监控指定目录内的文件的改动

    package coin; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Pat ...

  3. C#监控指定目录的文件变化的代码

    如下的资料是关于C#监控指定目录的文件变化的代码. FileSystemWatcher watcher = new FileSystemWatcher();watcher.Path = @" ...

  4. [Erlang27]如何监控指定目录下的*.beam文件,如果有改动就更新到指定的节点?

    在Erlang In Anger第二章中讲到使用rebar来创建一个Erlang项目(Application或Project) 但美中不足的只是给出了指引,但没有给出详细的步骤. 下面我们就使用reb ...

  5. vc++ 监控指定路径下文件变化

    参考MSDN文档 https://docs.microsoft.com/zh-cn/windows/desktop/api/winbase/nf-winbase-readdirectorychange ...

  6. Window Linux下实现指定目录内文件变更的监控方法

    转自:http://qbaok.blog.163.com/blog/static/10129265201112302014782/ 对于监控指定目录内文件变更,window 系统提供了两个未公开API ...

  7. 使用FileSystemWatcher监视指定目录

    使用 FileSystemWatcher 监视指定目录中的更改.可监视指定目录中的文件或子目录的更改. 以下是一个简单的实例,用来监控指定目录下文件的新增.删除.重命名等情况(文件内容更改会触发多次, ...

  8. [转]C# FileSystemWatcher监控指定文件或目录的文件的创建、删除、改动、重命名等活动

    觉得这个很常用..比如一些软件.   http://www.rabbit8.cn/DoNet/407.html   FileSystemWatcher控件主要功能: 监控指定文件或目录的文件的创建.删 ...

  9. zabbix的日常监控-自动发现端口并监测(服务器开启的所有端口或监控指定端口)(十三)

    动批量检查agent开放的端口 注:此方法给监控磁盘IO(即十二)篇过程一样: 注释:如果服务器上的应用都是固定的,不会随机产生的都可以使用自动发现端口来监控:  如果服务器会随机出现端口且每次启动程 ...

随机推荐

  1. java通过LinkedList实现堆栈和队列数据结构

    package shb.java.demo3; import java.util.LinkedList; public class TestLinkedList { /** * @author sha ...

  2. MyEclipse安装插件的三种方法和使用心得

    本文讲解MyEclipse(MyEclipse10)的三种方法,以TestNG为例 Eclipse update site URL:  http://beust.com/eclipse. 一.通过My ...

  3. C语言资源

    0.C自带库/函数在线文档 http://www.acm.uiuc.edu/webmonkeys/book/c_guide/ 1.so文件制作和使用 http://blog.csdn.net/love ...

  4. android 学习随笔六(网络要求及配置)

    android在4.0之后已经不允许在主线程执行http请求了. 主线程阻塞,应用会停止刷新界面,停止响应用户任何操作,耗时操作不要写在主线程   只有主线程才能修改UI ANR异常:Applicat ...

  5. JavaScript复习笔记——字符串

    String构造器可以使用new调用,也可以不使用,但是,这两种调用的结果也是完全不一样的.用new调用的时候,String作为构造器函数,创建字符串对象.不使用new的时候,String用作一个常规 ...

  6. 人工智能深度学习Caffe框架介绍,优秀的深度学习架构

    人工智能深度学习Caffe框架介绍,优秀的深度学习架构 在深度学习领域,Caffe框架是人们无法绕过的一座山.这不仅是因为它无论在结构.性能上,还是在代码质量上,都称得上一款十分出色的开源框架.更重要 ...

  7. JDBC的几种驱动

    不同的数据库的驱动是不同的 其中:Access驱动串---------sun.jdbc.odbc.JdbcOdbcDriver    MySQL驱动串---------com.mysql.jdbc.D ...

  8. Oracle之虚拟索引

    一.引言 DBA在日常维护管理数据库进行低性能SQL分析时,有时候需要通过创建索引对SQL进行优化,但有些时候我们创建的索引是否能用到?这个只能创建以后才能看出效果,但是在实际工作中,特别是对大表创建 ...

  9. php curl向远程服务器上传文件

    <?php /** * test.php: */ header('content-type:text/html;charset=utf8'); $ch = curl_init(); //加@符号 ...

  10. iOS-网址集

    0. 在线工具 http://tool.lu 1. iOS学习笔记汇总链接 https://blog.6ag.cn/533.html 2.iOS开发内购全套图文教程http://mp.weixin.q ...