【问题标题】:Debugging shell extensions in Win 7 and 8.1在 Win 7 和 8.1 中调试 shell 扩展
【发布时间】:2014-08-05 14:45:08
【问题描述】:

我非常感谢您对此的帮助。我花了几个小时试图解决它。

我用 VCPP6 编写了一个小扩展(是的,我知道。无需告诉我),在 XP 下使用 IExtractImage 在资源管理器中将特定 DOS 文件的内容显示为缩略图。调试证明很容易——我关闭了资源管理器并按了 F5。单击所需类型的文件会生成缩略图。断点都处于活动状态。

升级到 VS2012(VS2013 Express 也是如此)并使用 IThumbnailProvider,相同的顺序不起作用。

程序本身有效。我可以在 7 和 8.1 中显示缩略图。我不能做的是通过资源管理器调试它。我可以使用 SDK (ThumbnailProvider) 中的示例进行调试,但不能使用 Explorer。

项目设置为:

Debugging->Command: C:\Windows\explorer.exe
Debugging->Command Arguments: /e,/select,F:\NewWork\NSD-24kW\pcb\15300003.pcb
Debugging->Working Directory: $(ProjectDir) (I've tried $(OutDir) too)
Debugging->Attach: No (I've tried 'yes' too)
Debugging->Debugger Type: Native Only
Debugging->Environment: (not set)
Debugging->Merge Environment: Yes

搜索我能想到的用于调试 shell 扩展的每一个变体,并尝试我能找到的指导的所有可能变体,但它仍然没有看到断点。

【问题讨论】:

  • 扩展现在可能由 dllhost.exe 而不是 explorer.exe 托管。您可以使用 systinternals 的 procexp.exe 工具查找:technet.microsoft.com/en-us/sysinternals/bb896653.aspx
  • 嗨,西蒙。感谢您的建议。使用 ProcessExplorer,当我单击文件时会弹出 dllhost.exe 然后消失。我已经尝试了所有明显的东西以及我可以通过谷歌搜索找到的所有想法,但仍然没有启用断点。哼哼。

标签: windows visual-c++ visual-studio-debugging shell-extensions


【解决方案1】:

该扩展现在很可能不是托管在 explorer.exe 中,而是托管在 dllhost.exe(一种 Windows 功能,可将可能有错误的扩展与关键的 Windows 进程隔离开来)。

您可以将其配置为使用 explorer.exe 在进程内托管以简化调试,如下所述:C++ Windows Shell thumbnail handler (CppShellExtThumbnailHandler)

由于几个原因,调试缩略图处理程序很困难。

1) Windows 资源管理器将缩略图提供程序托管在一个独立的 过程以获得稳健性并提高安全性。正因为如此 难以调试您的处理程序,因为您无法在您的 explorer.exe 进程中的代码,因为它没有在那里加载。这 独立进程是 DllHost.exe,它用于其他目的 所以很难找到这个过程的正确实例。

2) 一旦为特定文件计算了缩略图,它就会被缓存并 除非您为该项目再次调用您的处理程序 通过更新文件的修改日期使缓存失效。 请注意,即使文件被重命名或移动,此缓存仍然有效。

鉴于所有这些问题,在测试中调试代码的最简单方法 应用程序,然后一旦你证明它可以在那里测试它 探险家的语境。

另一件事是禁用进程隔离功能 探险家。您可以通过将以下命名值放在 处理程序的 CLSID

HKCR\CLSID{您的处理程序的CLSID}

   DisableProcessIsolation=REG_DWORD:1

请务必不要在运送您的处理程序时携带此产品,因为客户需要 隔离过程功能的安全性和稳健性优势。

【讨论】:

    【解决方案2】:

    您可以编写一个小程序,使用此 DLL 从文件创建缩略图。该程序可以在调试器下轻松运行。

    #define WIN32_LEAN_AND_MEAN
    #include <Windows.h>
    
    #include <ObjBase.h>
    #include <Shlwapi.h>
    #include <Thumbcache.h>
    #include <Unknwn.h>
    
    #include <stdio.h>
    
    #pragma comment(lib, "Shlwapi.lib")
    #pragma comment(lib, "Ole32.lib")
    
    // Our GUID here:
    LPCOLESTR myGuid = L"{9B083210-C856-48C0-8E8A-D9367301F046}";
    
    typedef HRESULT ourDllGetClassObjectT(REFCLSID rclsid, REFIID riid, void **ppv);
    
    
    int main(int c, char **v)
    {
        GUID clsid = {0};
        IIDFromString(myGuid, &clsid);
    
        if (c < 3) { printf("not enough arguments: dll image\n"); return 1; }
        HRESULT r;
        IStream* pStream = NULL;
        HMODULE dll = NULL;
    
        dll = LoadLibraryA(v[1]);
        if (!dll) { printf("can't open DLL\n"); return 1; }
    
        ourDllGetClassObjectT *ourDllGetClassObject = (ourDllGetClassObjectT*) GetProcAddress(dll, "DllGetClassObject");
    
        IClassFactory *pFactory = NULL;
        r = ourDllGetClassObject(clsid, IID_IClassFactory , (void**) &pFactory);
        if (r != S_OK) { printf("failed: get factory: %08x\n", r); return 2; }
    
        IInitializeWithStream *pInit;
        r = pFactory->CreateInstance(NULL, IID_IInitializeWithStream, (void**) &pInit);
        if (r != S_OK) { printf("failed: get object\n"); return 3; }
        pFactory->Release();
    
        IThumbnailProvider *pProvider;
        r = pInit->QueryInterface(IID_IThumbnailProvider, (void**) &pProvider);
        if (r != S_OK) { printf("failed: get provider\n"); return 5; }
    
        wchar_t wfile[256] = {0};
        MultiByteToWideChar(CP_ACP, 0, v[2], -1, wfile, 256);
        r = SHCreateStreamOnFileEx(wfile, STGM_READ, 0, FALSE, NULL, &pStream);
        if (r != S_OK || !pStream) { printf("can't open file\n"); return 10; }
    
        r = pInit->Initialize(pStream, 0);
        pInit->Release();
        pStream->Release();
        if (r != S_OK) { printf("failed: init provider\n"); return 11; }
    
        HBITMAP bmp;
        WTS_ALPHATYPE alpha;
        r = pProvider->GetThumbnail(256, &bmp, &alpha);
        pProvider->Release();
        if (r != S_OK) { printf("failed: make thumbnail\n"); return 12; }
    
        printf("done");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      • 2023-04-06
      • 2012-11-24
      • 2011-08-08
      相关资源
      最近更新 更多