如何在 C++ 中创建 shell 使用的 IconHandler?

Posted

技术标签:

【中文标题】如何在 C++ 中创建 shell 使用的 IconHandler?【英文标题】:How to create a IconHandler used by the shell in c++? 【发布时间】:2013-06-06 02:14:21 【问题描述】:

我尝试在 C++ 中编写图标处理程序,但我有一些问题要执行此操作。我从codeproject跟踪了turoriel

本教程的不同之处在于我想用 Visual Studio 向导 (2013) 中的 ATL 项目编写我的 dll。所以我创建了一个新的 ATL 项目,并且我有一个 COM +1 类到这个项目(这是标题的代码)。

问题是我的 dll 是附加的,但之后立即分离。

我会在下面放一些代码和更多解释:

extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)

    if (dwReason == DLL_PROCESS_ATTACH)
    
        _AtlModule.InitLibId();
        //_AtlModule.RegisterAppId();
    

    return _AtlModule.DllMain(dwReason, lpReserved);;

这是我的 dll 的入口点。我在这个入口点做了很多尝试和测试。我试图写一些 dwReason 的登录函数,这个函数只有在我编译时才会启动。一次使用属性 DLL_PROCESS_ATTACH,另一次使用属性 DLL_PROCESS_DETACH。之后,即使我将注册表设置为在文件的 IconHandler 中调用此 dll,也没有任何接缝工作。

我将放置我的 dllmain.h、我的 handler.h、我的 idl 文件和我的 rgs 文件。如果您需要更多代码来帮助我,我稍后再放。

dllmain.h

class CQIIconDllModule : public ATL::CAtlDllModuleT< CQIIconDllModule >

public :
    DECLARE_LIBID(LIBID_QIIconDllLib)
    DECLARE_REGISTRY_APPID_RESOURCEID(IDR_QIHANDLER, "7FFCD43D-9EB3-4F76-940C-98C333FB8A99")
;

extern class CQIIconDllModule _AtlModule;

图标处理程序.h

// QIHandler.h : Declaration of the CQIHandler

#pragma once
#include "resource.h"       // main symbols
#include <ShlObj.h>


#include "QIIconDll_i.h"



#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif

using namespace ATL;


// CQIHandler

class ATL_NO_VTABLE CQIHandler :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CQIHandler, &CLSID_QIHandler>,
    public IQIHandler,
    public IPersistFile,
    public IExtractIcon

public:
    CQIHandler()
    
    

DECLARE_REGISTRY_RESOURCEID(IDR_QIHANDLER)

DECLARE_NOT_AGGREGATABLE(CQIHandler)

BEGIN_COM_MAP(CQIHandler)
    COM_INTERFACE_ENTRY(IQIHandler)
    COM_INTERFACE_ENTRY(IPersistFile)
    COM_INTERFACE_ENTRY(IExtractIcon)
END_COM_MAP()



    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    
        return S_OK;
    

    void FinalRelease()
    
    

public:
     // IPersistFile
    STDMETHODIMP GetClassID( CLSID* )  return E_NOTIMPL; 
    STDMETHODIMP IsDirty()  return E_NOTIMPL; 
    STDMETHODIMP Save( LPCOLESTR, BOOL )  return E_NOTIMPL; 
    STDMETHODIMP SaveCompleted( LPCOLESTR )  return E_NOTIMPL; 
    STDMETHODIMP GetCurFile( LPOLESTR* )  return E_NOTIMPL; 

    STDMETHODIMP Load( LPCOLESTR wszFile, DWORD )
         
        USES_CONVERSION;
        lstrcpyn ( m_szFilename, W2CT(wszFile), MAX_PATH );
        return S_OK;
        

    // IExtractIcon
    STDMETHODIMP GetIconLocation( UINT uFlags, LPTSTR szIconFile, UINT cchMax,
                                  int* piIndex, UINT* pwFlags );
    STDMETHODIMP Extract( LPCTSTR pszFile, UINT nIconIndex, HICON* phiconLarge,
                          HICON* phiconSmall, UINT nIconSize );

protected:
    TCHAR     m_szFilename[MAX_PATH];   // Full path to the file in question.


;

OBJECT_ENTRY_AUTO(__uuidof(QIHandler), CQIHandler)

我的 idl 文件

// QIIconDll.idl : IDL source for QIIconDll
//

// This file will be processed by the MIDL tool to
// produce the type library (QIIconDll.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";

[
    object,
    uuid(a817e7a2-43fa-11d0-9e44-00aa00b6770a),
    dual,   
    pointer_default(unique)
]
interface IComponentRegistrar : IDispatch

    [id(1)] HRESULT Attach([in] BSTR bstrPath);
    [id(2)] HRESULT RegisterAll();
    [id(3)] HRESULT UnregisterAll();
    [id(4)] HRESULT GetComponents([out] SAFEARRAY(BSTR)* pbstrCLSIDs, [out] SAFEARRAY(BSTR)* pbstrDescriptions);
    [id(5)] HRESULT RegisterComponent([in] BSTR bstrCLSID);
    [id(6)] HRESULT UnregisterComponent([in] BSTR bstrCLSID);
;

[
    object,
    uuid(1A80BA8B-2932-4EB4-AA88-5216F92BBA33),
    pointer_default(unique)
]
interface IQIHandler : IUnknown
;


[
    uuid(17AD604F-FDD1-453C-A2D2-EAD3FCC42AB5),
    version(1.0),
    custom(a817e7a1-43fa-11d0-9e44-00aa00b6770a,"D32D9690-E6A4-44D8-A949-5F39D35269F8")
]
library QIIconDllLib

    importlib("stdole2.tlb");
    [
        uuid(D32D9690-E6A4-44D8-A949-5F39D35269F8)      
    ]
    coclass CompReg
    
        [default] interface IComponentRegistrar;
    ;
    [
        uuid(7FFCD43D-9EB3-4F76-940C-98C333FB8A99)      
    ]
    coclass QIHandler
    
        [default] interface IQIHandler;
    ;
;

rgs 文件:

HKCR

    NoRemove CLSID
    
        ForceRemove D32D9690-E6A4-44D8-A949-5F39D35269F8 = s 'CompReg Class'
        
            InprocServer32 = s '%MODULE%'
            
                val ThreadingModel = s 'Apartment'
            
            TypeLib = s '17AD604F-FDD1-453C-A2D2-EAD3FCC42AB5'
            Version = s '1.0'
        
    

rgs 处理程序文件:

HKCR

    NoRemove CLSID
    
        ForceRemove 7FFCD43D-9EB3-4F76-940C-98C333FB8A99 = s 'QIHandler Class'
        
            InprocServer32 = s '%MODULE%'
            
                val ThreadingModel = s 'Apartment'
            
            TypeLib = s '17AD604F-FDD1-453C-A2D2-EAD3FCC42AB5'
            Version = s '1.0'
        
    


    NoRemove qifile
    
        NoRemove DefaultIcon = s '%%1'
        NoRemove ShellEx
        
            ForceRemove IconHandler = s '7FFCD43D-9EB3-4F76-940C-98C333FB8A99'
        
    

我希望我的解释很清楚。如果您需要更多信息来回答我的问题,请告诉我,我会尽快回答。我会感谢你花时间帮助我。

弗洛里安

编辑:

在我的 dllmain 上查看我的测试。 cpp

    BOOL ret = false;
    FILE *file; 
    fopen_s(&file, "test.txt","a+"); /* apend file (add text to 
        a file or create a file if it does not exist.*/ 
    if (dwReason == DLL_PROCESS_ATTACH)
    
        fprintf(file,"%s","Initialize AtlModule\n"); /*writes*/ 
        _AtlModule.InitLibId();
        HRESULT hr = _AtlModule.RegisterAppId();
        if (SUCCEEDED(hr))
        
            fprintf(file,"%s","Registrer app succeeded \n"); /*writes*/ 
            hr = _AtlModule.RegisterServer(TRUE, &CLSID_QIHandler);
            if (SUCCEEDED(hr))
            
                fprintf(file,"%s","RegisterServer succeeded \n"); /*writes*/ 
                hr = _AtlModule.UpdateRegistryAppId(TRUE);
                if (SUCCEEDED(hr))
                
                    fprintf(file,"%s","UpdateRegistryAppId succeeded \n"); /*writes*/ 
                    ret = true;
                
            
        

    
#ifdef _DEBUG
    else if (dwReason == DLL_PROCESS_DETACH)
    
        _AtlModule.UpdateRegistryAppId(FALSE);
        _AtlModule.Term();
    //*/
#endif
    if (dwReason == DLL_PROCESS_DETACH && lpReserved != NULL)
    
        ret = true;
    
    else if (dwReason == DLL_PROCESS_DETACH)
    
        fprintf(file,"%s","Execption ! \n"); /*writes*/ 
    

    fclose(file); /*done!*/ 
    return ret;

我的 test.txt 中的结果:

Initialize AtlModule
Registrer app succeeded 
RegisterServer succeeded 
UpdateRegistryAppId succeeded 
Execption ! 

这里有人有想法吗?

【问题讨论】:

【参考方案1】:

我没有找到任何解决方案来解决我的问题。所以我用 C# 编写我的处理程序,即使这不是最好的方法,因为它调用了一些本机函数。

我使用了代码项目中的以下教程:NET-Shell-Extensions-Shell-Icon-Handlers

我希望本教程能帮助一些人。如果有人回答了我的预览问题,我会很高兴知道我必须做什么。

弗洛里安

【讨论】:

以上是关于如何在 C++ 中创建 shell 使用的 IconHandler?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 C++ 在 Windows 中创建守护线程?

如何使用 C++ 在任务计划程序中创建任务

如何在 Flutter 中创建圆形图标按钮?

如何在 C++ 或 Qt 中创建进程?

如何在 C++ 中的子类中创建父对象数组?

如何使用 c++ 和 opengl 在 mac 中创建窗口?