问题
I would genuinely appreciate help with this. I have spent hours trying to solve it.
I wrote a small extension with VCPP6 (yes, I know. no need to tell me) to display the content of a particular DOS file as a thumbnail in Explorer using IExtractImage under XP. Debugging proved easy - I shut down explorer and hit F5. Clicking a file of the desired type resulted in a thumbnail. Breakpoints all active.
Upgrading to VS2012 (same happens with VS2013 Express) and using IThumbnailProvider, the same sequence doesn't work.
The program itself works. I can display the thumbnails in both 7 and 8.1. What I can't do is debug it via Explorer. I can debug it using a sample from the SDK (ThumbnailProvider) but not Explorer.
Project settings are:
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
Searching for every variant I can dream up for debugging shell extensions and trying every possible variation on the guidance I can find, but it still does not see the breakpoints.
回答1:
The extension is now probaby not hosted in explorer.exe, but in dllhost.exe (a Windows feature that isolates possibly buggy extensions from a critical Windows process).
You can configure it to be hosted inprocess with explorer.exe to ease debugging, as documented here: C++ Windows Shell thumbnail handler (CppShellExtThumbnailHandler)
Debugging thumbnail handlers is difficult for several reasons.
1) The Windows Explorer hosts thumbnail providers in an isolated process to get robustness and improve security. Because of this it is difficult to debug your handler as you cannot set breakpoints on your code in the explorer.exe process as it is not loaded there. The isolated process is DllHost.exe and this is used for other purposes so finding the right instance of this process is difficult.
2) Once a thumbnail is computed for a particular file it is cached and your handler won't be called again for that item unless you invalidate the cache by updating the modification date of the file. Note that this cache works even if the files are renamed or moved.
Given all of these issues the easiest way to debug your code in a test application then once you have proven it works there test it in the context of the explorer.
Another thing to do is to disable the process isolation feature of explorer. You can do this by putting the following named value on the CLSID of your handler
HKCR\CLSID{CLSID of Your Handler}
DisableProcessIsolation=REG_DWORD:1
Be sure to not ship your handler with this on as customers require the security and robustness benefits of the isolated process feature.
回答2:
You can write a small program to create a thumbnail from a file with this DLL. This program can easily be run under the debugger.
#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");
}
来源:https://stackoverflow.com/questions/24232451/debugging-shell-extensions-in-win-7-and-8-1