我有一个应用程序,我想在其中为特定文件和文件夹设置图标覆盖。
为此,我编写了一个实现 IShellIconOverlayIdentifier 接口的 shell 扩展。它用 c++ / Qt ( activeqt ) 作为 dll 编写,使用 tcp 连接到相关应用程序以查询应用程序以决定是否显示图标覆盖。它的构建方式与此大致相同。
它在 XP/Vista/7 中运行良好,但在 Windows 8 中无法运行。
在 Windows 8 中加载 dll。我可以在进程资源管理器中看到它,并且作为调试的一部分,它还将输出记录到文件中,这样我就可以看到发生了什么并推断出什么。
使用ShellExView我还可以看到它已注册,而不是禁用,而且总的来说一切正常。
类声明看起来或多或少像这样:
class Q_DECL_EXPORT OverlayClass :
public QAxAggregated,
public IShellIconOverlayIdentifier{
public:
// Implements IUnknown
QAXAGG_IUNKNOWN;
JShellOverlayWorking();
// Implements IShellIconOverlayIdentifier
STDMETHOD(GetOverlayInfo)(LPWSTR pwszIconFile, int cchMax, int *pIndex, DWORD* pdwFlags);
STDMETHOD(GetPriority)(int* pPriority);
STDMETHOD(IsMemberOf)(LPCWSTR pwszPath, DWORD dwAttrib);
//pure virtual from QAxAggregated
long queryInterface(const QUuid &iid, void**iface);
};
XP/Vista/7 上发生了什么:
- 如果 iid == IID_IShellIconOverlayIdentifier 和所有其他 iid 的 E_NOINTERFACE,则加载时的资源管理器首先调用 queryInterface() 并获得 S_OK
- 然后它继续调用 GetOverlayInfo() 来初始化东西。获取图标文件路径等。
- 然后根据 shell 的需要调用 IsMemberOf() 来查看它是否应该显示文件或文件夹的图标。
在 Windows 8 上会发生什么:
- 加载时的资源管理器调用 queryInterface() 并在 iid == IID_IShellIconOverlayIdentifier 和所有其他 iid 的 E_NOINTERFACE 时获得 S_OK
没有别的了。queryInterface() 被调用,但之后没有任何反应。我可以看到我的应用程序成功连接到由 shell 扩展创建的 tcp 套接字,并且 IPC 正在工作(我可以在应用程序和 dll 之间来回发送数据,但又一次。没有其他事情发生。资源管理器没有使用实现的接口。
该 dll 使用以下方式注册:
regsvr32.exe shellext.dll
并且还添加了下面的注册表项
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\Shellextname ( value = CSLID )
为了在 Windows 8 上进行测试,我还添加了以下密钥
HKCU\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved
使用我的 shell 扩展 CSLID 作为名称和 data = Shellextname (如上一个键中所示),尽管这在 XP/Vista/7 上似乎无关紧要,所以我猜测它在这里也无关紧要。
同样,这适用于除 Windows 8 之外的所有 Windows(>= xp)。
我错过了什么?我该从哪里找到答案?