Internet Explorer falha quando MSXML2 :: IXMLDOMDocumentPtr -> Release () é chamado
Pergunta
Estou criando uma extensão de shell em C ++ (ATL 9) usando o Visual Studio 2008. A Shell Extensão cria um m_XmlDoc mundial objeto MSXML2 :: IXMLDOMDocumentPtr na classe módulo. Este m_XmlDoc é então utilizado na extensão por todas as classes de ler documento XML.
O problema que estou enfrentando é com o Internet Explorer. Quando a extensão Shell está ativa e eu abrir / fechar o Internet Explorer, eu recebo uma caixa de diálogo de depuração e IE falha. A mensagem de erro diz "Exceção não tratada no 0x6aac30f1 em iexplore.exe: Violação de acesso local de leitura 0x03050970: 0xC0000005." Quando eu clicar em "pausa" na janela de mensagem, Leva-me para o método "Release" do COM ponteiro inteligente eo erro parece estar em m_pInterface-> Release ();
Esta chamada foi feita a partir de destruição do módulo e também o valor de m_pInterface não é NULL. Eu acho que talvez o Internet Explorer está usando o DOM XML ea chamada para lançamento cria algum problema nele.
MSXML2::IXMLDOMDocumentPtr m_XmlDoc;
In _AtlModule.Init() method
::CoInitialize(NULL);
m_XmlDoc.CreateInstance(MSXML2::CLSID_DOMDocument40);
código de DllMain:
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
::CoInitialize(NULL);
if (dwReason == DLL_PROCESS_ATTACH)
{
_AtlModule.Init();
CreateImageLists();
::DisableThreadLibraryCalls(hInstance);
}
hInstance;
return _AtlModule.DllMain(dwReason, lpReserved);
}
Solução 3
O problema era por causa do COM ponteiro inteligente usado para XMLDOMDocument. Eu mudei para um ponteiro normal e ele está funcionando bem, mesmo em Vista.
Este problema tem um comportamento diferente no XP e Vista. No XP, eu estava ficando uma exceção não tratada quando fechei Internet Explorer. No Vista, eu não era capaz de navegar a unidade virtual.
Outras dicas
o uso de DisableThreadLibraryCalls está desanimado, você viu isso?
Há pelo menos dois problemas com seu código conforme publicado:
- Você está chamando CoInitialize no DllMain.
- Você está criando um objeto COM no DllMain.
- Não me surpreenderia se você está fazendo algo em CreateImageLists () que você também não deveria estar fazendo no DllMain.
Além disso, a razão que seu acidente foi "corrigido" por não usar o ponteiro inteligente é porque agora você não está realmente liberar o objeto mais. Seu código é quebrado, e não liberar a referência não é uma forma válida de corrigir alguma coisa.
Gostaria de sugerir que você lê, e, em seguida, voltar a ler, a documentação para DllMain com especial atenção para as coisas que você nunca deve fazer dentro da sua implementação da função. Como você verá frente até certo:
Aviso Há limites sérios sobre o que você pode fazer em um ponto de entrada DLL. Para fornecer a inicialização mais complexos, criar uma rotina de inicialização para a DLL. Você pode exigir aplicações para chamar a rotina de inicialização antes de chamar qualquer outras rotinas na DLL.
Eu suspeito que uma vez que você lê-lo, e corrigir o seu código para criar o objeto COM em um momento válido, e soltá-lo em um momento válido, sua extensão shell vai parar de bater.