Como posso devolver tanto uma string de erro e código de erro para VB6 de um controle ActiveX ATL?

StackOverflow https://stackoverflow.com/questions/1069585

Pergunta

Eu estou tentando retornar um erro detalhada para VB6 usando CComCoClass :: erro , mas parece que só pode retornar um código de erro / ou / a mensagem - mas não ambos

.
return Error(_T("Not connected"), __uuidof(IMyInterface), HRESULT_FROM_WIN32(ERROR_CONNECTION_INVALID));

resulta em um genérico "Método 'Request' do objeto 'IMyInterface' falhou" mensagem de erro no Err.Description no lado do VB6 (mas ERROR_CONNECTION_INVALID em Err.Number), enquanto

return Error(_T("Not connected"));

resulta na mensagem de erro apropriada, mas um código de erro genérico em Err.Number. Como posso obter o melhor dos dois mundos?

Foi útil?

Solução

Você não pode, este parece ser por design. Detalhes mais adiante, mas em suma, você tem três opções:

  • Voltar nenhuma mensagem e um erro amigável COM VB, ou seja, um conhecido pelo tempo de execução VB de acordo com esta KB artigo ; o tempo de execução VB irá traduzir este 'erro COM' a um erro VB além de mensagem.
  • retornar uma mensagem de erro e DISP_E_EXCEPTION; o tempo de execução VB vai passar por este 'Erro de servidor' e sua mensagem de erro personalizada. Isto é o que está acontecendo implicitamente em seu segundo exemplo, veja abaixo para mais detalhes.
  • Voltar nenhuma mensagem e qualquer outro erro COM, isto é, um não conhecido pelo tempo de execução VB; o tempo de execução VB irá recorrer ao HRESULT cru mais a mensagem genérica "Method '~' of object '~' failed".
    • Por favor note que este comportamento de tempo de execução também se aplica, se você fornecer uma mensagem de erro aqui, ou seja, a sua mensagem será simplesmente ignorado! Isto é o que está acontecendo em seu primeiro exemplo, veja abaixo para mais detalhes.

Para a tarefa em mãos tudo se resume a duas escolhas:

  • Se você quiser fornecer 'erros COM' contextualmente corretas para clientes de automação como VB (e provavelmente você deve), você deve omitir mensagens de erro personalizadas.
  • Se você quiser fornecer mensagens de erro personalizada para 'erros servidor' (uma condição de erro personalizadas ou seja, sobre a funcionalidade dentro o seu servidor de automação) sua única opção é DISP_E_EXCEPTION.

Detalhes

O tempo de execução VB parece oferecer muito restrito manipulação no que diz respeito a erros COM. Isto é provavelmente por razões históricas e / ou técnicas específicas para o caminho VB foi implementado e não de particular interesse aqui (palavras-chave seria IDispatch única vs interface dupla e ActiveX como um 'subconjunto' de COM).

Enquanto eu fui incapaz de superfície uma especificação explícita para o comportamento descrito acima pode-se entender de cavar através de outras fontes:

A partir do artigo KB justadreamer apontou já :

[...] é feita uma chamada para o método GetErrorInfo para recuperar o informações de erro disponível. o runtime, em seguida, determina se bstrDescription tem um valor diferente de NULO. Se o tempo de execução encontra um valor diferente de NULL, [...], o HRESULT crua valor é usado neste cenário. Se o tempo de execução encontra um valor NULL, [...] Visual Basic, em seguida, usa HRESULT para procurar o correspondente Visual erro básico.

Isso explica o comportamento em relação a sua exemplo punho:. Que você fez fornecer uma mensagem de erro, portanto, o tempo de execução simplesmente recorre a sua mensagem genérica "Method '~' of object '~' failed" plus seu HRESULT

O comportamento do seu segundo exemplo também é consistente uma vez que você olhar para a definição do construtor (primeiro da lista) para CComCoClass::Error : tem padrões para os parâmetros não especificada, especialmente 'hRes = 0'. A secção 'Observações' afirma ainda que "Se hRes é zero, então os primeiros quatro versões de DISP_E_EXCEPTION retorno de erro.". Consequentemente, esta desencadeia implicitamente o passe 'Erro de servidor' através de um comportamento.

Finalmente, para um concreto C ++ amostra implementação de um VB como o comportamento do cliente de automação ver por 'Erro de manipulação' exemplo parágrafos e o seguinte 'Exercício 5' em Automatizando Microsoft Office 97 e Microsoft Office 2000 .

Outras dicas

derivar a classe que implementa a interface exposta-COM da ISupportErrorInfoImpl, chamar SetErrorInfo para definir a explicação detalhada do erro se houver ocorre. Não se esqueça de incluir ISupportErrorInfo no COM_MAP de sua classe.

Eu estou lutando com isso agora também. Até agora o meu escavação indica que o código de erro é realmente o valor HRESULT. VB6 tenta ser inteligente e interpretar o HRESULT mas parece ter uma lista bastante limitada de HRESULTs ele entende. Para o HRESULTs VB6 não está familiarizado com, ele apenas coloca o HRESULT para a propriedade Err.Number e espera que o desenvolvedor é inteligente o suficiente para descobrir o que fazer com ele.

O mais próximo que eu vim para retornar um número de erro é usando MAKE_SCODE para gerar um HRESULT com o campo de código do conjunto HRESULT para o que eu quero, o jogo da bandeira gravidade e que eu espero é a facilidade direita.

Isso em conjunto com CreateErrorInfo e SetErrorInfo me um código de erro e uma descrição de erro em VB6. E isso nos traz de volta ao VB6 tentando ser inteligente com uma lista limitada de erros.

Checkout este artigo http://support.microsoft.com/kb/827994 . Portanto, o seu objeto deve implementar o método ISupportsErrorInfo :: InterfaceSupportsErrorInfo () que retorna S_OK. e, em seguida, antes de retornar você deve chamar SetErrorInfo com um ponteiro para um objeto COM que implementa IErrorInfo :: GetDescription (). Há um exemplo aqui: http://msdn.microsoft.com/en-us/library/ms221409. aspx .

Se você SetErrorInfo antes do retorno, VB irá consultar o método GetDescription do ponteiro do objeto que você passou para SetErrorInfo.

Eu não sou muito profundo no código atribuído você estiver usando - Eu preferiria testá-lo usando COM mais cru que é certamente sempre um monte de código clichê - mas pelo menos ele funciona, então você poderia usar invólucros sofisticados em vez de -lo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top