我想Windows中的钩子来实现功能:随时监控文件夹下是否有文件,有就上传至数据库。请大家给个思路,谢谢!

我有个固定的文件夹E:a\下面有很多文件夹,我要实现的是随时监控这些文件夹下面是否有文件,有就上传至数据库,再delete它,老大说Windowsapi中有个钩子函数就可... 我有个固定的文件夹E:a\ 下面有很多文件夹,我要实现的是随时监控这些文件夹下面是否有文件,有就上传至数据库,再delete它,老大说Windows api中有个钩子函数就可以随时监控!请各位给个思路吧,谢谢! 展开
 我来答
耿直又低调灬福星373
2011-03-17 · TA获得超过1059个赞
知道小有建树答主
回答量:886
采纳率:0%
帮助的人:1065万
展开全部
COM接口,它决定一个文件夹或者打印机对象是否可以被移动,拷贝,重命名或删除。Shell在执行这些操作之前,会调用ICopyHook接口的CopyCallback方法对它们进行验证。CopyCallback返回一个int值指示Shell是否应该继续执行这个操作。返回值IDYES表示继续,而返回值IDNO和IDCANCEL则表示终止。最好的网上开店系统:凡人网络购物系统V8.0 网上开店助手 不懂技术怎么建网上商城 网上开店两步搞定

一个文件夹对象可以安装多个拷贝钩子处理程序。如果出现这种情况,Shell会依次调用每个处理程序。只有当每个处理程序都返回IDYES时,Shell才真正执行用户请求的操作。

拷贝钩子处理程序的作用是在上述四种操作执行前对它们进行验证,但是Shell并不会把操作的结果通知给拷贝钩子处理程序。而windows提供的API函数FindFirstChangeNotification和FindNextChangeNotification却可以实现这个功能。因此,只有把这种两种方法结合起来,才能对一个文件夹的状态进行完全的监控。

拷贝钩子处理程序实现并不困难,首先创建一个作为进程内组件的COM对象,它只需要暴露一个ICopyHook接口(当然还有IUnknown)。然后用regsrv32.exe注册这个COM组件。最后一步是向Shell注册你的这个拷贝钩子处理程序,方法是在注册表HKEY_CLASSES_ROOT\Directory\Shellex\CopyHookHandlers下创建一个名称任意的sub key,在此sub key中创建一个类型为REG_SZ的项并将你的COM对象的CLSID作为它的默认值就可以了。

下面就是一个拷贝钩子的实现程序

// CCopyHook.h

//CCopyHook类实现了ICopyHook接口,CClassFactory实现了IClassFactory接口

#include <shlobj.h>

class CCopyHook: public ICopyHook

{

public:

CCopyHook():m_refcnt(0)

STDMETHODIMP QueryInterface(REFIID iid,void** ppvObject);

STDMETHODIMP_(ULONG) AddRef();

STDMETHODIMP_(ULONG) Release();

STDMETHODIMP_(UINT) CopyCallback(HWND hwnd,UINT wFunc,UINT wFlags,

LPCTSTR pszSrcFile,DWORD dwSrcAttribs,

LPCTSTR pszDestFile,DWORD dwDestAttribs);

private:

int m_refcnt;

};

class CClassFactory:public IClassFactory

{

public:

CClassFactory():m_refcnt(0)

STDMETHODIMP QueryInterface(REFIID iid,void** ppvObject);

STDMETHODIMP_(ULONG) AddRef();

STDMETHODIMP_(ULONG) Release();

STDMETHODIMP CreateInstance(IUnknown * pUnkOuter,REFIID riid,void ** ppvObject);

STDMETHODIMP LockServer(BOOL fLock);

private:

int m_refcnt;

};

// CCopyHook.cpp

//CCopyHook对象和CClassFactory对象的实现文件

#include <stdio.h>

#include "CCopyHook.h"

extern LONG nLocks; //对象计数,用于DllCanUnloadNow

ULONG __stdcall CCopyHook::AddRef(){

if(m_refcnt==0)

nLocks++;

m_refcnt++;

return m_refcnt;

}

ULONG __stdcall CCopyHook::Release(){

int nNewCnt=--m_refcnt;

if(nNewCnt<=0){

nLocks--;

delete this;

}

return nNewCnt;

}

HRESULT __stdcall CCopyHook::QueryInterface(REFIID iid,void** ppvObject){

if(iid==IID_IUnknown)

*ppvObject=static_cast<IUnknown*>(this);

else

if(iid==IID_IShellCopyHook)

*ppvObject=static_cast<ICopyHook*>(this);

else

return E_NOINTERFACE;

reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();

return S_OK;

}

//这就是CopyCallback方法,拷贝钩子的所有功能由它实现。参数的具体值参看MSDN

UINT __stdcall CCopyHook::CopyCallback(HWND hwnd,UINT wFunc,UINT wFlags,

LPCTSTR pszSrcFile,DWORD dwSrcAttribs,

LPCTSTR pszDestFile,DWORD dwDestAttribs){

char szMessage[MAX_PATH+14];

sprintf(szMessage,"对%s进行的操作,是否继续?",pszSrcFile);

return MessageBox(NULL,szMessage,"确认",MB_YESNO|MB_ICONEXCLAMATION);

}

ULONG __stdcall CClassFactory::AddRef(){

if(m_refcnt==0)

nLocks++;

m_refcnt++;

return m_refcnt;

}

ULONG __stdcall CClassFactory::Release(){

int nNewCnt=--m_refcnt;

if(nNewCnt<=0){

nLocks--;

delete this;

}

return nNewCnt;

}

HRESULT __stdcall CClassFactory::QueryInterface(REFIID iid,void** ppvObject){

if(iid==IID_IUnknown)

*ppvObject=static_cast<IUnknown*>(this);

else

if(iid==IID_IClassFactory)

*ppvObject=static_cast<IClassFactory*>(this);

else

return E_NOINTERFACE;

reinterpret_cast<IUnknown*>(*ppvObject)->AddRef();

return S_OK;

}

HRESULT __stdcall CClassFactory::CreateInstance(IUnknown* pUnkownOuter,REFIID riid,void** ppvObj){

if(pUnkownOuter!=NULL)

return CLASS_E_NOAGGREGATION;

CCopyHook* pObj=new CCopyHook;

pObj->AddRef();

HRESULT hr=pObj->QueryInterface(riid,ppvObj);

pObj->Release();

return hr;

}

HRESULT __stdcall CClassFactory::LockServer(BOOL fLock){

if(fLock)

nLocks++;

else

nLocks--;

return S_OK;

}

// main.cpp

//主要实现了几个COM对象标准的导出函数。

#include <objbase.h>

#include <olectl.h>

#include "CCopyHook.h"

//这是要添加到注册表中的项,注意如果你要使用这段代码,应该用UUIDGEN.exe生成一

//个新的CLSID。

const char* szRegTable[][3]={

",0,"CopyHook"},

\\InProcServer32",0,(const char*)-1},

\\InProcServer32","ThreadingModel","Apartment"},

\\ProgID",0,"webber84.CopyHook.1"},

,

"}};

HMODULE hInstance=NULL;

LONG nLocks=0;

BOOL APIENTRY DllMain( HANDLE hModule,

DWORD ul_reason_for_call,

LPVOID lpReserved

){

if(ul_reason_for_call==DLL_PROCESS_ATTACH)

hInstance=(HMODULE)hModule;

return TRUE;

}

STDAPI DllUnregisterServer(){

HRESULT hr=S_OK; LONG ret=0;

int items=sizeof(szRegTable)/sizeof(szRegTable[0]);

for(int i=items-1;i>=0;i--){

const char* szKeyName=szRegTable[i][0];

if( (i==items-1) || stricmp(szRegTable[i+1][0],szKeyName)!=0)

ret=RegDeleteKey(HKEY_CLASSES_ROOT,szKeyName);

if(ret!=ERROR_SUCCESS)

hr=SELFREG_E_CLASS;

}

return hr;

}

//可重用的DllRegisterServer函数,只要照上面的格式把注册表项放到一个数组中,就可以//用这段代码完成对任意组件的注册。

STDAPI DllRegisterServer(void){

HRESULT hr=S_OK;

int items=sizeof(szRegTable)/sizeof(szRegTable[0]);

char szDllPath[MAX_PATH];

GetModuleFileName(hInstance,szDllPath,MAX_PATH);

for(int i=0;i<items && SUCCEEDED(hr);i++){

const char* szKeyName=szRegTable[i][0];

const char* szValueName=szRegTable[i][1];

const char* szValue=szRegTable[i][2];

if(szValue==(const char*)-1)

szValue=szDllPath;

HKEY hKey;

LONG ret=RegCreateKey(HKEY_CLASSES_ROOT,szKeyName,&hKey);

if(ret==ERROR_SUCCESS){

RegSetValueEx(hKey,szValueName,0,REG_SZ,(const BYTE*)szValue,

strlen(szValue)+1);

RegCloseKey(hKey);

}

if(ret!=ERROR_SUCCESS){

hr=SELFREG_E_CLASS;

DllUnregisterServer();

}

}

return hr;

}

STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, void** ppvObj) {

HRESULT hr = E_OUTOFMEMORY;

*ppvObj = NULL;

CClassFactory *pClassFactory = new CClassFactory;

if (pClassFactory != NULL)

hr = pClassFactory->QueryInterface(riid, ppvObj);

return hr;

}

STDAPI DllCanUnloadNow(){

return nLocks==0 ? S_OK : S_FALSE;

}
追问
谢谢,但是请问有C#代码吗?我看不懂你这个代码!呜呜~~
thinsC
2011-03-16 · TA获得超过246个赞
知道小有建树答主
回答量:395
采纳率:0%
帮助的人:307万
展开全部
设个定时器,定时扫描该目录,
hook函数不靠谱
更多追问追答
追问
我之前用的是定时器,通过依次循环文件夹来查找是否有文件。主要是有个问题:如果排在前面的文件夹不停的有新的文件出现,那么这样子的话,就紧都循环不到后面的文件夹下面的文件,这样的话,后面的文件就不能及时上传至数据库,
老大就提了这么个思路:利用Windows的钩子函数来监控,随时监控每个文件夹,文件夹中一旦有文件,就立马读取该文件,并同时锁定该文件(以免重复读取),等读取完了,再解锁文件。
追答
你轮询时,一个目录处理一个后马上转下一个目录,也就是多队列轮询的思想
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式