- °³¿ä
- ¼Ò½º
- FileSystemWatcher.h
- FileSystemWatcher.cpp
- Sample
1 °³¿ä
À©µµ¿ìÁî¿¡¼´Â ReadDirectoryChangesW ÇÔ¼ö¸¦ ÀÌ¿ëÇØ °£´ÜÈ÷ ó¸®ÇÒ ¼ö ÀÖ´Ù.
2 ¼Ò½º
ReadDirectoryChangesW ÇÔ¼ö´Â µ¿±â(synchronous) ¹æ½ÄÀ¸·Îµµ µ¿ÀÛÇϰí, ºñµ¿±â ¹æ½Ä(asynchronous)À¸·Îµµ µ¿ÀÛÇϴµ¥, "ÆÄÀÏ ½Ã½ºÅÛ ¸ð´ÏÅ͸µ"À̶ó´Â Ư¼º»ó ºñµ¿±â ¹æ½ÄÀ¸·Î »ç¿ëÇÏ´Â °Ô ÁÁ´Ù. µ¿±â ¹æ½ÄÀ¸·Î ó¸®Çϸé, ÆÄÀÏ ½Ã½ºÅÛ¿¡ º¯È°¡ »ý±æ ¶§±îÁö ÇÔ¼ö°¡ ¹ÝȯÀÌ µÇÁö ¾Ê±â ¶§¹®¿¡, µû·Î ½º·¹µå¸¦ ¸¸µéÁö ¾ÊÀ¸¸é, UI°¡ ¸ÔÅëÀÌ µÇ¹ö¸°´Ù. ¾Æ·¡ÀÇ »ùÇÃÀº AlertableIo ¹æ½ÄÀ» ÀÌ¿ëÇÑ ºñµ¿±â ¹æ½Ä »ùÇÃÀÌ´Ù. ÄÄÆÄÀÏÀº ¾Ë¾Æ¼, Àß~
////////////////////////////////////////////////////////////////////////////////
/// \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);
};
2.2 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);
}
2.3 Sample
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();
}
}
SeriousMoin v1 (koMoinMoin 1.0a4 Modified)