Synhronize

Скачать cpp-файлы...
Скачать проект целиком...

Краткое описание программы:

Оконное приложение, основанное на mfc. В главном окне имеется два editbox-а, в один вводится папка входных данных, в другой - папка выходных данных. По нажатию на кнопку "Старт" начинается слежение за изменениями во входной папке. Как только что-то происходит (нопример, в папку попадает файл), программа просматривает всё содержимое папки (включая то, что было в ней до изменений) и переносит все найденные файлы в выходную папку.

Затрагиваемые темы: работа с файловой системой, события, wait-функции, создание потоков, работа с интерфейсом.

Описание используемых функций:

MoveFile

Эта функция переносит в заданную директорию файл или папку (включая все её подпапки). Может также использоваться для переименования файла/папки. Возвращаемое значение - успех/неудача.

BOOL MoveFile(
   LPCTSTR lpExistingFileName, //Полный путь к переносимому файлу/папке
   LPCTSTR lpNewFileName //Полный путь к файлу/папке в новом месте
);

Более подробную информацию можно получить в MSDN.

Как используется в данной программе:

void ProcessFile (LPTSTR fname) //Обработчик файла
{//Я перемещу файл из g_strInFolder в g_strOutFolder
   MoveFile (g_strInFolder+fname, g_strOutFolder+fname);
}

CreateEvent

Эта функция создаёт или открывает существующее событие, возвращаемым значением является его описатель.

HANDLE CreateEvent(
   LPSECURITY_ATTRIBUTES lpEventAttributes, //Аттрибуты защиты
   BOOL bManualReset, //Ручной сброс
   BOOL bInitialState, //Состояние при создании
   LPCTSTR lpName //Имя (если необходимо)
);

Рассмотрим подробнее некоторые параметры функции:
lpEventAttributes - в качестве этого параметра передаётся адрес структуры вида:

typedef struct _SECURITY_ATTRIBUTES {
   DWORD nLength; //Размер структуры (как правило, берётся sizeof)
   LPVOID lpSecurityDescriptor; //Указатель на дескриптор, контролирующий совместное                                        //использование объекта
   BOOL bInheritHandle; //Флаг, разрешающий наследование объекта дочерним процессом
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES;

bManualReset - если этот параметр true, то помещение объекта в несигнальное состояние нужно производить вручную (путём вызова спецмальной функции). Если же передать сюда false, то событие будет обладать автосбросом, т.е. автоматически возвращаться в несигнальное состояние.
bInitialState - если этот параметр равен true, начальное состояние события - сигнальное, в противном случае - несигнальное.

Более подробную информацию можно получить в MSDN.

Как используется в данной программе:

BOOL CSynhronizeDlg::OnInitDialog()
{
   //...
   g_hStopEvent= CreateEvent(NULL, FALSE, FALSE, NULL); //Создаём событие
   //...
}
//...
void CSynhronizeDlg::OnBnClickedButton1() //Обработчик нажатия кнопки
{
   if (m_hThread==NULL) { //Если поток ещё не создан, значит нажата кнопка "старт"
      //...
   }
   else //Иначе - нажата кнопка "стоп"
   {
      //stop WorkThread
      SetEvent(g_hStopEvent); //Делаем событие сигнальным
      //...
   }
}
//В продолжение см. пример к FindFirstChangeNotification

WaitForMultipleObjects

Эта функция приостанавливает выполнение текущего потока до тех пор, пока один или все указанные в её параметрах объекты ядра не придут в сигнальное состояние (также возможен выход по таймауту). Применяется для ограниничения доступа к разделяемым ресурсам. Параметром чаще всего служат события, семафоры или мьютексы, уведомления (notification), процессы, потоки и некоторые другие объекты. Возвращаемое значение показывает, что послужило выходом из функции. Это может быть значение от WAIT_OBJECT_0 до (WAIT_OBJECT_0 + nCount– 1) - номер объекта ядра, пришедшего в сигнальное состояние (в случае, если мы ожидаем любого из них), от WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount– 1) - специфическое значение в случае использования мьютексов (номер мьютекса, его вызвавшего) или WAIT_TIMEOUT - выход по таймауту.

DWORD WaitForMultipleObjects(
   DWORD nCount, //Число описателей в массиве
   const HANDLE* lpHandles, //Массив описателей на ожидаемые объекты
   BOOL bWaitAll, //Флаг - ждать один или все объекты
   DWORD dwMilliseconds //Таймаут
);

Рассмотрим подробнее некоторые параметры функции:
lpHandles - в этом параметре нужно передавать массив из описателей на существующие объекты ядра (они могут быть разными в рамках одного массива). При этом учитываться функцией будет только nCount объектов, начиная с нулевого элемента массива, а всего их должно быть не более MAXIMUM_WAIT_OBJECTS (константа, равная 64).
bWaitAll - нужно передавать true, если необходимо дождаться сигнального состояния всех объектов, и false, если достаточно одного любого (по какому из них произошёл выход можно вычислить по возвращённому функцией значению - индекс в массиве описателей легко вычисляется по формуле возвращённое_значение-WAIT_OBJECT_0).
dwMilliseconds - таймаут, по истечению которого функция вернёт управление в случае, если за это время не выполнится условие, связанное с объектами ядра. Если выход по таймауту не нужен - сюда передаётся константа INFINITE.

Более подробную информацию можно получить в MSDN.

Как используется в данной программе: см. пример к FindFirstChangeNotification.

FindFirstChangeNotification
FindNextChangeNotification
FindCloseChangeNotification

Функция FindFirstChangeNotification создаёт описатель объекта ядра "уведомление", с помощью которого можно отслеживать заданные фильтром изменения в директории или её поддереве. При выполнении заданного условия (например, появления новых файлов, переименования файлов, изменение их размеров или аттрибутов и т.п.) объект приходит в сигнальное состояние, что можно отследить какой-нибудь wait-функцией. После первого изменения можно продолжить ожидание (т.е. по сути вернуть "уведомление" в несигнальное состояние и направить к ожиданию изменений) с помощью функции FindNextChangeNotification. После завершения слежения необходимо вызывать функцию FindCloseChangeNotification, чтобы освободить объект ядра "уведомление".

HANDLE FindFirstChangeNotification(
   LPCTSTR lpPathName, //Путь к директории, изменения в которой будут отслеживаться
   BOOL bWatchSubtree, //Флаг, указывающий просматривать ли поддерево каталога
   DWORD dwNotifyFilter //Фильтр, т.е указание, что именно отслеживать
);

BOOL FindNextChangeNotification(
   HANDLE hChangeHandle //Описатель "уведомления", полученный из предыдущей функции
);

BOOL FindCloseChangeNotification(
    HANDLE hChangeHandle //Описатель "уведомления"
);

Рассмотрим подробнее некоторые параметры функции FindFirstChangeNotification:
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_SECURITY.

Более подробную информацию можно получить в MSDN (FindFirstChangeNotification, FindNextChangeNotification, FindCloseChangeNotification).

Как используется в данной программе:

HANDLE hNotification= FindFirstChangeNotification(g_strInFolder, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME); //Начинаем отслеживать изменения в заданной папке посредством специальной функции
if (hNotification==INVALID_HANDLE_VALUE) //Если создать описатель не удалось, значит заданного пути не существует
{
   MessageBox (NULL, "Wrong path", "Error", MB_OK);
   return -1;
}
HANDLE pHandles[2]; //Объявляем массив описателей для функции WaitForMultipleObjects
pHandles[0]= g_hStopEvent; //Одним элементом будет событие (нажатие кнопки "стоп")
pHandles[1]= hNotification; //Другим - наш описатель, отслеживающий изменения в папке
while(1) //Бесконечный цикл
{
   DWORD dwResult= WaitForMultipleObjects(2, pHandles, FALSE, INFINITE); //Ждём
   if (dwResult==WAIT_OBJECT_0) //Нажата кнопка "стоп" - выходим из цикла
      break;
   //...
   FindNextChangeNotification(hNotification); //И включаем ожидание следующего изменения в папке
}//while (1)
FindCloseChangeNotification(hNotification);

FindFirstFile
FindNextFile
FindClose

Функция FindFirstFile создаёт описатель "поиск" (возвращаемое значение) и начинает поиск файлов и папок в заданной директории, соответствующих определённой маске. Продолжать поиск следует через функцию FindNextFile, которая работает с уже существующим описателем и возвращает bool-значение, показывающее, найдено ли ещё что-то в директории. После окончания поиска его следует закрыть функцией FindClose.

HANDLE FindFirstFile(
   LPCTSTR lpFileName, //Директория для поиска и маска, по которой следует отбирать найденное
   LPWIN32_FIND_DATA lpFindFileData //Информация о найденном файле/папке
);

BOOL FindNextFile(
    HANDLE hFindFile, //Описатель, созданный FindFirstFile
   LPWIN32_FIND_DATA lpFindFileData //Информация о найденном файле/папке
);

BOOL FindClose(
   HANDLE hFindFile //Описатель, созданный FindFirstFile
);

Рассмотрим подробнее некоторые параметры функций:
lpFileName - здесь передаётся существующий путь и имя файла (или маска), т.е. после указания пути можно задать фильтр поиска при помощи символов '*' (любое количество любых символов) и '?' (один любой символ). Например, для поиска всех файлов можно задать маску *.* - любое имя файла с любым расширением (в данном случае фильтр также пройдут . и .. - указатели на родительскую и корневую директории).
lpFindFileData - указатель на структуру WIN32_FIND_DATA следующего вида:

typedef struct _WIN32_FIND_DATA {
   DWORD dwFileAttributes; //Аттрибуты файла
   FILETIME ftCreationTime; //Время создания
   FILETIME ftLastAccessTime; //Время последнего открытия
   FILETIME ftLastWriteTime; //Время последней записи
   DWORD nFileSizeHigh;
   DWORD nFileSizeLow;
   DWORD dwReserved0;
   DWORD dwReserved1;
   TCHAR cFileName[MAX_PATH]; //Имя файла
   TCHAR cAlternateFileName[14]; //Альтернативное имя файла
} WIN32_FIND_DATA, *PWIN32_FIND_DATA;

Это возвращаемое значение, из этой структуры мы можем получить всю необходимую информацию о найденном файле или папке. К тому же, по первому полю этой структуры (dwFileAttributes) мы можем узнать, к примеру, файл или папку мы нашли.

Более подробную информацию можно получить в MSDN (FindFirstFile, FindNextFile, FindClose).

Как используется в данной программе:

HANDLE hFindFile= FindFirstFile (g_strInFolder+"\\*.*", &fd); //Начинаем просматривать папку
BOOL bContinue=(hFindFile!= INVALID_HANDLE_VALUE);
//Флаг, означающий, есть ли ещё в папке нерассмотренные объекты
while (bContinue)
{
   if ((fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)==0)
//Если это файл (т.е. если не является директорией)
{
       ProcessFile(fd.cFileName); //Обработка
}
    bContinue= FindNextFile(hFindFile, &fd); //Ищем следующий объект в папке
}//while (bContinue)
FindClose(hFindFile);
//Когда всё, что было в папке на начало поиска, рассмотрено, закрываем поиск

WaitForSingleObject

Эта функция приостанавливает выполнение текущего потока до тех пор, пока указанный в её параметрах объект ядра не придёт в сигнальное состояние (также возможен выход по таймауту). Применяется для ограниничения доступа к разделяемым ресурсам. Параметром чаще всего служит событие, семафор или мьютекс, но также в качестве параметра может выступать уведомление (notification), процесс, поток и некоторые другие объекты. Возвращаемое значение показывает, что послужило выходом из функции. Это может быть WAIT_ABANDONED (специфическое значение, возвращаемое в случае завершения потока, владеющего мьютексом), WAIT_OBJECT_0 (объект получил сигнальное состояние - в этом случае функция сама переводит его в несигнальное, а для семафора наращивает счётчик числа занятых ресурсов), WAIT_TIMEOUT (функция вышла по таймауту).

DWORD WaitForSingleObject(
   HANDLE hHandle, //Описатель объекта ядра, сигнальное состояние которого нас интересует
   DWORD dwMilliseconds //Таймаут, по истечению которого прервать ожидание
);

Рассмотрим подробнее некоторые параметры функции:
dwMilliseconds - здесь можно указать любой необходимый таймаут, кроме того, если указать 0, функция вернёт потоку управление сразу (таким образом можно проверить состояние объекта), а если указать константу
INFINITE, функция не будет учитывать время и будет ждать только сигнального состояния объекта ядра.

Более подробную информацию можно получить в MSDN.

Как используется в данной программе:

WaitForSingleObject(m_hThread, INFINITE); //Ждём, пока поток завершит работу

CreateThread

Эта функция создаёт поток внутри адресного пространства текущего процесса. Возвращает описатель созданного потока. Функция полезна, когда, например, нужно выполнять какие-то действия в оконном приложении, но не отключать при этом его интерфейс. В общем случае поток начинает работу сразу после вызова этой функции, и все действия, которые он выполняет, не мешают работе программы.

HANDLE CreateThread(
   LPSECURITY_ATTRIBUTES lpThreadAttributes, //Аттрибуты защиты
   SIZE_T dwStackSize, //Размер стека потока (если указать 0, то берётся по умолчанию)
   LPTHREAD_START_ROUTINE lpStartAddress, //Адрес стартовой функции
   LPVOID lpParameter, //Параметр для передачи потоку
   DWORD dwCreationFlags, //Служебные флаги
   LPDWORD lpThreadId //ID потока
);

Рассмотрим подробнее некоторые параметры функции:
lpStartAddress - указатель на стартовую функцию потока (т.е. её название), которую надо объявить внутри приложения. Она должна иметь определённый вид:

DWORD WINAPI ThreadProc( //Имя функции может быть произвольным
   LPVOID lpParameter
);

lpParameter - параметр, передаваемый в стартовую функцию потока. Если потоку необходимо передать несколько параметров, следует либо использовать глобальные переменные, либо объявлять структуру со всеми необходимыми данными и передавать её.
dwCreationFlags - в основном этот параметр используется для того, чтобы обозначить, следует ли запустить поток сразу после создания или по вызову функции ResumeThread (в первом случае в параметре можно передать 0, во втором - флаг CREATE_SUSPENDED).
lpThreadId - возвращаемый параметр - id потока, который иногда может быть полезен (например, если потоку будет посылаться сообщение). Если id не нужен, можно передать NULL.

Более подробную информацию можно получить в MSDN.

Как используется в данной программе:

m_hThread= CreateThread(NULL, 0, WorkThread, NULL, 0, &dwID); //Создаём поток

Обратная связь:
230360822 
ved-vampir@yandex.ru

Посетите мой проект:Портал вникуда
Портал вникуда

Визитная карточка эксперта RFpro.ru

 
Hosted by uCoz