使用完成例程监控文件目录的例子

由于项目需要实现了一个文件监控服务,期间研究过使用完成例程的方式来监控文件目录。

下面简单的BCB6命令行实现版本。(参考来源 http://bbs.csdn.net/topics/340172813 )

下次补充一个完成端口的版本。

  1 //---------------------------------------------------------------------------
  2 // 使用完成例程监控当前文件夹
  3 //------------------------------------------------------------------------------
  4
  5
  6
  7
  8 #include <vcl.h>
  9 #pragma hdrstop
 10 #include <iostream>
 11 using namespace std;
 12
 13
 14 //---------------------------------------------------------------------------
 15
 16 #pragma argsused
 17
 18
 19 HANDLE hThreadHandle = NULL ;
 20 HANDLE hMonitorDirHandle = NULL;
 21 HANDLE hMonitorEventHandle = NULL;
 22
 23 //这个回调函数,是完成例程的核心
 24 //在IO 完成的时候会触发。
 25 //然后这个回调函数去设置overlapped->hEvent信号量
 26 //使线程能不被阻塞。
 27 void CALLBACK FileIOCompletionRoutine(  DWORD dwErrorCode,
 28                                         DWORD dwNumberOfBytesTransfered,
 29                                         LPOVERLAPPED lpOverlapped)
 30 {
 31     if(dwErrorCode)
 32     {
 33         printf("Error Code:%d\r\n",dwErrorCode);
 34     }
 35     //设置信号量,多线程会得到通知
 36     SetEvent(lpOverlapped->hEvent);
 37 }
 38
 39 DWORD WINAPI MonitorThread( LPVOID )
 40 {
 41     OVERLAPPED overlapped={0};
 42     DWORD ByteReturn = 0;
 43     DWORD BufferLen=10*(sizeof(FILE_NOTIFY_INFORMATION)+MAX_PATH*sizeof(TCHAR));
 44     FILE_NOTIFY_INFORMATION* Buffer=
 45         (FILE_NOTIFY_INFORMATION*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,BufferLen);
 46
 47     while(true)
 48     {
 49         //简单起见只监控了 修改文件和文件目录
 50         if(ReadDirectoryChangesW(hMonitorDirHandle,Buffer,BufferLen,TRUE,
 51             FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME,
 52             &ByteReturn,&overlapped,FileIOCompletionRoutine))
 53         {
 54             DWORD dwResult;
 55             //这个信号一开始没信号的,直到完成例程回调被调用(FileIOCompletionRoutine)
 56             dwResult=WaitForSingleObjectEx(hMonitorEventHandle,INFINITE,TRUE);
 57             if(dwResult==WAIT_IO_COMPLETION    )
 58             {
 59                 FILE_NOTIFY_INFORMATION* notify = Buffer;
 60
 61                 AnsiString fileName =
 62                         WideCharLenToString(
 63                             notify->FileName,notify->FileNameLength/2);
 64                 do
 65                 {
 66                     bool blNormal = true;
 67                     switch(notify->Action)
 68                     {
 69                     case FILE_ACTION_ADDED:
 70                         {
 71                             cout<<"增加了文件"<<fileName.c_str()<<endl;
 72                         }
 73                         break;
 74                     case FILE_ACTION_REMOVED:
 75                         {
 76                             cout<<"删除了文件"<<fileName.c_str()<<endl;
 77                         }
 78                         break;
 79                     case FILE_ACTION_MODIFIED:
 80                         {
 81                             cout<<"修改了文件"<<fileName.c_str()<<endl;
 82                         }
 83                         break;
 84                     case FILE_ACTION_RENAMED_OLD_NAME:
 85                         {
 86                             cout<<"被重名的文件"<<fileName.c_str()<<endl;
 87                         }
 88                         break;
 89                     case FILE_ACTION_RENAMED_NEW_NAME:
 90                         {
 91                             cout<<"新命名的文件"<<fileName.c_str()<<endl;
 92                         }
 93                         break;
 94                     default:   //有可能已经溢出了!
 95                         blNormal = false;
 96                         break;
 97                     }
 98
 99                     if(!blNormal)
100                     {
101                         break;
102                     }
103                     //将指针偏移offset个字节
104                     notify =  notify + notify->NextEntryOffset;
105                 }
106                 while(notify->NextEntryOffset>0);
107            }
108            //重新设置信号量,继续阻塞
109            ResetEvent(hMonitorEventHandle);
110         }
111         else
112         {
113             cout<<"缓冲溢出!"<<SysErrorMessage(GetLastError()).c_str()<<endl;
114             break;
115         }
116     }
117     HeapFree(GetProcessHeap(),0,Buffer);
118     return 0;
119 }
120
121 int main(int argc, char* argv[])
122 {
123     AnsiString mointorDir = ExtractFileDir(Application->ExeName);
124
125     hMonitorDirHandle=CreateFile(mointorDir.c_str(),
126         FILE_LIST_DIRECTORY,                            //见MSDN ReadDirectoryChangesW 函数说明
127         FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
128         NULL,
129         OPEN_EXISTING,
130         FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED,//FILE_FLAG_OVERLAPPED表示异步模式,当异步的IO 完成的时,会填充OVERLAPPED结构
131         NULL);
132
133     if(hMonitorDirHandle == INVALID_HANDLE_VALUE)
134     {
135         cout<<"打开监控文件夹失败!"<< SysErrorMessage(GetLastError()).c_str() <<endl;
136         CloseHandle(hMonitorDirHandle);
137         return 0;
138     }
139
140     hMonitorEventHandle = CreateEvent(NULL,TRUE,FALSE,NULL);
141
142     DWORD threadId = 0;
143     hThreadHandle = CreateThread(NULL,0,MonitorThread,NULL,0,&threadId);
144
145
146     cout<<"开始监控本程序所在的文件夹..."<<endl;
147     int i=0;
148     cin>>i;
149
150     CloseHandle(hThreadHandle);
151     CloseHandle(hMonitorDirHandle);
152     CloseHandle(hMonitorEventHandle);
153     return 0;
154 }
155 //---------------------------------------------------------------------------
时间: 2024-10-10 18:18:42

使用完成例程监控文件目录的例子的相关文章

使用完成端口监控文件目录的例子

和完成例程比较.完成端口的效率更高.其主要原因是完成端口可以指定线程池. 下面是BCB实现效果及源码(参考资料 windows 核心编程 第10章,11章) //--------------------------------------------------------------------------- #include <vcl.h> #include <iostream> using namespace std; #pragma hdrstop //----------

python 监控文件目录变化

使用os.listdir()监控文件目录: #!/usr/bin/env python #-*- coding=utf-8 -*- #filename: monitor_dir.py import os import time monitor_dir = "/opt/" now_file = dict([(f,None)for  f in os.listdir(monitor_dir)]) while True:     new_file = dict([(f,None)for  f 

通过collectd工具获取虚拟机的nagios监控脚本简单例子

在宿主机上安装collectd工具后,可以通过collectd工具来获取宿主机上的虚拟机的cpu,memery,if-traffic等数据.可以通过nagios监控脚本来实现对这些数据监控. 以下是一个简单的监控虚拟机内存脚本: #!/bin/bash #Desc:to check memory about vm instance STATE_OK=0 STATE_WARNING=1 STATE_CRITICAL=2 STATE_UNKNOWN=3 COLLECTD_HOME=/usr/loca

获取监控信息,产生监控响应动作

w 0-生产环境下,为了脚本持续执行的效率:用原生函数.写硬代码. 该自重复执行脚本的执行环境: 00-Windows 下 shell  或浏览器 01-Linux 下 1-php监控文件目录变动信息 <?php include('conn.php'); include('w_fun.php'); include('w_fun_this_project.php'); $sql = 'SELECT MAX(wid) AS wi FROM w '; $wi = db_single_row_singl

数百个 HTML5 例子学习 HT 图形组件 – WebGL 3D 篇

<数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇>一文让读者了解了 HT的 2D 拓扑图组件使用,本文将对 HT 的 3D 功能做个综合性的介绍,以便初学者可快速上手使用 HT 构建例如电信网管 3D 机房应用.水务燃气 SCADA 监控应用及智能楼宇等应用场景. HT for Web 的 3D 是完全基于 WebGL 技术实现的渲染引擎,但开发者几乎不需要了解 3D 图形数学或 Shader 渲染的底层技术,只需要掌握基本的 3D 坐标系和相机  Camera 的概念,剩下需要掌

大数据系统之监控系统(二)Flume的扩展

一些需求是原生Flume无法满足的,因此,基于开源的Flume我们增加了许多功能. EventDeserializer的缺陷 Flume的每一个source对应的deserializer必须实现接口EventDeserializer,该接口定义了readEvent/readEvents方法从各种日志源读取Event. flume主要支持两种反序列化器: (1)AvroEventDeserializer:解析Avro容器文件的反序列化器.对Avro文件的每条记录生成一个flume Event,并将

【SQL Performance】实时SQL监控功能(Real-Time SQL Monitoring)

概述 使用条件 监视对象 查看实时SQL监控结果的方法 DBMS_SQLTUNE包的以下子程序包 动态视图 Enterprise ManagerEM 相关参数 各版本变化 实时SQL监控使用的例子 参考 概述 实时SQL监控功能(Real-Time SQL Monitoring)是Oracle11g推出的功能,通过这个功能可以实时地监视执行中的SQL性能. 使用条件 要想使用实时SQL监控功能(Real-Time SQL Monitoring),必须满足以下几个条件 ?EE版本,购买了Diagn

linux下监控jvm 使用的方法

之前一直用jconsole监控jvm,图形界面简单易用,最近因为需要在纯linux下进行操作,所以总结了一下 linux下监控jvm的例子,这次主要用到了jstat工具, 各个参数意义: jstat -class pid:显示加载class的数量,及所占空间等信息. jstat -compiler pid:显示VM实时编译的数量等信息. jstat -gc pid:可以显示gc的信息,查看gc的次数,及时间.其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数

通过本地Agent监控Azure sql database

背景: 虽然Azure sql database有DMVs可以查看DTU等使用情况,但记录有时间限制,不会一直保留.为了更好监控Azure_sql_database上各个库的DTU使用情况.数据库磁盘使用情况.阻塞等情况.通过本地的Agent的job使用link server 链接到各个Azure sql database 对应库(本地Ip能直连azure sql database),把相关的信息读取出来,存储在本地已新建好的对应表中,通过分析本地对应表中记录来实现监控azure sql dat