如何查找文件的IFilter
IFilter接口定义了Windows平台扫描文件文本的操作,不同的IFilter实现存储在注册表中。通过以下三个步骤获取:
1、注册表HKEY_LOCAL_MACHINE\SOFTWARE\Classes\{文件扩展名}\PersistentHandler\下存储了文件扩展名持久化处理器,获取它的ClassName。以.docx为例:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.docx\PersistentHandler
默认值为{D3B41FA1-01E3-49AF-AA25-1D0D824275AE}
2、没有PersistentHandler项的情况下需要查找文档类型。注册表HKEY_LOCAL_MACHINE\SOFTWARE\Classes\{文件扩展名}\下的默认值存储了文档类型。在找到文档类型的情况下根据HKEY_LOCAL_MACHINE\SOFTWARE\Classes\{文档类型}\CLSID\存储的ClassName前往HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{ClassName}\PersistentHandler\获取ClassName。
3、查找文档类型失败的情况下访问HKEY_LOCAL_MACHINE\SOFTWARE\Classes\{文件扩展名}\的Content Type值,在Windows平台MIME会存储对应Content Type的Extension。访问HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MIME\Database\Content Type\{Content Type}\的Extension值并重复第一、第二步。以.sln为例:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.sln\PersistentHandler\项不存在
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.sln\的默认值为VisualStudio.Launcher.sln
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID的值为{68681A5C-C22A-421d-B68B-5BA9D01F35C5}
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{68681A5C-C22A-421d-B68B-5BA9D01F35C5}\PersistentHandler项不存在
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.sln\的Content Type值为text/plain
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MIME\Database\Content Type\text/plain\的Extension值为.txt
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\.txt\PersistentHandler\的默认值为{5e941d80-bf96-11cd-b579-08002b30bfeb}
4、找到PersistentHandler的ClassName后前往HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{PersistentHandler ClassName}\PersistentAddinsRegistered\{89BCB740-6119-101A-BCB7-00DD010655AF}\获取默认值,这个值得存放了持久化的ClassName。以.txt为例:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{5e941d80-bf96-11cd-b579-08002b30bfeb}\PersistentAddinsRegistered\{89BCB740-6119-101A-BCB7-00DD010655AF}\默认值为{c1243ca0-bf96-11cd-b579-08002b30bfeb}。
5、根据这个持久化ClassName获取HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{PersistentHandler ClassName}\InprocServer32\的默认值,它存放了对应的dll路径。
以.txt为例:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{c1243ca0-bf96-11cd-b579-08002b30bfeb}\InprocServer32\默认值为%systemroot%\system32\query.dll。
6、根据对应的dll路径,可以通过LoadLibrary函数加载该模块。使用GetProcAddress获取DllGetClassObject函数指针,调用DllGetClassObject获取IClassFactory接口,由它的CreateInstance函数创建IFilter接口实例,简单示例如下:
1 #include “stdafx.h” 2 #include <windows.h> 3 #include <unknwn.h> 4 #include <atlbase.h> 5 #include <atlcom.h> 6 #include <filter.h> 7 8 using namespace ATL; 9 10 TCHAR szFileName[] = _T(“C:\\Windows\\System32\\query.dll”); 11 TCHAR szClsid[] = _T(“{c1243ca0-bf96-11cd-b579-08002b30bfeb}”); 12 13 HMODULE hModule = LoadLibrary(szFileName); 14 15 typedef HRESULT (*DllGetClassObjectFunc)(__in REFCLSID rclsid, __in REFIID riid, __deref_out LPVOID FAR* ppv); 16 17 DllGetClassObjectFunc dllGetClassObjectPtr = reinterpret_cast(GetProcAddress(hModule, “DllGetClassObject”)); 18 19 CComPtr<IClassFactory> pClassFactory; 20 21 if (dllGetClassObjectPtr) { 22 HRESULT hr = S_OK; 23 IID clsid; 24 25 hr = CLSIDFromString(szClsid, &clsid); 26 hr = dllGetClassObjectPtr(clsid, IID_IClassFactory, (void**)(&pClassFactory)); 27 28 CComPtr<IFilter> pFilter; 29 30 hr = pClassFactory->CreateInstance(NULL, IID_IFilter, (void**)(&pFilter)); 31 32 }