사용자 도구

사이트 도구


kb:windowsfilesystemmonitoring

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

kb:windowsfilesystemmonitoring [2014/11/09 21:12] (현재)
줄 1: 줄 1:
 +====== File System Monitoring ======
 +윈도우즈에서는 ReadDirectoryChangesW 함수를 이용해 간단히 처리할 수 있다.
 +
 +
 +====== Source ======
 +ReadDirectoryChangesW 함수는 동기(synchronous) 방식으로도 동작하고,​ 비동기 방식(asynchronous)으로도 동작하는데,​ "​파일 시스템 모니터링"​이라는 특성상 비동기 방식으로 사용하는 게 좋다. 동기 방식으로 처리하면,​ 파일 시스템에 변화가 생길 때까지 함수가 반환이 되지 않기 때문에, 따로 스레드를 만들지 않으면, UI가 먹통이 되버린다. 아래의 샘플은 AlertableIo 방식을 이용한 비동기 방식 샘플이다. 컴파일은 알아서, 잘~
 +
 +<file cpp FileSystemWatcher.h>​
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \file FileSystemWatcher.h
 +/// \author excel96
 +/// \date 2006.10.26
 +////////////////////////////////////////////////////////////////////////////////​
 +
 +#pragma once
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \class cFileSystemEvent
 +/// \brief 변경된 파일 시스템에 대한 정보.
 +///
 +/// 변경된 파일은 일반 파일일 수도 있고, 디렉토리일 수도 있다. 이름만으로는 ​
 +/// 변경된 것이 파일인지 디렉토리인지 구분할 수 없으므로,​ GetFileAttributes
 +/// 함수를 이용해서 구분하도록 한다.
 +////////////////////////////////////////////////////////////////////////////////​
 +
 +class cFileSystemEvent
 +{
 +public:
 +    enum ChangeType ​
 +    {
 +        CREATED, ///< 파일 생성
 +        CHANGED, ///< 파일 내용 변경
 +        DELETED, ///< 파일 삭제
 +        RENAMED, ///< 파일 이름 변경
 +        MAX,     ///<​ 배열을 위한 맥스값
 +    };
 +
 +
 +private:
 +    ChangeType ​ m_ChangeType; ​  ///<​ 변경의 종류
 +    std::string m_Directory; ​   ///< 디렉토리
 +    std::string m_FileName; ​    ///<​ 원래 파일 이름
 +    std::string m_NewFileName; ​ ///< 변경된 파일 이름
 +
 +
 +public:
 +    /// \brief 생성자
 +    cFileSystemEvent(ChangeType type, const std::​string&​ directory, ​
 +        const std::​string&​ fileName);
 +
 +    /// \brief 생성자
 +    cFileSystemEvent(const std::​string&​ directory, ​
 +        const std::​string&​ oldFileName,​ const std::​string&​ newFileName);​
 +
 +    /// \brief 소멸자
 +    ~cFileSystemEvent();​
 +
 +
 +public:
 +    /// \brief 디렉토리까지 포함한 파일 경로를 반환한다.
 +    std::string GetFullPath() const;
 +
 +    /// \brief 디렉토리까지 포함한 이전 파일 경로를 반환한다.
 +    std::string GetOldFullPath() const;
 +
 +    /// \brief 디렉토리까지 포함한 새로운 파일 경로를 반환한다.
 +    std::string GetNewFullPath() const;
 +
 +
 +public:
 +    /// \name Simple getter/​setter
 +    /// \{ 
 +    ChangeType GetChangeType() const { return m_ChangeType;​ }
 +    const std::​string&​ GetDirectory() const { return m_Directory;​ }
 +    const std::​string&​ GetFileName() const { return m_FileName; }
 +    const std::​string&​ GetOldFileName() const { return m_FileName; }
 +    const std::​string&​ GetNewFileName() const { return m_NewFileName;​ }
 +    /// \} 
 +};
 +
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \class cFileSystemWatcher
 +/// \brief 파일 시스템 변경 모니터링을 위한 클래스.
 +///
 +/// 클래스 인스턴스를 생성하고,​ Open 함수를 통해 모니터링할 디렉토리를 지정한 ​
 +/// 다음, 메인 루프 어딘가에서 Heartbeat() 함수를 지속적으로 호출해줘야 한다.
 +///
 +/// <pre>
 +///
 +/// cFileSystemWatcher watcher("​C:​\\Program Files"​);​
 +/// watcher.SetEventHandler(cFileSystemEvent::​CREATED,​ MyCreateHandler);​
 +/// watcher.SetEventHandler(cFileSystemEvent::​CHANGED,​ MyChangeHandler);​
 +/// watcher.SetEventHandler(cFileSystemEvent::​DELETED,​ MyDeleteHandler);​
 +/// watcher.SetEventHandler(cFileSystemEvent::​RENAMED,​ MyRenameHandler);​
 +/// ...
 +/// while (true)
 +/// {
 +///     ...
 +///     ​watcher.Heartbeat();​
 +/// }
 +/// </​pre>​
 +////////////////////////////////////////////////////////////////////////////////​
 +
 +class cFileSystemWatcher
 +{
 +public:
 +    typedef void (*PFN_EVENT_HANDLER)(const cFileSystemEvent&​ args);
 +
 +
 +private:
 +    struct MONITOR;
 +
 +    std::​string ​      ​m_Path; ​                               ///< 디렉토리 경로 문자열
 +    HANDLE ​           m_hDirectory; ​                         ///< 디렉토리 핸들
 +    MONITOR* ​         m_Monitor; ​                            ///<​ OVERLAPPED 구조체
 +    PFN_EVENT_HANDLER m_EventHandler[cFileSystemEvent::​MAX];​ ///< 이벤트 핸들러
 +
 +
 +public:
 +    /// \brief 생성자
 +    cFileSystemWatcher();​
 +
 +    /// \brief 생성자 + Open
 +    cFileSystemWatcher(const std::​string&​ directory);
 +
 +    /// \brief 소멸자
 +    virtual ~cFileSystemWatcher();​
 +
 +
 +public:
 +    /// \brief 모니터링을 시작한다.
 +    bool Open(const std::​string&​ directory);
 +
 +    /// \brief 모니터링을 중단한다.
 +    void Close();
 +
 +    /// \brief 객체의 상태가 정상적인지의 여부를 반환한다.
 +    bool IsGood() const;
 +
 +    /// \brief 폴링 함수
 +    void Heartbeat(DWORD period = 1);
 +
 +    /// \brief 이벤트 핸들러를 설정한다.
 +    void SetEventHandler(
 +        cFileSystemEvent::​ChangeType type, PFN_EVENT_HANDLER handler);
 +
 +    /// \brief 모니터링 중인 디렉토리를 반환한다.
 +    const std::​string&​ GetPath() const { return m_Path; }
 +
 +
 +private:
 +    /// \brief 변경 사항 요청을 포스트한다.
 +    bool PostChangeNotificationRequest(int operation);
 +
 +    /// \brief 파일 생성시 외부에서 호출하기 위한 함수
 +    void OnCreate(const std::​string&​ fileName);
 +
 +    /// \brief 파일 변경시 외부에서 호출하기 위한 함수
 +    void OnChange(const std::​string&​ fileName);
 +
 +    /// \brief 파일 삭제시 외부에서 호출하기 위한 함수
 +    void OnDelete(const std::​string&​ fileName);
 +
 +    /// \brief 파일 이름 변경시 외부에서 호출하기 위한 함수
 +    void OnRename(const std::​string&​ oldFileName,​ const std::​string&​ newFileName);​
 +
 +    /// \brief 완료 통지 함수
 +    static void CALLBACK FileSystemWatcherCallback(DWORD,​ DWORD, LPOVERLAPPED);​
 +};
 +</​file>​
 +
 +<file cpp FileSystemWatcher.cpp>​
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \file FileSystemWatcher.cpp
 +/// \author excel96
 +/// \date 2006.10.26
 +////////////////////////////////////////////////////////////////////////////////​
 +
 +#include "​PCH.h"​
 +#include "​FileSystemWatcher.h"​
 +
 +namespace
 +{
 +    /*
 +    const DWORD FILTER = 
 +        FILE_NOTIFY_CHANGE_SECURITY |
 +        FILE_NOTIFY_CHANGE_CREATION |
 +        FILE_NOTIFY_CHANGE_LAST_ACCESS |
 +        FILE_NOTIFY_CHANGE_LAST_WRITE |
 +        FILE_NOTIFY_CHANGE_SIZE |
 +        FILE_NOTIFY_CHANGE_ATTRIBUTES |
 +        FILE_NOTIFY_CHANGE_DIR_NAME |
 +        FILE_NOTIFY_CHANGE_FILE_NAME;​
 +    */
 +
 +    /// 작업의 종류
 +    enum Operation
 +    {
 +        CONTINUE_MONITORING, ​ ///< 모니터링을 계속 한다.
 +        STOP_MONITORING, ​     ///< 모니터링을 중단한다.
 +    };
 +
 +    /// 모니터링할 이벤트의 종류
 +    const DWORD FILTER = 
 +        FILE_NOTIFY_CHANGE_CREATION | 
 +        FILE_NOTIFY_CHANGE_LAST_WRITE |
 +        FILE_NOTIFY_CHANGE_SIZE |
 +        FILE_NOTIFY_CHANGE_DIR_NAME |
 +        FILE_NOTIFY_CHANGE_FILE_NAME;​
 +
 +    /// MONITOR 버퍼의 크기
 +    const size_t BUFFER_SIZE = sizeof(FILE_NOTIFY_INFORMATION) * 1024;
 +
 +    /// FILE_NOTIFY_INFORMATION 구조체 안에 와이드 문자열을 std::string 형태로 ​
 +    /// 변환해서 반환한다.
 +    std::string ExtractFileName(const FILE_NOTIFY_INFORMATION* info)
 +    {
 +        char fileName[1024] = {0, };
 +        int count = WideCharToMultiByte(
 +            CP_ACP, 0, info->​FileName,​ info->​FileNameLength / sizeof(WCHAR), ​
 +            fileName, _ARRAYSIZE(fileName) - 1, NULL, NULL);
 +        fileName[count] = '​\0';​
 +        return std::​string(fileName);​
 +    }
 +
 +    /// 경로 끝에다 백슬래쉬를 추가한 경로를 반환한다.
 +    std::string AddBackslash(const std::​string&​ path)
 +    {
 +        if (path.empty()) return std::​string(""​);​
 +        return path[path.size()-1] != '​\\'​ ? path + std::​string("​\\"​) : path;
 +    }
 +
 +    /// 디렉토리 + 파일 이름을 합쳐서 전체 경로를 생성한다.
 +    std::string Combine(const std::​string&​ dir, const std::​string&​ file)
 +    {
 +        return AddBackslash(dir) + file;
 +    }
 +
 +    /// 디렉토리가 존재하는지의 여부를 반환한다.
 +    bool IsDirectoryExist(const std::​string&​ path)
 +    {
 +        DWORD attr = GetFileAttributes(path.c_str());​
 +        return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);​
 +    }
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 생성자
 +/// \param type 변경의 종류
 +/// \param directory 디렉토리
 +/// \param fileName 파일 이름
 +////////////////////////////////////////////////////////////////////////////////​
 +cFileSystemEvent::​cFileSystemEvent(ChangeType type, 
 +                                   const std::​string&​ directory, ​
 +                                   const std::​string&​ fileName)
 +: m_ChangeType(type), ​
 +m_Directory(directory), ​
 +m_FileName(fileName)
 +{
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 생성자
 +/// \param directory 디렉토리
 +/// \param oldFileName 원래 이름
 +/// \param newFileName 변경된 이름
 +////////////////////////////////////////////////////////////////////////////////​
 +cFileSystemEvent::​cFileSystemEvent(const std::​string&​ directory, ​
 +                                   const std::​string&​ oldFileName, ​
 +                                   const std::​string&​ newFileName)
 +: m_ChangeType(RENAMED),​
 +m_Directory(directory), ​
 +m_FileName(oldFileName),​
 +m_NewFileName(newFileName)
 +{
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 소멸자
 +////////////////////////////////////////////////////////////////////////////////​
 +cFileSystemEvent::​~cFileSystemEvent()
 +{
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 디렉토리까지 포함한 파일 경로를 반환한다.
 +/// \return std::string 경로 문자열
 +////////////////////////////////////////////////////////////////////////////////​
 +std::string cFileSystemEvent::​GetFullPath() const
 +{
 +    return Combine(m_Directory,​ m_FileName);​
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 디렉토리까지 포함한 이전 파일 경로를 반환한다.
 +/// \return std::string 경로 문자열
 +////////////////////////////////////////////////////////////////////////////////​
 +std::string cFileSystemEvent::​GetOldFullPath() const
 +{
 +    return Combine(m_Directory,​ m_FileName);​
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 디렉토리까지 포함한 새로운 파일 경로를 반환한다.
 +/// \return std::string 경로 문자열
 +////////////////////////////////////////////////////////////////////////////////​
 +std::string cFileSystemEvent::​GetNewFullPath() const
 +{
 +    return Combine(m_Directory,​ m_NewFileName);​
 +}
 +
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \struct cFileSystemWatcher::​MONITOR
 +/// \brief 비동기 함수 호출을 위한 OVERLAPPED 구조체
 +////////////////////////////////////////////////////////////////////////////////​
 +
 +struct cFileSystemWatcher::​MONITOR : public OVERLAPPED
 +{
 +    BYTE                Buffer[BUFFER_SIZE];​ ///< 버퍼
 +    int                 ​Operation; ​          ///<​ 작업의 종류
 +    cFileSystemWatcher* Watcher; ​            ///<​ 왓처 객체
 +};
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 생성자
 +////////////////////////////////////////////////////////////////////////////////​
 +cFileSystemWatcher::​cFileSystemWatcher()
 +: m_hDirectory(INVALID_HANDLE_VALUE),​ m_Monitor(NULL)
 +{
 +    ZeroMemory(m_EventHandler,​ sizeof(PFN_EVENT_HANDLER) * cFileSystemEvent::​MAX);​
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 생성자 + Open
 +/// \param directory 모니터링할 디렉토리
 +////////////////////////////////////////////////////////////////////////////////​
 +cFileSystemWatcher::​cFileSystemWatcher(const std::​string&​ directory)
 +: m_hDirectory(INVALID_HANDLE_VALUE),​ m_Monitor(NULL)
 +{
 +    ZeroMemory(m_EventHandler,​ sizeof(PFN_EVENT_HANDLER) * cFileSystemEvent::​MAX);​
 +
 +    if (!Open(directory))
 +        Close();
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 소멸자
 +////////////////////////////////////////////////////////////////////////////////​
 +cFileSystemWatcher::​~cFileSystemWatcher()
 +{
 +    Close();
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 모니터링을 시작한다.
 +/// \param directory 모니터링할 디렉토리
 +/// \return bool 무사히 모니터링을 시작했다면 true, 뭔가 에러가 생겼다면 false
 +////////////////////////////////////////////////////////////////////////////////​
 +bool cFileSystemWatcher::​Open(const std::​string&​ directory)
 +{
 +    Close();
 +
 +    bool success = false;
 +
 +    do 
 +    {
 +        m_Path = AddBackslash(directory);​
 +        if (!IsDirectoryExist(m_Path))
 +            break;
 +
 +        m_hDirectory = CreateFile(m_Path.c_str(),​
 +            FILE_LIST_DIRECTORY,​
 +            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,​
 +            NULL,
 +            OPEN_EXISTING,​
 +            FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,​
 +            NULL
 +            );
 +
 +        if (m_hDirectory == INVALID_HANDLE_VALUE)
 +            break;
 +
 +        m_Monitor = reinterpret_cast<​MONITOR*>​(HeapAlloc(GetProcessHeap(),​ 0, sizeof(MONITOR)));​
 +        if (!m_Monitor)
 +            break;
 +
 +        ZeroMemory(m_Monitor,​ sizeof(MONITOR));​
 +        m_Monitor->​Watcher = this;
 +
 +        if (!PostChangeNotificationRequest(CONTINUE_MONITORING))
 +            break;
 +
 +        success = true;
 +    } while(0);
 +
 +    if (!success)
 +        Close();
 +
 +    return success;
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 모니터링을 중지한다.
 +////////////////////////////////////////////////////////////////////////////////​
 +void cFileSystemWatcher::​Close()
 +{
 +    m_Path = "";​
 +
 +    if (m_hDirectory != INVALID_HANDLE_VALUE)
 +    {
 +        CloseHandle(m_hDirectory);​
 +        m_hDirectory = INVALID_HANDLE_VALUE;​
 +    }
 +
 +    if (m_Monitor)
 +    {
 +        HeapFree(GetProcessHeap(),​ 0, m_Monitor);
 +        m_Monitor = NULL;
 +    }
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 객체의 상태가 정상적인지의 여부를 반환한다.
 +/// \return bool 정상적이라면 true
 +////////////////////////////////////////////////////////////////////////////////​
 +bool cFileSystemWatcher::​IsGood() const
 +{
 +    return m_hDirectory != INVALID_HANDLE_VALUE && m_Monitor != NULL;
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 폴링 함수
 +/// \param period 비동기 함수 호출 결과를 처리할 시간
 +////////////////////////////////////////////////////////////////////////////////​
 +void cFileSystemWatcher::​Heartbeat(DWORD period)
 +{
 +    if (IsGood())
 +    {
 +        SleepEx(period,​ TRUE); // make thread alertable
 +    }
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 이벤트 핸들러를 설정한다.
 +/// \param type 이벤트의 종류
 +/// \param handler 핸들러
 +////////////////////////////////////////////////////////////////////////////////​
 +void cFileSystemWatcher::​SetEventHandler(
 +    cFileSystemEvent::​ChangeType type, cFileSystemWatcher::​PFN_EVENT_HANDLER handler)
 +{
 +    if (0 <= type && type < cFileSystemEvent::​MAX)
 +        m_EventHandler[type] = handler;
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 변경 사항 요청을 포스트한다.
 +/// \param operation 작업의 종류
 +/// \return bool 무사히 실행했다면 true 뭔가 에러가 생겼다면 false
 +////////////////////////////////////////////////////////////////////////////////​
 +bool cFileSystemWatcher::​PostChangeNotificationRequest(int operation)
 +{
 +    if (!IsGood()) return false;
 +
 +    m_Monitor->​Operation = operation;
 +
 +    DWORD bytesReturned = 0;
 +    DWORD bufferSize = static_cast<​DWORD>​(BUFFER_SIZE);​
 +
 +    if (ReadDirectoryChangesW(m_hDirectory,​ m_Monitor->​Buffer,​ bufferSize, ​
 +        TRUE, FILTER, &​bytesReturned,​ m_Monitor, FileSystemWatcherCallback))
 +    {
 +        return true;
 +    }
 +    else
 +    {
 +        return false;
 +    }
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 파일 생성시 외부에서 호출하기 위한 함수
 +/// \param fileName 생성된 파일 이름
 +////////////////////////////////////////////////////////////////////////////////​
 +void cFileSystemWatcher::​OnCreate(const std::​string&​ fileName)
 +{
 +    if (m_EventHandler[cFileSystemEvent::​CREATED])
 +    {
 +        cFileSystemEvent evt(cFileSystemEvent::​CREATED,​ m_Path, fileName);
 +        m_EventHandler[cFileSystemEvent::​CREATED](evt);​
 +    }
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 파일 변경시 외부에서 호출하기 위한 함수
 +/// \param fileName 변경된 파일 이름
 +////////////////////////////////////////////////////////////////////////////////​
 +void cFileSystemWatcher::​OnChange(const std::​string&​ fileName)
 +{
 +    if (m_EventHandler[cFileSystemEvent::​CHANGED])
 +    {
 +        cFileSystemEvent evt(cFileSystemEvent::​CHANGED,​ m_Path, fileName);
 +        m_EventHandler[cFileSystemEvent::​CHANGED](evt);​
 +    }
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 파일 삭제시 외부에서 호출하기 위한 함수
 +/// \param fileName 삭제된 파일 이름
 +////////////////////////////////////////////////////////////////////////////////​
 +void cFileSystemWatcher::​OnDelete(const std::​string&​ fileName)
 +{
 +    if (m_EventHandler[cFileSystemEvent::​DELETED])
 +    {
 +        cFileSystemEvent evt(cFileSystemEvent::​DELETED,​ m_Path, fileName);
 +        m_EventHandler[cFileSystemEvent::​DELETED](evt);​
 +    }
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 파일 이름 변경시 외부에서 호출하기 위한 함수
 +/// \param oldFileName 원래 파일 이름
 +/// \param newFileName 변경된 파일 이름
 +////////////////////////////////////////////////////////////////////////////////​
 +void cFileSystemWatcher::​OnRename(const std::​string&​ oldFileName,​ const std::​string&​ newFileName)
 +{
 +    if (m_EventHandler[cFileSystemEvent::​RENAMED])
 +    {
 +        cFileSystemEvent evt(m_Path, oldFileName,​ newFileName);​
 +        m_EventHandler[cFileSystemEvent::​RENAMED](evt);​
 +    }
 +}
 +
 +////////////////////////////////////////////////////////////////////////////////​
 +/// \brief 완료 통지 함수
 +/// \param errorCode 에러 코드
 +/// \param bytesTransferred 실제로 처리한 양
 +/// \param overlapped ReadDirectoryChangesW 함수에다 넘긴 오버랩드 구조체
 +////////////////////////////////////////////////////////////////////////////////​
 +void CALLBACK cFileSystemWatcher::​FileSystemWatcherCallback(
 +    DWORD errorCode, DWORD bytesTransferred,​ LPOVERLAPPED overlapped)
 +{
 +    cFileSystemWatcher::​MONITOR* monitor = 
 +        reinterpret_cast<​cFileSystemWatcher::​MONITOR*>​(overlapped);​
 +    cFileSystemWatcher* watcher = monitor->​Watcher;​
 +
 +    if (errorCode == ERROR_SUCCESS)
 +    {
 +        PFILE_NOTIFY_INFORMATION info = NULL;
 +        size_t offset = 0;
 +        std::string fileName, oldFileName,​ newFileName;​
 +
 +        do
 +        {
 +            info = reinterpret_cast<​PFILE_NOTIFY_INFORMATION>​(&​monitor->​Buffer[offset]);​
 +            offset += info->​NextEntryOffset;​
 +
 +            if (info->​Action == FILE_ACTION_ADDED)
 +            {
 +                fileName = ExtractFileName(info);​
 +                watcher->​OnCreate(fileName);​
 +            }
 +            else if (info->​Action == FILE_ACTION_REMOVED)
 +            {
 +                fileName = ExtractFileName(info);​
 +                watcher->​OnDelete(fileName);​
 +            }
 +            else if (info->​Action == FILE_ACTION_MODIFIED)
 +            {
 +                fileName = ExtractFileName(info);​
 +                watcher->​OnChange(fileName);​
 +            }
 +            else if (info->​Action == FILE_ACTION_RENAMED_OLD_NAME)
 +            {
 +                oldFileName = ExtractFileName(info);​
 +            }
 +            else if (info->​Action == FILE_ACTION_RENAMED_NEW_NAME)
 +            {
 +                newFileName = ExtractFileName(info);​
 +                watcher->​OnRename(oldFileName,​ newFileName);​
 +            }
 +        } while (info->​NextEntryOffset != 0);
 +    }
 +
 +    if (monitor->​Operation == CONTINUE_MONITORING)
 +        watcher->​PostChangeNotificationRequest(CONTINUE_MONITORING);​
 +}
 +</​file>​
 +
 +====== Sample ======
 +<code cpp>
 +void OnFileCreate(const cFileSystemEvent&​ evt)
 +{
 +    std::cout << evt.GetFullPath() << " created"​ << std::endl;
 +}
 +
 +void OnFileChange(const cFileSystemEvent&​ evt)
 +{
 +    std::cout << evt.GetFullPath() << " changed"​ << std::endl;
 +}
 +
 +void OnFileDelete(const cFileSystemEvent&​ evt)
 +{
 +    std::cout << evt.GetFullPath() << " deleted"​ << std::endl;
 +}
 +
 +void OnFileRename(const cFileSystemEvent&​ evt)
 +{
 +    std::cout << evt.GetOldFullPath() << " rename to " << evt.GetNewFullPath() << std::endl;
 +}
 +
 +void main()
 +{
 +    cFileSystemWatcher watcher("​C:​\\Program Files"​);​
 +
 +    watch.SetEventHandler(cFileSystemEvent::​CREATED,​ OnFileCreate);​
 +    watch.SetEventHandler(cFileSystemEvent::​CHANGED,​ OnFileChange);​
 +    watch.SetEventHandler(cFileSystemEvent::​DELETED,​ OnFileDelete);​
 +    watch.SetEventHandler(cFileSystemEvent::​RENAMED,​ OnFileRename);​
 +
 +    while (true)
 +    {
 +        watcher.Heartbeat();​
 +    }
 +}
 +</​code>​
  
kb/windowsfilesystemmonitoring.txt · 마지막으로 수정됨: 2014/11/09 21:12 (바깥 편집)