Gethrforexception
Obter através da App Store Leia esta publicação em nosso aplicativo!
Chamando Marshal. GetHRForException em um ambiente de confiança parcial (SecurityPermission)
Eu tenho algum código IO que lê um fluxo dentro de uma tentativa. Ele captura IOException e chama System. Runtime. InteropServices. Marshal. GetHRForException () dentro da captura, na tentativa de tomar diferentes ações com base no HResult. Algo assim:
Mas executando este código dentro do ASP com confiança = "médio", recebo essa exceção:
Algumas dúvidas:
Eu acho que a exceção está ocorrendo porque GetHRForException chama em código não gerenciado, o que não é permitido na 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 estou 99% certo de que uma exceção de IO não ocorreu) Se assim for, existe uma maneira para eu variar o comportamento em um ambiente de confiança parcial, de modo que eu não ligue para o GetHRForException ( código não gerenciado) onde não é permitido? Em outras palavras, como posso permitir que o JIT seja bem sucedido no tempo de compilação, enquanto também avalia em tempo de execução se o código deve chamar GetHRForException ()? Algo assim:
Eu acho que há um mecanismo de tempo de execução para testar se as permissões estão disponíveis, mas não conseguiram encontrá-lo.
Gethrforexception
Obter através da App Store Leia esta publicação em nosso aplicativo!
Como determino o HResult para uma System. IO. IOException?
A propriedade System. Exception. HResult está protegida. Como posso espreitar dentro de uma exceção e obter o HResult sem recorrer a reflexão ou outros hacks feios?
Aqui está a situação:
Quero escrever uma ferramenta de backup, que abre e lê arquivos em um sistema. Abro o arquivo com FileAccess. Read e FileShare. ReadWrite, de acordo com esta orientação, porque não me importo se o arquivo está aberto para escrita no momento em que eu lê-lo.
Em alguns casos, quando um arquivo que estou lendo é aberto por outro aplicativo, o método System. IO. FileStream. Read () lança uma Sessão System. IO. IO, "O processo não pode acessar o arquivo porque outro processo bloqueou uma parte do o arquivo". Este é o erro 33, ou acho que o HResult 0x80070021. [EDIT: Eu acredito que isso pode ser retornado quando outro processo chama LockFileEx para bloquear um intervalo de bytes dentro de um arquivo.]
Eu gostaria de pausar e voltar a tentar quando eu recebo este erro. Penso que esta é a ação apropriada a seguir. Se o processo de bloqueio liberar o bloqueio do intervalo de bytes rapidamente, então eu posso continuar a ler o arquivo.
Como posso distinguir uma IOException por esse motivo, de outras? Posso pensar nessas maneiras:
Reflexão privada - não quero fazer isso. Perf vai maldito. chame Exception. ToString () e analise a string. Sinta-se mal-humorado. Não funcionará em versões i18n.
Não gosto dessas opções. Não existe uma maneira melhor e mais limpa?
Eu apenas procurei e encontrei System. Runtime. InteropServices. Marshal. GetHRForException. Será que isso retornará um uint como o 0x80070021?
Para Framework 4.5 e acima, você pode usar a propriedade Exception. HResult:
Para o que vale a pena, System. Exception. HResult não está mais protegido em 4.5 - apenas o setter está protegido. Isso não ajuda com o código que pode ser compilado com mais de uma versão do framework.
Você também pode usar a interface ISerializable:
A propriedade CanRead ajuda neste caso?
ou seja, ligue para CanRead, se isso retornar verdadeiro, ligue para Read ()
Você descreveu esses dois casos? Eu imagino que o método de reflexão não é tão lento, especialmente em relação a todos os outros trabalhos que sua aplicação estará fazendo e com que frequência essa exceção provavelmente ocorrerá.
Se for um gargalo, você pode procurar cache de algumas das operações de reflexão ou gerar IL dinâmico para recuperar a propriedade.
Gethrforexception
Permitir que uma exceção se propague fora do método produz um comportamento incorreto. (Na verdade, o tempo de execução da linguagem comum não pode passar uma exceção para um cliente COM chamando esse método através de uma tabela v).
Como eu removi todos os atributos PreserveSig de todos os meus métodos de interface e mudou-me para uma abordagem completamente baseada em exceções para minha biblioteca, isso seria ruim. Em meus objetos COM, eu uso "quitar" o tempo todo para enviar erros ao chamador (ambos gerenciados e não gerenciados) e ainda não vi um problema. Eu lanço uma COMException, e o HRESULT acaba na hora do chamador. Além disso, o cliente (não gerenciado) pode recuperar a interface IErrorInfo para receber o texto que eu lanço juntamente com o código de erro.
Esses documentos antigos que não foram atualizados para refletir o comportamento atual? Talvez eu esteja incompreendendo o que está tentando me dizer? Ou há algum ganho horrível esperando me morder no futuro, umm?
Todas as respostas.
É possível que sua informação esteja desatualizada aqui? Eu tentei ver as terríveis conseqüências que você está descrevendo, e isso simplesmente não está acontecendo. Aqui está o meu programa c ++:
hr = CoCreateInstance (stype, NULL, CLSCTX_INPROC_SERVER, IID_IMFTransform, (void **) & amp; it);
E aqui está o código para DeleteInputStream:
public void DeleteInputStream (int dwStreamID)
lance nova COMException (& quot; Removendo fluxos não suportados & quot; E_NotImplemented);
O HRESULT que recebo da chamada c ++ é E_NOTIMPL, como você esperaria. Eu perambulei através das configurações de c ++ e encontrei "Habilitar c ++ exceções & quot; e eu configurá-lo para "No." Ainda assim, acabei de voltar a hora que eu esperava. Não vi nada mais que se aplicasse.
E não, não estou compilando o programa c ++ com o suporte clr. Na verdade, aqui estão os conteúdos da "linha de comando" & quot; janela:
/ Od / D "WIN32" / D "_DEBUG" / D "_CONSOLE" / D "_UNICODE" / D "UNICODE" / Gm / RTC1 / MDd / Fo "Debug \\" quot; /Fd"Debug\vc80.pdb" / W3 / nologo / c / Wp64 / ZI / TP / erroReporte: prompt.
Apenas as suas opções básicas de compilação. Estou executando no Vista, mas não parece que isso valesse.
Talvez isso seja algo que mudou ao longo do tempo? Ou há alguma outra opção de compilação c ++ eu deveria desligar?
Desculpe, deveria ter adicionado a versão de framework que estou usando. A linha de comando que uso para registrar meu objeto COM é:
c: \ Windows \ Microsoft \ Framework \ v2.0.50727 \ regasm / tlb / codebase MFT_Grayscale. dll.
Ok, eu estava preocupada. Eu tinha retirado centenas de linhas de ", se SUCCEEDED & quot; codifique e exclua PreserveSig de centenas de métodos. Ter que colocar tudo de volta foi. assustador.
Obrigado por me deixar correr por você.
A Microsoft está conduzindo uma pesquisa on-line para entender sua opinião sobre o site da Msdn. Se você optar por participar, a pesquisa on-line será apresentada quando você deixar o site Msdn.
Blog do MSDN de Yi Zhang & # 039; Blog do MSDN de Yi Zhang & # 039; Blog do MSDN da MSDN.
Tudo sobre o CLR & # 8211; interop / WinRT / e outras coisas aleatórias.
Marshal. GetHRForException faz mais do que apenas Get-HR-For-Exception.
Comecemos primeiro a olhar para um pequeno trecho de código:
Isso parece perfeitamente bom, certo? Na verdade não. Acontece que esta API é realmente mal nomeada e, na verdade, faz mais do que apenas recuperar o RH do objeto de exceção. Usar esta API incorretamente pode dar-lhe alguns problemas estranhos, como, por exemplo, descartar uma exceção antiga incorreta.
Então, o que a API realmente faz?
Além de retornar o HRESULT, essa função também define o objeto atual do IErrorInfo para ser o objeto de exceção. Cada thread tem um objeto COM associado IErrorInfo, com o padrão para NULL. Este objeto IErrorInfo representa a falha da última chamada da API COM, que é como a API GetLastError () Win32 ou o errno C api. No objeto IErrorInfo, você pode obter mais informações, como a descrição do erro, o contexto do arquivo de ajuda, etc., que lhe dá mais informações sobre o erro. Ao configurar o objeto IErrorInfo no objeto de exceção (na verdade, configurando a implementação do objeto de exceção do IErrorInfo, que é compartilhada por todos os objetos gerenciados), você está dizendo essencialmente aos seus chamadores de COM, "ei", há uma falha, é esse objeto de exceção , e você deve fazer algo sobre isso ", o que obviamente é uma má idéia se você quiser apenas recuperar o RH.
Em muitos casos, isso pode passar despercebido, se o seu chamador / calle COM lidar com o IErrorInfo corretamente. Por "corretamente", quero dizer, eles seguem o protocolo COM IErrorInfo, que são basicamente:
1. O chamador usa IErrorInfo do segmento atual ao chamar uma interface COM que explicitamente diz "eu apoio o IErrorInfo & quot;
2. O destinatário (que implementa a interface COM) que diz "eu apoio o IErrorInfo", deve limpar / definir o IErrorInfo antes de retornar. Isso é muito semelhante ao GetLastError () / errno, certo?
Se for esse o caso, o IErrorInfo configurado incorretamente no tópico, normalmente, será substituído ou apagado por alguma implementação de interface que suporte o IErrorInfo ou seja ignorada.
No entanto, como o protocolo que descrevi não é muito bem compreendido por cada desenvolvedor COM, muitas vezes vi casos em que o componente COM apenas diz "claro", eu aceito IErrorInfo em cada interface COM e não configura / claro IErrorInfo em tudo. E então, o chamador desta interface COM mal implantada, acabaria usando o IErrorInfo configurado pela chamada GetHRForException anteriormente e levará a acreditar que existe um erro. Por exemplo, considere o seguinte cenário:
Xamarin.
System. Runtime. InteropServices. Marshal. GetHRForException Method.
Converte a exceção especificada em um HRESULT.
Parâmetros.
O HRESULT mapeado para a exceção fornecida.
Marshal. GetHRForException (Exception) 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 PreserveSigAttribute. Ter o método atribuído pegar todas as exceções e usar Marshal. GetHRForException (Exceção) para retornar o valor HRESULT apropriado. Permitir que uma exceção se propague fora do método produz um comportamento incorreto. (Na verdade, o tempo de execução da linguagem comum não consegue passar uma exceção para um cliente COM que chama esse método através de uma tabela v.)
Note que o método Marshal. GetHRForException (Exception) define o IErrorInfo do thread atual. Isso pode causar resultados inesperados para métodos como os métodos erload: System. Runtime. InteropServices. Marshal. ThrowExceptionForHR que padrão para usar o IErrorInfo do segmento atual se estiver configurado.
Requisitos.
Assembly: mscorlib (em mscorlib. dll)
Versões de montagem: 1.0.5000.0, 2.0.0.0, 4.0.0.0.
Namespace System. Runtime. InteropServices.
Estruturas.
Interfaces.
Enumerações.
Produtos Xamarin para Visual Studio Xamarin Test Cloud Xamarin Insights Xamarin University Xamarin Studio Visual Studio Xamarin. Forms Aplicações pré-construídas Mono Licensing Company Quem somos Clientes Parceiros Blog Empregos Prêmio Pricing Centro de desenvolvedores Começar Guias Recipes Xamarin. iOS APIs Xamarin. Android APIs Xamarin. Mac APIs Fóruns Vídeos Connect Developer Support Resources Consultoria Serviços Contato Vendas Twitter GitHub Stack Overflow Facebook Google+ YouTube.
Xamarin Inc., como uma subsidiária integral da Microsoft que atua como uma entidade jurídica separada, adere à Declaração de Privacidade da Microsoft: Privacidade e biscoitos.
Marshal. GetHRForException () sempre retorna 0 em plataformas não-Windows # 11144.
Akoeplinger comentou 25 de agosto de 2016 e # 8226;
Tome este exemplo de programa:
Quando executado no Windows, ele imprime "Valor: 123456". No OSX / Linux, ele imprime "Valor: 0".
0 parece ser o valor de retorno errado aqui, pois indicaria sucesso. O Mono atualmente retorna -1 em plataformas que não suportam interoperabilidade COM, mas estamos discutindo o que fazer, p. Ex. iOS uma vez que precisamos adicionar este método lá para conformidade com netstandard: bugzilla. xamarin / show_bug. cgi? id = 43646.
O problema é que algum código como o Serilog está usando este método (veja a publicação do Fórum Xamarin e o GitHub), então, lançar o PlatformNotSupportedException (o que adicionamos para todas essas API Marshal agora no iOS) não fará com que esse código funcione, e é por isso que eu ' Estou pensando em apenas mudá-lo para -1 também. Mas, idealmente, seríamos consistentes com Core :)
Qualquer razão por que você está retornando 0 em vez de -1 ou algum outro código genérico de erro?
stephentoub comentou 25 de agosto de 2016 e # 8226;
Akoeplinger comentou 25 de agosto de 2016.
ghuntley graemechristie fyi ^^. Eu não acho que Serilog deve estar confiando nessa API em plataformas que não são Windows, como atualmente, é pura sorte que funciona como está.
jkotas comentou 25 de agosto de 2016 e # 8226;
A exceção possui propriedade HResult. Marshal. GetHRForException deve apenas retornar isso em plataformas que não sejam do Windows. É o que ele (normalmente) retorna no Windows.
Observe que Marshal. GetHRForException no Windows também configura informações de erro de thread COM local, de modo que COM possa obter detalhes sobre a exceção uma vez que o HRESULT seja retornado a ele. Marshal. GetHRForException deve ser chamado apenas antes de retornar HRESULT para COM. O MSDN tem mais detalhes sobre isso.
jkotas adicionou um commit para jkotas / coreclr que referenciou este problema 25 de agosto de 2016.
Faça GetHRForException para retornar e. HResult em plataformas não-Windows # 6929.
jkotas adicionou um commit para jkotas / corefx que referenciou este problema 25 de agosto de 2016.
Adicione teste para Marshal. GetHRForException # 11168.
jkotas adicionou um commit para dotnet / coreclr que referenciou este problema 26 de agosto de 2016.
jkotas adicionou um commit para jkotas / corefx que referenciou este problema 26 de agosto de 2016.
ghuntley comentou 26 de agosto de 2016 e # 8226;
oh bom deus; consumir uma biblioteca de registro, acabar descobrindo um problema de implementação do BCL em mono / corefx para System. Runtime. InteropServices / mscorlib. Obrigado por consertar este jkotas, marek-safar / akoeplinger.
Não confie em HRESULTs para detectar arquivos de marcadores bloqueados # 33.
jkotas adicionou um commit que referenciou este problema 30 de agosto de 2016.
&cópia de; 2018 GitHub, Inc. Termos Privacidade Segurança Status Ajuda.
Você não pode executar essa ação neste momento.
Você fez login com outra guia ou janela. Recarregue para atualizar sua sessão. Você se separou em outra guia ou janela. Recarregue para atualizar sua sessão.
Obter através da App Store Leia esta publicação em nosso aplicativo!
Como determino o HResult para uma System. IO. IOException?
A propriedade System. Exception. HResult está protegida. Como posso espreitar dentro de uma exceção e obter o HResult sem recorrer a reflexão ou outros hacks feios?
Aqui está a situação:
Quero escrever uma ferramenta de backup, que abre e lê arquivos em um sistema. Abro o arquivo com FileAccess. Read e FileShare. ReadWrite, de acordo com esta orientação, porque não me importo se o arquivo está aberto para escrita no momento em que eu lê-lo.
Em alguns casos, quando um arquivo que estou lendo é aberto por outro aplicativo, o método System. IO. FileStream. Read () lança uma Sessão System. IO. IO, "O processo não pode acessar o arquivo porque outro processo bloqueou uma parte do o arquivo". Este é o erro 33, ou acho que o HResult 0x80070021. [EDIT: Eu acredito que isso pode ser retornado quando outro processo chama LockFileEx para bloquear um intervalo de bytes dentro de um arquivo.]
Eu gostaria de pausar e voltar a tentar quando eu recebo este erro. Penso que esta é a ação apropriada a seguir. Se o processo de bloqueio liberar o bloqueio do intervalo de bytes rapidamente, então eu posso continuar a ler o arquivo.
Como posso distinguir uma IOException por esse motivo, de outras? Posso pensar nessas maneiras:
Reflexão privada - não quero fazer isso. Perf vai maldito. chame Exception. ToString () e analise a string. Sinta-se mal-humorado. Não funcionará em versões i18n.
Não gosto dessas opções. Não existe uma maneira melhor e mais limpa?
Eu apenas procurei e encontrei System. Runtime. InteropServices. Marshal. GetHRForException. Será que isso retornará um uint como o 0x80070021?
Para Framework 4.5 e acima, você pode usar a propriedade Exception. HResult:
Para o que vale a pena, System. Exception. HResult não está mais protegido em 4.5 - apenas o setter está protegido. Isso não ajuda com o código que pode ser compilado com mais de uma versão do framework.
Você também pode usar a interface ISerializable:
A propriedade CanRead ajuda neste caso?
ou seja, ligue para CanRead, se isso retornar verdadeiro, ligue para Read ()
Você descreveu esses dois casos? Eu imagino que o método de reflexão não é tão lento, especialmente em relação a todos os outros trabalhos que sua aplicação estará fazendo e com que frequência essa exceção provavelmente ocorrerá.
Se for um gargalo, você pode procurar cache de algumas das operações de reflexão ou gerar IL dinâmico para recuperar a propriedade.
Comments
Post a Comment