问题
I tried to code an icon handler in c++ but i have some issues to do this. I followed the turoriel from codeproject
The difference with this tutorial is i wanna code my dll with an ATL project from the wizard of visual studio (2013). So i create a new ATL project and i had a COM +1 class to this project (this the code of the header).
The problem is it seams that my dll is attach but is detach right after.
I'll put some code and more explication bellow :
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);;
}
This is my entry point of my dll. I did a lot of try and test on this entry point. I tried to write some log in function of the dwReason and this function is launch only when i compile. One time with the attribute DLL_PROCESS_ATTACH and an other time with the attribute DLL_PROCESS_DETACH. After that nothing seams to work even when i set my registry to call this dll in the IconHandler of my file.
I'll put my dllmain.h, my handler.h, my idl file and my rgs file. If you need more code to help me i'll put them later.
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;
IconHandler.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)
my idl file
// 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 file :
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 handler file :
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}'
}
}
}
I hope i was clear in my explanation. If you need more information to response at my question just tell me i'll be fast with my answer. I'll thank you to take your time to help me.
Florian
EDIT :
See my test on my 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;
The result in my test.txt :
Initialize AtlModule
Registrer app succeeded
RegisterServer succeeded
UpdateRegistryAppId succeeded
Execption !
Sombody here have a idee ?
回答1:
I didn't found any solution to work my solution. So i write my handler in C# even if this is not the best way to do that because that call some native function.
I used the follow tutorial from code-project : NET-Shell-Extensions-Shell-Icon-Handlers
I hope this tutorial gonna help some people. If someone have the answer to my preview question i will be glad to know what i have to do.
Florian
来源:https://stackoverflow.com/questions/16952684/how-to-create-a-iconhandler-used-by-the-shell-in-c