基于Visua C++2010 与 Windows 7 SDK开发Window Search应用(1)-查询文件夹结构

Windows 7 新功能、新发现 - 超强的Windows Search
Windows 7 强化了Windows Search功能,方便使用者在电脑中检索所有的东西,只要按Windows Button在Search Program and File按入你想要的东西就可找尋到相關的Programs, Folder, Documents等在用戶的电脑中。

Windows Search,一个小型的繁忙的后台Windows服务,每个Window用户对它既爱又恨。 Windows Search占用你宝贵的CPU周期并翻来覆去地搜索你的硬盘,用户对它的态度也是爱恨交加,但是它很少得到应有的重视。

就有利方面而言,Windows Search使得查找隐藏文件、数据---以Vista为例---功能、设置等几乎非常容易。你只需要在任何Explorer窗口的搜索框中输入你要搜索的内容,那么你想要的目标几乎可以立刻就能出现。虽然这一功能在Windows XP操作系统中集成地不太好(例如,你不能组织搜索结果或搜索特定的Windows对象),而免费下载的Windows桌面搜索工具(Windows Desktop Search)提供了一个非常不错的集中接口,使得你可以在以数据为中心的数字世界里任意驰骋。

Windows Search for windows7,可以帮助用户轻松找到PC上的文件、Email消息或附件、日程、照片等等任何东西,甚至还可以快速找到其他PC共享文件,或邮件服务器上的内容。

Windows Search for windows7提高了搜索速度和可靠性,并能够同Windows操作系统无缝整合。其他新特性包括:

•支持索引在线邮件,即使没有将邮件下载到本地也可随时搜索其内容,减轻Exchange Server服务器负担。

•支持加密文件系统(EFS)搜索。

•支持远程搜索其他PC上的共享文件。

•支持组策略设置。

 

我们来亲自体验下基于VS2010与windows 7sdk开发Window Search应用,查询文件夹结构,

代码在windows7上用VS2010调试通过,

详情请见代码

 #include <stdio.h> #include <propsys.h> #include <propvarutil.h> #include <shlwapi.h> #include <structuredquery.h> #pragma comment(lib, "propsys.lib") #pragma comment(lib, "shlwapi.lib") // 一个条件操作返回一个结果。非任意结果。 #define MAP_ENTRY(x) {L#x, x} PCWSTR GetOperationLabel(CONDITION_OPERATION op) { PCWSTR pszLabel = NULL; static struct { PCWSTR pszLabel; CONDITION_OPERATION op; } const c_rgOperationLabels[] = { MAP_ENTRY(COP_IMPLICIT), MAP_ENTRY(COP_EQUAL), MAP_ENTRY(COP_NOTEQUAL), MAP_ENTRY(COP_LESSTHAN), MAP_ENTRY(COP_GREATERTHAN), MAP_ENTRY(COP_LESSTHANOREQUAL), MAP_ENTRY(COP_GREATERTHANOREQUAL), MAP_ENTRY(COP_VALUE_STARTSWITH), MAP_ENTRY(COP_VALUE_ENDSWITH), MAP_ENTRY(COP_VALUE_CONTAINS), MAP_ENTRY(COP_VALUE_NOTCONTAINS), MAP_ENTRY(COP_DOSWILDCARDS), MAP_ENTRY(COP_WORD_EQUAL), MAP_ENTRY(COP_WORD_STARTSWITH), MAP_ENTRY(COP_APPLICATION_SPECIFIC), }; for (ULONG i = 0 ; !pszLabel && i < ARRAYSIZE(c_rgOperationLabels) ; ++i) { if (c_rgOperationLabels[i].op == op) { pszLabel = c_rgOperationLabels[i].pszLabel; } } if (!pszLabel) { pszLabel = L"???"; } return pszLabel; } //显示在标准输出上一个条件与缩进树。 //代码只针对Windows 7和更高版本可以利用ICondition2和IObjectArray优势。 //代码为Windows早期版本的搜索也应该使用ICondition和IEnumUnknown。 //请注意,这两个函数显示,没有留下明确原因使用搜索条件有所不同 #if _WIN32_WINNT >= _WIN32_WINNT_WIN7 HRESULT DisplayQuery(ICondition2* pc, int cIndentation) { CONDITION_TYPE ct; HRESULT hr = pc->GetConditionType(&ct); if (SUCCEEDED(hr)) { switch (ct) { case CT_AND_CONDITION: case CT_OR_CONDITION: { wprintf(L"%*s%s/n", 2 * cIndentation, L"", (ct == CT_AND_CONDITION ? L"AND" : L"OR")); IObjectArray* poaSubs; hr = pc->GetSubConditions(IID_PPV_ARGS(&poaSubs)); if (SUCCEEDED(hr)) { UINT cSubs; hr = poaSubs->GetCount(&cSubs); for (UINT i = 0 ; SUCCEEDED(hr) && i < cSubs ; ++i) { ICondition2* pcSub; hr = poaSubs->GetAt(i, IID_PPV_ARGS(&pcSub)); if (SUCCEEDED(hr)) { DisplayQuery(pcSub, cIndentation + 1); pcSub->Release(); } } poaSubs->Release(); } } break; case CT_NOT_CONDITION: { wprintf(L"%*s%s/n", 2 * cIndentation, L"", L"NOT"); // ICondition::GetSubConditions返回一个检索的结果 ICondition2* pcSub; hr = pc->GetSubConditions(IID_PPV_ARGS(&pcSub)); if (SUCCEEDED(hr)) { DisplayQuery(pcSub, cIndentation + 1); pcSub->Release(); } } break; case CT_LEAF_CONDITION: { PROPERTYKEY propkey; CONDITION_OPERATION op; PROPVARIANT propvar; hr = pc->GetLeafConditionInfo(&propkey, &op, &propvar); if (SUCCEEDED(hr)) { IPropertyDescription* ppd; hr = PSGetPropertyDescription(propkey, IID_PPV_ARGS(&ppd)); if (SUCCEEDED(hr)) { PWSTR pszPropertyName; hr = ppd->GetCanonicalName(&pszPropertyName); if (SUCCEEDED(hr)) { PROPVARIANT propvarString; hr = PropVariantChangeType(&propvarString, propvar, PVCHF_ALPHABOOL, VT_LPWSTR); // 实际应用中应选择PSFormatForDisplay,但我们希望有更多的“原始”的数据。 if (SUCCEEDED(hr)) { PWSTR pszSemanticType; hr = pc->GetValueType(&pszSemanticType); if (SUCCEEDED(hr)) { //语义类型可以是NULL;若有,不显示它。 if (!pszSemanticType) { hr = SHStrDup(L"", &pszSemanticType); } if (SUCCEEDED(hr)) { wprintf(L"%*sLEAF %s %s %s %s/n", 2 * cIndentation, L"", pszPropertyName, GetOperationLabel(op), propvarString.pwszVal, pszSemanticType); } CoTaskMemFree(pszSemanticType); } PropVariantClear(&propvarString); } CoTaskMemFree(pszPropertyName); } ppd->Release(); } PropVariantClear(&propvar); } } break; } } return hr; } #else // _WIN32_WINNT >= _WIN32_WINNT_WIN7 HRESULT DisplayQuery(ICondition* pc, int cIndentation) { CONDITION_TYPE ct; HRESULT hr = pc->GetConditionType(&ct); if (SUCCEEDED(hr)) { switch (ct) { case CT_AND_CONDITION: case CT_OR_CONDITION: { wprintf(L"%*s%s/n", 2 * cIndentation, L"", (ct == CT_AND_CONDITION ? L"AND" : L"OR")); IEnumUnknown* peuSubs; hr = pc->GetSubConditions(IID_PPV_ARGS(&peuSubs)); if (SUCCEEDED(hr)) { IUnknown* punk; while ((hr = peuSubs->Next(1, &punk, NULL)) == S_OK) { ICondition* pcSub; hr = punk->QueryInterface(IID_PPV_ARGS(&pcSub)); if (SUCCEEDED(hr)) { DisplayQuery(pcSub, cIndentation + 1); pcSub->Release(); } punk->Release(); } peuSubs->Release(); } } break; case CT_NOT_CONDITION: { wprintf(L"%*s%s/n", 2 * cIndentation, L"", L"NOT"); // ICondition::GetSubConditions 返回一个检索的结果 ICondition* pcSub; hr = pc->GetSubConditions(IID_PPV_ARGS(&pcSub)); if (SUCCEEDED(hr)) { DisplayQuery(pcSub, cIndentation + 1); pcSub->Release(); } } break; case CT_LEAF_CONDITION: { PWSTR pszPropertyName; CONDITION_OPERATION op; PROPVARIANT propvar; hr = pc->GetComparisonInfo(&pszPropertyName, &op, &propvar); if (SUCCEEDED(hr)) { // The property name may be NULL or "*"; if NULL, display it as such. if (!pszPropertyName) { hr = SHStrDup(L"(NULL)", &pszPropertyName); } PROPVARIANT propvarString; hr = PropVariantChangeType(&propvarString, propvar, PVCHF_ALPHABOOL, VT_LPWSTR); // 实际应用中应选择PSFormatForDisplay,但我们希望有更多的“原始”的数据。 if (SUCCEEDED(hr)) { PWSTR pszSemanticType; hr = pc->GetValueType(&pszSemanticType); if (SUCCEEDED(hr)) { // 语义类型可以是NULL;若有,不显示它。 if (!pszSemanticType) { hr = SHStrDup(L"", &pszSemanticType); } if (SUCCEEDED(hr)) { wprintf(L"%*sLEAF %s %s %s %s/n", 2 * cIndentation, L"", pszPropertyName, GetOperationLabel(op), propvarString.pwszVal, pszSemanticType); } CoTaskMemFree(pszSemanticType); } PropVariantClear(&propvarString); } CoTaskMemFree(pszPropertyName); PropVariantClear(&propvar); } } break; } } return hr; } #endif // _WIN32_WINNT >= _WIN32_WINNT_WIN7 int wmain(int /* argc */, wchar_t* /* argv */ []) { wprintf(L"文件夹机构查询范例/n"); wprintf(L"请输入一个在高级查询语法(AQS),或一个空行查询退出/n"); wprintf(L"该程序。该项目将解析查询,解决由此产生的条件n"); wprintf(L"尝试树的形式显示它:/n"); wprintf(L"from:bill modified:last week subject:(cats OR dogs)/n"); wprintf(L"name:(bubble NOT bath) author:~~george taken:<October 2007/n"); wprintf(L"kind:=folder has:attachment rating:****/n"); wprintf(L"flower readstatus:read size:42KB/n"); wprintf(L"System.IsShared:=FALSE exposuretime:>=0.125 received:5/25/2006 .. 7/17/2007/n"); wprintf(L"请注意,这些问题是英语语言的界面。如果您的界面语言/n"); wprintf(L"不同的,你可以使用该语言的关键字。需要注意的是/n"); wprintf(L"System.IsShared:=否则是一个查询的例子/"canonical syntax/", which/n"); wprintf(L"适用于任何用户界面语言,应在使用旧AQS./n"); wprintf(L"MSDN on AQS: http://msdn.microsoft.com/en-us/library/aa965711(VS.85).aspx)/n"); wprintf(L"还要注意,在任何时间条件下的树结构在星期六,而不是本地时间./n"); HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (SUCCEEDED(hr)) { //这是可能的CoCreateInstance的查询分析器直接使用__uuidof(QueryParser的),但由于使用QueryParserManager,我们可以从查询分析器某用户界面语言和目录编制。 IQueryParserManager* pqpm; hr = CoCreateInstance(__uuidof(QueryParserManager), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pqpm)); if (SUCCEEDED(hr)) { //给IQueryParserManager的语言::CreateLoadedParser应该是用户界面语言应用程序,它通常是作为操作系统的默认界面此用户的语言相同。它用于决定什么语言时使用的解释的关键字 IQueryParser* pqp; hr = pqpm->CreateLoadedParser(L"SystemIndex", GetUserDefaultUILanguage(), IID_PPV_ARGS(&pqp)); if (SUCCEEDED(hr)) { //此示例关闭“自然查询语法”,这是更为宽松和人类的语言一样搜索符号,也使自动搜索的词用了什么的开始位置指定的(这样的投入“的:法案”将搜索来自任何人的名字开头“规则”。 hr = pqpm->InitializeOptions(FALSE, TRUE, pqp); WCHAR szLine[1024]; while (SUCCEEDED(hr) && fgetws(szLine, ARRAYSIZE(szLine), stdin)[0] != L'/n') { //在解析查询字符串的实际工作都是在这里完成 IQuerySolution* pqs; hr = pqp->Parse(szLine, NULL, &pqs); if (SUCCEEDED(hr)) { //在这个示例,我们也懒得各方的解析错误,但我们可以区分。请注意,将有一个解决办法,即使有解析错误,它只是可能不用户意图 IEnumUnknown* peu; hr = pqs->GetErrors(IID_PPV_ARGS(&peu)); if (SUCCEEDED(hr)) { if (peu->Skip(1) == S_OK) { wprintf(L"Some part of the query string could not be parsed./n"); } ICondition* pc; hr = pqs->GetQuery(&pc, NULL); if (SUCCEEDED(hr)) { //IQueryCondition::Resolve and IConditionFactory2::ResolveCondition 转任何日期/时间引用(相对,如“今天”,绝对的,如“2009年5月7日”)为绝对日期/时间引用(在星期二的时区),并简化了各种方式的结果。 //请注意,电脑是不变的,可以解决对其他日期/时间。代码只针对Windows 7和更高版本可以利用IConditionFactory2::ResolveCondition优势。代码为目标的Windows和Windows早期版本的搜索也应使用IQueryCondition::Resolve。 SYSTEMTIME st; GetLocalTime(&st); #if (_WIN32_WINNT >= _WIN32_WINNT_WIN7) IConditionFactory2* pcf; hr = pqs->QueryInterface(IID_PPV_ARGS(&pcf)); if (SUCCEEDED(hr)) { ICondition2* pcResolved; hr = pcf->ResolveCondition(pc, SQRO_DEFAULT, &st, IID_PPV_ARGS(&pcResolved)); if (SUCCEEDED(hr)) { hr = DisplayQuery(pcResolved, 0); pcResolved->Release(); } pcf->Release(); } #else // _WIN32_WINNT >= _WIN32_WINNT_WIN7 ICondition* pcResolved; //由于IConditionFactory::Resolve ,我们必须使用SQRO_DONT_SPLIT_WORDS表现得像IConditionFactory2::ResolveCondition,我们希望保持自然短语间断。 hr = pqs->Resolve(pc, SQRO_DONT_SPLIT_WORDS, &st, &pcResolved); if (SUCCEEDED(hr)) { hr = DisplayQuery(pcResolved, 0); pcResolved->Release(); } #endif // _WIN32_WINNT >= _WIN32_WINNT_WIN7 pc->Release(); } peu->Release(); } pqs->Release(); } } pqp->Release(); } pqpm->Release(); } CoUninitialize(); } return SUCCEEDED(hr) ? EXIT_SUCCESS : EXIT_FAILURE; }

欢迎技术交流!

 

本文作者专著《Visual C++2010开发权威指南》即将推出,敬请关注,Visual C++2010最近技术,Windows7开发最新技术!

你可能感兴趣的:(C++,windows,null,search,语言,2010)