Gethrforexception
Eu tenho um código IO que lê um fluxo dentro de um try..catch. Ele captura IOException e chama System. Runtime. InteropServices. Marshal. GetHRForException () dentro da captura, em uma tentativa de executar ações diferentes com base no HResult. Algo assim:
Mas executando este código dentro do ASP. NET com trust = "medium", eu recebo esta exceção:
Algumas perguntas:
Eu acho que a exceção está ocorrendo porque GetHRForException chama em código não gerenciado, o que não é permitido em confiança média. Corrigir? Esta exceção está sendo lançada, não no momento da execução do GetHRForException, mas no momento em que o método está sendo JIT'ed - correto? (O stacktrace mostra meu método, mas tenho 99% de certeza de que uma exceção de IO não ocorreu) Em caso afirmativo, há uma maneira de variar o comportamento em um ambiente de confiança parcial, para que eu não chame o GetHRForException ( código não gerenciado) onde não é permitido? Em outras palavras, como posso permitir que o JIT seja bem-sucedido em tempo de compilação, enquanto também avalio em tempo de execução se o código deve chamar GetHRForException ()? Algo assim:
Eu acho que existe um mecanismo de tempo de execução para testar se as permissões estão disponíveis, mas não foram capazes de encontrá-lo.
Moeda estrangeira on-line Angra dos Reis.
Pesquisar este blog.
Gethrforexception exemplo de application.
Obter link Facebook Twitter Pinterest Google+ E-mail Outras Aplicações.
Eu sou algum código IO que lê um fluxo dentro de um try..catch. Ele captura IOException e chama System. Tempo de execução. InteropServices. Marechal. GetHRForException () dentro da captura, em uma tentativa de tomar ações diferentes com base no HResult. Algo como isto: NET com o trustmedium, eu recebo esta exception: Algumas perguntas: Acho que está isento de uma exceção porque getHRForException não é gerenciado, o que não é permitido na média. Corrigir Esta exceção está sendo lançada, não há momento da execução de GetHRForException, mas não há nenhum método em que está sendo JITed - Correto (O stacktrace mostra meu método, mas tenho certeza de que uma exceção de IO não ocorreu) O que é um código de suporte não pode ser usado como um código de controle. O código não é gerenciado em outras palavras, como posso permitir que o código para o sucesso também seja avaliado. Se o código for necessário GetHRForException (), você não pode ter sido capaz de encontrar-se. EDITAR. É este artigo de blogue resposta ShawnFa da Microsoft. Catch (SecurityException) em torno de um método protegido por um LinkDemand. Se MethodA () chama MethodB (), e MethodB () é marcado com LinkDemand para total de confiança, em seguida, o LinkDemand é marcado com MethodA é Jited. Portanto, se quiser uma SecurityException, preciso extrair Marshal. GetHRForException em um método separado. O código pode ser aplicado ao método, e pode ser chamado de GetHRForException (). GetHRForException é MethodB (). O LinkDemand é rated quando MethodA () é JITd. (Este LinkDemand falha no meu cenário de médio-confiança ASP. NET). Se você mover o GetHRForException em um novo método, MethodC (), e chamar condicionalmente MethodC () somente após uma permissão imperativa. Demanda () é bem-core, teoricamente deveria ser capaz de evitar SecurityException no tempo JIT, porque MethodC () será JITd somente após a permissão. Demain () tiver sucedido. Pediu Jul 12 09 at 14:20 O método necessário é SecurityPermission. IsUnrestricted (). Retorna a false to the permission is permissioned or não. Ele não requer uma permissão, como faz SecurityPermission. Exigem (). Eu use IsUnresticted com SecurityPermissionFlag. UnmanagedCode para ver se o código de acesso não é gerenciado, em seguida, o código de acesso não é gerenciado somente se permitido. Há uma torção adicional. O compilador JIT, ao compilar um método, verifica para LinkAcessos de CodeAccessPermission em qualquer método chamado meu método a ser compilado. Marechal. GetHRForException () é marcado com um LinkDemand. Assim, meu método que chama Marshal. GetHRForException () irá apresentar uma condição de segurança não disponível no momento da compilação JIT, quando estiver em um ambiente restrito, como o ASP. NET com confiança média. Portanto, o método JEC e o Marshal. GetHRForException () nesse caso, o que significa que eu preciso para quebrar Marshal. GetHRForException () em um método separado não é um código que é chamado (assim) JITted) apenas quando UnmanagedCode é Sem restrições. Heres sometum code de exemplo: não respondido Jul 20 09 at 17:56 Sim - média não é chamada em código não gerenciado. O nível de confiança que é o único é um total de confiança. Depende. As demandas de CAS podem ser executadas em tempo de execução, mas as informações de hospedagem também podem ser executadas em um programa de busca. Você pode fazer o teste para ver se há uma chamada para o código não gerenciado em uma mensagem CAS com uma instância de SecurityPermission. O código para fazer uma demanda parece ter sido respondido Jul 12 09 at 14:32 OK, esta é uma grande informação. Isso é parte da Q3. Mas, em uma parte Como fazer para obter uma compilação JIT for business success Pode marcar meu método com um atributo de segurança ou. - P, Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security Security. Então a questão é, como eu escrevo o código para permitir que o JIT compile. Ndash Cheeso Jul 12 09 at 15:50 Você deve fazer o tempo de execução, caso contrário, o assembly wouldn39t mesmo carregar - e para que isso aconteça o assembly precisa ser marcado como exigindo uma permissão. O que então é uma verificação de tempo de execução, como é o tempo na carga de execução, que poderia estar no tempo de execução. Ndash blowdart Jul 12 09 at 16:24 Diferentes tipos de verificação, como as demandas de link são atributos em um método, e são de fato verificadas sem tempo JIT. Ele é muito usado pela própria estrutura e é raro para a fonte CLR. O que é uma demonstração imperativa, não declarativa como um SecurityPermission (SecurityAction. LinkDemand, Unrestricted true) ndash blowdart Jul 12 09 às 18: 55Quiz: Gotcha com exceções e HRESULTs Bem, tanto ENOINTERFACE e EPOINTER HRESULT são mapeados para um InvalidCast Exceção por ThrowExceptionForHR. Uma vez que uma exceção InvalidCast é lançada, o mesmo HRESULT será retornado de GetHRForException (they8217re a mesma exceção nesse ponto). A razão que 0x8004002 é apresentada como sendo o objeto de erro não está sendo redefinido entre os dois try / catch blocos. Antes da primeira tentativa / captura o objeto de erro associado com o segmento lógico está vazio, após tentar / capturar o objeto de erro objeto8217s HRESULT é listado como 0x8004002. Agora, o segundo try / catch bloco é executado e GetErrorInfo () é executado para definir o valor COMException. HRESULT para o valor do objeto de erro (que já está definido como 0x8004002), portanto, o valor COMException. HRESULT é como como 0x8004002. Veja o que está apresentando um exemplo8230 Bem, consegui demonstrar que está fazendo o mesmo (veja o código abaixo). Eu inseri uma chamada para criar uma nova instância do Excel. ApplicationClass no Excel COM Server. Qualquer chamada de apartamento cruzado que pode ser utilizada por um proxy-stub ou qualquer outra chamada COM dentro de um apartamento para usar o ciclo de comunicação COM (STA) irá apagar o arquivo de informações de erro. Dessa forma, uma chamada para o objeto COM do Excel entre como exceções Capturou o objeto de suas informações de erro: Classe A1 const int ENOINTERFACE desmarcado (int 0x80004002) const int EPOINTER desmarcado (int 0x80004003) private Excel. Application ExcelApplication null Muito bom Observações, todos normalmente, ENOINTERFACE é mapeado para InvalidCastException e EPOINTER é mapeado para NullReferenceException. Mas como Fernando apontou, ambas as exceções lançadas neste exemplo são InvalidCastException. Isso se justifica por GetHRForException retorna ENOINTERFACE em ambos os casos, mas por isso as últimas duas variáveis InvalidCastException duas vezes OO ThrowExceptionForStyle ou HRESULT (HRESULT) é uma tabela de mapeamento. CLR8217s). Mas ele faz mais do que apenas isso: ele chama o Win32 GetErrorInfo API para tentar recuperar um objeto de erro disponível no thread atual. Ele usa essas informações para dar uma mensagem de erro, origem e assim por diante. ThrowExceptionForHR também tem uma sobrecarga com um segundo sistema de parâmetros. IntPtr que representa um ponteiro para uma interface IErrorInfo, para que os seres humanos possam transmitir essas informações diretamente. IntPtr Passar O que significa que você pode usar um API como uma sobrecarga de um parâmetro e, em seguida, fazer uma atualização de informações extras. O GetHRForException método recupera o valor HRESULT para qualquer exceção gerenciada. Este é o valor da propriedade protegida de exceção, que especificamente você não pode acessar diretamente. Mas esse método tem um efeito colateral: ele chama o Win32 API SetErrorInfo, passando o CCW para a exceção (que implementa IErrorInfoetado). Ele faz isso para tornar mais fácil o comportamento do marshaler8217s ao exportar uma exceção como um HRESULT e IErrorInfo para COM. Neste exemplo, uma primeira chamada para GetHRForException faz com que o CLR seja chamado SetErrorInfo com o objeto inválido InvalidCastException. After a this, a second Call for ThrowExceptionForHR to get as informações when you chama GetErrorInfo, como Phil marcou. A razão isso é tipo de exceção lançada 8211 apesar do fato de que o IErrorInfo doesn8217t tem um mecanismo para recuperar um HRESULT 8211 é que o CLR pode detectar quando o objeto de erro é recuperado de SetErrorInfo como uma exceção gerenciada e apenas reutilizar essa exceção original . Tudo isso é que não importa o que é HRESULT para o método ThrowExceptionForHR pela segunda vez, uma exceção lançada é sempre um InvalidCastException. Para obter o desempenho que você está usando, clique em ignorar IErrorInfo: using System using System. Tempo de execução. InteropServices classe pública Pergunta int int ENOINTERFACE desmarcada (int 0x80004002) const int EPOINTER desmarcada ((int) 0x80004003) Pública static void Main () try Marshal. ThrowExceptionForHR (ENOINTERFACE) captura (exceção ex) Console. WriteLine (quot0x quot, Marshal. GetHRForException (ex)) Este código foi escrito: Phil perguntou por Marshal. GetLastWin32Error sempre retornou 0 não importa onde ele Inserido. That8217s porque GetLastError / SetLastError é um mecanismo separado de GetErrorInfo / SetErrorInfo. O mecanismo anterior nunca está envolvido aqui. E, sim, o código gerenciado nunca deve chamar GetLastError diretamente. Veja: blogs. gotdotnet / anathan / PermaLink. aspx / 6d021f27-72c8-4420-b6ad-1c5f0690bde8 Lamento que meu guest não se refere ao assunto. O que é o conhecimento pode obter informações de uma página, por exemplo, obter o código html de uma página especial no meu ASP ou ASP. NET apllication e usar o meu aplicativo. Por exemplo, use o código html quotanysite Em seguida, use o código na minha página de programação. I8217ve having enough people would question about this, then eu. Eles podem ter uma chance primeira de fazer o download do seu aplicativo, mas ele não pode ser usado como qualquer outro problema (app doesn t8177) e ainda existem 8216fine8217. O que parece ter acontecido principalmente se você tem um problema, mas eu não tenho certeza de que é isso que eu acho. Tempo. É um conceito difícil, mas difícil de agarrar uma vez que você começa a pensar sobre o fluxo real do código vai e o inferno em uma vez que você começa a descrever o que é mais fácil de explicar isso e vamos dizer que você tem uma função de exportação em sua DLL nativa: void WINAPI MyFunction (comptrtltIMyInterfacegt ptr) E o DllImport seria algo como isto: DllImport (quotmydll. dll) void MyFunction (IMyInterface ptr) As pessoas que estão apresentando o código para VS 2017. Normalmente, elas têm P / Invoke assim: DllImport (quotWin32Project2.dllquot, PreserveSig true, CharSet CharSet. Unicode) estático extern int MyPInvoke (seqüência de caracteres ret) Se você anexar um depurador nativo (ou habilitar uma depuração nativa), com os símbolos corretos (símbolo público8230 24 de janeiro de 2017 2 x2605 x2605 x2605 x2605 x 2605 x2605 x2605 x2605 x2605 x2605 x2605 Para a primeira vez, olhando para um pequeno código de snippet: if (Marshal. GetHRForException (myException) ESMECOMERROR DoSomething () Isso parece exatamente bem, não realmente. Acontece that is API is really mal called, and it is it now it is lost the HR object of ilo. Você pode estar interessado em encontrar alguns erros estranhos? Aprenda esse truque de depuração de alguns dias, quando estivermos a depilar juntos e não pudermos esperar por isso. Conceitualmente, é realmente uma idéia simples, mas é muito útil. O que está fazendo é depurando um acidente. Você sabe que o bug é útil na última vez que Samsung Focus, mas ele não é reconhecido pelo Software Quando ele se conecta ao meu computador e software zune fez pop - acima. Passar meia hora procurando soluções e eu corro para este artigo: microsoft / windows / pt-br / howto / wp7 / básico / o-zune-software-doesnt-reconhece-my-phone. aspx Um de8230 21 de dezembro de 2018 1 x2605 x2605 x2605 x2605 x2605 x2605 x2605 x2605 x2605 x2605 x2605 O que é 0x8013XXXX Ocasionalmente você pode executar em HRESULTs misterioso retornado de. NET que começa com 0x8013, por exemplo, 0x80131522. Infelizmente, uma pesquisa de erro feita com o Visual Studio não funciona realmente com aqueles HRESULTs estranhos. O que são eles Acontece que eles são de fato, definidos por. NET / CLR nos arquivos de cabeçalho. 4 de dezembro de 2018 0 x2605 x2605 x2605 x2605 x2605 x2605 x2605 x2605 x2605 x2605 x2605 x2605
Gethrforexception
Permitir que uma exceção se propague fora do método produz um comportamento incorreto. (Na verdade, o common language runtime não passa uma exceção para um cliente COM chamando esse método por meio de uma v-table.)
Desde que eu removi todos os atributos PreserveSig de todos os meus métodos de interface e mudei para uma abordagem completamente baseada em exceção para minha biblioteca, isso seria ruim. Nos meus objetos COM, eu uso & quot; throw & quot; o tempo todo para enviar erros para o chamador (tanto gerenciados quanto não gerenciados) e eu ainda não vi nenhum problema. Eu jogo um COMException e o HRESULT acaba na chamada hr. Além disso, o cliente (não gerenciado) pode recuperar a interface IErrorInfo para receber o texto que eu lanço junto com o código de erro.
Esses documentos antigos não foram atualizados para refletir o comportamento atual? Talvez eu esteja entendendo mal o que está tentando me dizer? Ou há alguma pegadinha horrível esperando para me morder no futuro?
Antigo Blog de Adam Nathan Antigo Blog de Adam Nathan.
Por favor, visite adamnathan em vez disso!
Quiz: Gotcha com exceções e HRESULTs.
O código C # abaixo, quando executado, imprime o seguinte:
Quem pode descobrir por que a segunda linha impressa não é 0x80004003?
questionário de classe pública.
const int E_NOINTERFACE = desmarcado ((int) 0x80004002);
const int E_POINTER = desmarcado ((int) 0x80004003);
public static void Main ()
catch (exceção ex)
catch (exceção ex)
Cancelar resposta.
Bem, tanto E_NOINTERFACE e E_POINTER HRESULT são mapeados para uma exceção InvalidCast por ThrowExceptionForHR. Depois que uma exceção InvalidCast é lançada, o mesmo HRESULT será retornado de GetHRForException (eles são a mesma exceção nesse ponto).
O motivo pelo qual 0x8004002 é exibido nas duas vezes é que o objeto de erro não está sendo redefinido entre os dois blocos try / catch. antes do primeiro try / catch o objeto de erro associado ao thread lógico está vazio, depois que o valor HRESULT do try / catch do objeto de erro é definido como 0x8004002. Agora o segundo bloco try / catch é executado e o GetErrorInfo () é executado para definir o valor COMException. HRESULT para o valor do objeto de erro (que já está definido como 0x8004002), portanto, o valor COMException. HRESULT é definido como 0x8004002. Deixe-me ver se consigo criar um exemplo & # 8230;
Bem, eu pude demonstrar porque isso está acontecendo (veja o código abaixo). Eu inseri uma chamada para criar uma nova instância do Excel. ApplicationClass no servidor COM do Excel. Qualquer chamada entre apartamentos que utilize um proxy-stub ou qualquer chamada COM em um apartamento que use o loop de mensagem COM (STA) limpará o objeto de informação de erro. Assim, a chamada para o objeto COM do Excel entre as exceções capturadas irá limpar o objeto de informação de erro:
const int E_NOINTERFACE = desmarcado ((int) 0x80004002);
const int E_POINTER = desmarcado ((int) 0x80004003);
private Excel. Application _ExcelApplication = null;
Sim. Ovo está no meu rosto. Um teste simples provou que eu estava errado.
Interessante. No meu teste, eu também tentei Marshal. GetLastWin32Error após as funções TryInterface (), CallExcel () e TryPointer (), mas ele retornou 0. Eu também li em algum lugar que código gerenciado nunca deve chamar GetLastError () diretamente desde os resultados do GetLastError ( ) a chamada pode não ser precisa porque o CLR pode ter feito chamadas adicionais que modificariam o objeto de erro de encadeamento lógico.
Adam, você poderia dar algumas informações sobre como você encontrou esse bug / recurso?
Além disso, meu exemplo demonstrou o que está acontecendo ou há outra razão pela qual isso está acontecendo?
Eu não tenho muito a acrescentar, mas uma coisa que notei é que, em ambos os casos, o código está lançando a mesma instância da exceção. Além disso, se você lançar cada exceção em seu próprio thread, ele imprimirá o resultado esperado.
Muito boas observações, todos!
Normalmente, E_NOINTERFACE é mapeado para InvalidCastException e E_POINTER é mapeado para NullReferenceException. Mas, como Fernando destacou, ambas as exceções lançadas neste exemplo são InvalidCastException. Isso explica por que GetHRForException retorna E_NOINTERFACE nos dois casos, mas por que recebemos uma InvalidCastException duas vezes?
O ThrowExceptionForHR método lança uma exceção cujo tipo corresponde ao valor HRESULT de entrada (ou um COMException contendo o HRESULT se a entrada HRESULT isn & t; t na tabela de mapeamento do CLR). Mas ele faz mais do que isso: chama a API Win32 GetErrorInfo para tentar recuperar um objeto de erro disponível no thread atual. Ele usa essas informações para fornecer à exceção uma mensagem de erro personalizada, origem e assim por diante. ThrowExceptionForHR também tem uma sobrecarga com um segundo parâmetro System. IntPtr que representa um ponteiro para uma interface IErrorInfo, para que você possa passar essas informações diretamente. Passar IntPtr. Zero significa que você deseja que a API atue como a sobrecarga de parâmetro único (e chame GetErrorInfo), e passar -1 desabilita a recuperação extra de informações.
O GetHRForException método recupera o valor HRESULT para qualquer exceção gerenciada. Este é o valor do campo & quot; HResult & quot protegido &; propriedade, que você normalmente não pode acessar diretamente. Mas esse método tem um efeito colateral: ele chama a API Win32 SetErrorInfo, passando o CCW para exceção (que implementa IErrorInfo apropriadamente). Ele faz isso para facilitar a imitação do comportamento do empacotador ao expor manualmente uma exceção como um HRESULT e IErrorInfo para COM.
Neste exemplo, a primeira chamada para GetHRForException faz com que o CLR chame SetErrorInfo com o objeto InvalidCastException empacotado. Devido a isso, a segunda chamada para ThrowExceptionForHR pega essas informações quando ele chama GetErrorInfo, como Phil apontou. A razão pela qual isso afeta o tipo da exceção gerada & # 8211; apesar do fato de que IErrorInfo não tem um mecanismo para recuperar um HRESULT & # 8211; é que o CLR pode detectar quando o objeto de erro recuperado de SetErrorInfo é originado como uma exceção gerenciada e apenas reutilizar essa exceção original. Tudo isso significa que não importa o que HRESULT é passado para o método ThrowExceptionForHR a segunda vez (contanto que seja uma falha HRESULT), a exceção gerada é sempre um InvalidCastException.
Para obter o comportamento que você normalmente espera, você pode usar a sobrecarga de ThrowExceptionForHR que ignora IErrorInfo:
questionário de classe pública.
const int E_NOINTERFACE = desmarcado ((int) 0x80004002);
Marechal. Método GetHRForException (Exception)
A documentação de referência da API. NET tem uma nova página. Visite o Navegador da API. NET em docs. microsoft para ver a nova experiência.
Converte a exceção especificada para um HRESULT.
Assembly: mscorlib (em mscorlib. dll)
Parâmetros
A exceção para converter para um HRESULT.
Valor de retorno.
O HRESULT mapeado para a exceção fornecida.
GetHRForException também configura uma interface IErrorInfo para a exceção que pode ser obtida chamando a função COM GetErrorInfoNEEDGUID. Você pode usar essa função para retornar um valor HRESULT em uma implementação de classe gerenciada de uma interface COM onde você aplica o atributo PreserveSigAttribute. Ter o método atribuído capturar todas as exceções e use o método GetHRForException para retornar o valor HRESULT apropriado. Permitir que uma exceção se propague fora do método produz um comportamento incorreto. (Na verdade, o common language runtime não passa uma exceção para um cliente COM que chama esse método por meio de uma tabela v.)
Observe que o método GetHRForException define a interface IErrorInfo do thread atual. Isso pode causar resultados inesperados para métodos como os métodos ThrowExceptionForHR que usam o IErrorInfo do thread atual, se estiver definido.
requer confiança total para o chamador imediato. Este membro não pode ser usado pelo código parcialmente confiável ou transparente.
Permitir que uma exceção se propague fora do método produz um comportamento incorreto. (Na verdade, o common language runtime não passa uma exceção para um cliente COM chamando esse método por meio de uma v-table.)
Desde que eu removi todos os atributos PreserveSig de todos os meus métodos de interface e mudei para uma abordagem completamente baseada em exceção para minha biblioteca, isso seria ruim. Nos meus objetos COM, eu uso & quot; throw & quot; o tempo todo para enviar erros para o chamador (tanto gerenciados quanto não gerenciados) e eu ainda não vi nenhum problema. Eu jogo um COMException e o HRESULT acaba na chamada hr. Além disso, o cliente (não gerenciado) pode recuperar a interface IErrorInfo para receber o texto que eu lanço junto com o código de erro.
Esses documentos antigos não foram atualizados para refletir o comportamento atual? Talvez eu esteja entendendo mal o que está tentando me dizer? Ou há alguma pegadinha horrível esperando para me morder no futuro?
Antigo Blog de Adam Nathan Antigo Blog de Adam Nathan.
Por favor, visite adamnathan em vez disso!
Quiz: Gotcha com exceções e HRESULTs.
O código C # abaixo, quando executado, imprime o seguinte:
Quem pode descobrir por que a segunda linha impressa não é 0x80004003?
questionário de classe pública.
const int E_NOINTERFACE = desmarcado ((int) 0x80004002);
const int E_POINTER = desmarcado ((int) 0x80004003);
public static void Main ()
catch (exceção ex)
catch (exceção ex)
Cancelar resposta.
Bem, tanto E_NOINTERFACE e E_POINTER HRESULT são mapeados para uma exceção InvalidCast por ThrowExceptionForHR. Depois que uma exceção InvalidCast é lançada, o mesmo HRESULT será retornado de GetHRForException (eles são a mesma exceção nesse ponto).
O motivo pelo qual 0x8004002 é exibido nas duas vezes é que o objeto de erro não está sendo redefinido entre os dois blocos try / catch. antes do primeiro try / catch o objeto de erro associado ao thread lógico está vazio, depois que o valor HRESULT do try / catch do objeto de erro é definido como 0x8004002. Agora o segundo bloco try / catch é executado e o GetErrorInfo () é executado para definir o valor COMException. HRESULT para o valor do objeto de erro (que já está definido como 0x8004002), portanto, o valor COMException. HRESULT é definido como 0x8004002. Deixe-me ver se consigo criar um exemplo & # 8230;
Bem, eu pude demonstrar porque isso está acontecendo (veja o código abaixo). Eu inseri uma chamada para criar uma nova instância do Excel. ApplicationClass no servidor COM do Excel. Qualquer chamada entre apartamentos que utilize um proxy-stub ou qualquer chamada COM em um apartamento que use o loop de mensagem COM (STA) limpará o objeto de informação de erro. Assim, a chamada para o objeto COM do Excel entre as exceções capturadas irá limpar o objeto de informação de erro:
const int E_NOINTERFACE = desmarcado ((int) 0x80004002);
const int E_POINTER = desmarcado ((int) 0x80004003);
private Excel. Application _ExcelApplication = null;
Sim. Ovo está no meu rosto. Um teste simples provou que eu estava errado.
Interessante. No meu teste, eu também tentei Marshal. GetLastWin32Error após as funções TryInterface (), CallExcel () e TryPointer (), mas ele retornou 0. Eu também li em algum lugar que código gerenciado nunca deve chamar GetLastError () diretamente desde os resultados do GetLastError ( ) a chamada pode não ser precisa porque o CLR pode ter feito chamadas adicionais que modificariam o objeto de erro de encadeamento lógico.
Adam, você poderia dar algumas informações sobre como você encontrou esse bug / recurso?
Além disso, meu exemplo demonstrou o que está acontecendo ou há outra razão pela qual isso está acontecendo?
Eu não tenho muito a acrescentar, mas uma coisa que notei é que, em ambos os casos, o código está lançando a mesma instância da exceção. Além disso, se você lançar cada exceção em seu próprio thread, ele imprimirá o resultado esperado.
Muito boas observações, todos!
Normalmente, E_NOINTERFACE é mapeado para InvalidCastException e E_POINTER é mapeado para NullReferenceException. Mas, como Fernando destacou, ambas as exceções lançadas neste exemplo são InvalidCastException. Isso explica por que GetHRForException retorna E_NOINTERFACE nos dois casos, mas por que recebemos uma InvalidCastException duas vezes?
O ThrowExceptionForHR método lança uma exceção cujo tipo corresponde ao valor HRESULT de entrada (ou um COMException contendo o HRESULT se a entrada HRESULT isn & t; t na tabela de mapeamento do CLR). Mas ele faz mais do que isso: chama a API Win32 GetErrorInfo para tentar recuperar um objeto de erro disponível no thread atual. Ele usa essas informações para fornecer à exceção uma mensagem de erro personalizada, origem e assim por diante. ThrowExceptionForHR também tem uma sobrecarga com um segundo parâmetro System. IntPtr que representa um ponteiro para uma interface IErrorInfo, para que você possa passar essas informações diretamente. Passar IntPtr. Zero significa que você deseja que a API atue como a sobrecarga de parâmetro único (e chame GetErrorInfo), e passar -1 desabilita a recuperação extra de informações.
O GetHRForException método recupera o valor HRESULT para qualquer exceção gerenciada. Este é o valor do campo & quot; HResult & quot protegido &; propriedade, que você normalmente não pode acessar diretamente. Mas esse método tem um efeito colateral: ele chama a API Win32 SetErrorInfo, passando o CCW para exceção (que implementa IErrorInfo apropriadamente). Ele faz isso para facilitar a imitação do comportamento do empacotador ao expor manualmente uma exceção como um HRESULT e IErrorInfo para COM.
Neste exemplo, a primeira chamada para GetHRForException faz com que o CLR chame SetErrorInfo com o objeto InvalidCastException empacotado. Devido a isso, a segunda chamada para ThrowExceptionForHR pega essas informações quando ele chama GetErrorInfo, como Phil apontou. A razão pela qual isso afeta o tipo da exceção gerada & # 8211; apesar do fato de que IErrorInfo não tem um mecanismo para recuperar um HRESULT & # 8211; é que o CLR pode detectar quando o objeto de erro recuperado de SetErrorInfo é originado como uma exceção gerenciada e apenas reutilizar essa exceção original. Tudo isso significa que não importa o que HRESULT é passado para o método ThrowExceptionForHR a segunda vez (contanto que seja uma falha HRESULT), a exceção gerada é sempre um InvalidCastException.
Para obter o comportamento que você normalmente espera, você pode usar a sobrecarga de ThrowExceptionForHR que ignora IErrorInfo:
questionário de classe pública.
const int E_NOINTERFACE = desmarcado ((int) 0x80004002);
Marechal. Método GetHRForException (Exception)
A documentação de referência da API. NET tem uma nova página. Visite o Navegador da API. NET em docs. microsoft para ver a nova experiência.
Converte a exceção especificada para um HRESULT.
Assembly: mscorlib (em mscorlib. dll)
Parâmetros
A exceção para converter para um HRESULT.
Valor de retorno.
O HRESULT mapeado para a exceção fornecida.
GetHRForException também configura uma interface IErrorInfo para a exceção que pode ser obtida chamando a função COM GetErrorInfoNEEDGUID. Você pode usar essa função para retornar um valor HRESULT em uma implementação de classe gerenciada de uma interface COM onde você aplica o atributo PreserveSigAttribute. Ter o método atribuído capturar todas as exceções e use o método GetHRForException para retornar o valor HRESULT apropriado. Permitir que uma exceção se propague fora do método produz um comportamento incorreto. (Na verdade, o common language runtime não passa uma exceção para um cliente COM que chama esse método por meio de uma tabela v.)
Observe que o método GetHRForException define a interface IErrorInfo do thread atual. Isso pode causar resultados inesperados para métodos como os métodos ThrowExceptionForHR que usam o IErrorInfo do thread atual, se estiver definido.
requer confiança total para o chamador imediato. Este membro não pode ser usado pelo código parcialmente confiável ou transparente.
Комментарии
Отправить комментарий