Friday, 27 October 2017

Gethrforexception


Eu tenho algum código IO que lê um fluxo dentro de um try..catch. Ele captura IOException e chama System. Runtime. InteropServices. Marshal. GetHRForException () dentro do catch, em uma tentativa de tomar ações diferentes com base no HResult. Algo como isto: Mas executando este código no ASP. NET com o trustmedium, eu recebo esta exceção: Algumas perguntas: 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 de GetHRForException, mas no momento em que o método está sendo JITed - Correto (O stacktrace mostra meu método, mas tenho certeza de que uma exceção de IO não ocorreu) Existe uma maneira para mim variar o comportamento em um ambiente de confiança parcial, para que eu não chamar o GetHRForException (código não gerenciado) onde não é permitido Em outras palavras, como posso permitir que o JIT para ter sucesso na compilação, enquanto também Avaliando em tempo de execução se o código deve chamar GetHRForException () Algo como isto: Eu acho que há um mecanismo de tempo de execução para testar se as permissões estão disponíveis, mas havent sido capaz de encontrá-lo. EDIT. É este artigo de blog a resposta ShawnFa da Microsoft diz que você não pode fazer uma tentativa. Catch (SecurityException) em torno de um método protegido por um LinkDemand. Se MethodA () chama MethodB (), e MethodB () é marcado com LinkDemand para confiança total, em seguida, o LinkDemand é verificado com MethodA é Jited. Portanto, para evitar a SecurityException, preciso extrair Marshal. GetHRForException em um método separado. É isso correto Aplicado ao meu código, MethodA () pode ser o código que chama Read e, em seguida, na captura tenta chamar GetHRForException (). GetHRForException é MethodB (). O LinkDemand é avaliado quando MethodA () é JITd. (Este LinkDemand falha no meu cenário de médio-confiança ASP. NET). Se eu mover o GetHRForException em um novo método, MethodC () e condicionalmente chamar MethodC () somente após uma permissão imperativa. Demand () bem-sucedida, teoricamente eu deveria ser capaz de evitar o SecurityException no tempo JIT, porque MethodC () será JITd somente após a permissão. Demain () tiver êxito. Pediu Jul 12 09 at 14:20 O método necessário é SecurityPermission. IsUnrestricted (). Retorna um verdadeiro ou falso indicando se a permissão é permitida ou não. Ele não exige uma permissão, como faz SecurityPermission. Demand (). Eu uso IsUnresticted com SecurityPermissionFlag. UnmanagedCode para ver se o assembly é permitido chamar código não gerenciado e, em seguida, chamar o código 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 my o método a ser compilado. Marshal. GetHRForException () é marcado com um LinkDemand. Assim, meu método que chama Marshal. GetHRForException () irá lançar uma excepção de segurança uncatchable no momento da compilação JIT, quando executado em um ambiente restrito, como ASP. NET com confiança média. Portanto, nunca devemos JIT o método que chama Marshal. GetHRForException () nesse caso, o que significa que eu preciso para quebrar Marshal. GetHRForException () em um método separado no meu código que é chamado (e assim JITted) apenas quando UnmanagedCode é Sem restrições. Heres algum código de exemplo: respondeu Jul 20 09 at 17:56 Sim - confiança médio não permitirá chamadas em código não gerenciado. O único nível de confiança que o permite é a confiança total. Depende. As demandas de CAS podem ocorrer em tempo de execução, mas o ambiente de hospedagem também pode ir em um vagar e procurar coisas que não podem fazer. Você pode testar para ver se você pode fazer uma chamada para código não gerenciado usando uma demanda CAS com uma instância de SecurityPermission. O código para fazer uma demanda CAS parece com isso respondido Jul 12 09 at 14:32 OK, esta é a grande informação. Isso abrange a parte b da Q3. Mas e sobre a parte a Como faço para obter a compilação JIT para ter sucesso Posso marcar o meu método com um atributo de segurança ou. Lembre-se, minha teoria é que o erro SecurityPermission não está acontecendo em tempo de execução, ele está acontecendo durante JIT - e eu acho que você confirmou que isso é possível. 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 Deve estar acontecendo em 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 a permissão. Mesmo então isso é provavelmente uma verificação de tempo de execução, como acontecerá na carga de montagem, que poderia estar em tempo de execução. Ndash blowdart Jul 12 09 at 16:24 Diferentes tipos de verificação, as demandas de link são atributos em um método, e são de fato verificadas no tempo JIT. Ele é muito usado pela própria estrutura e é raro vê-lo fora da fonte CLR. O que eu demonstro é uma demanda imperativa, não declarativa como um SecurityPermission (SecurityAction. LinkDemand, Unrestricted true) ndash blowdart Jul 12 09 at 18: 55Marshal. GetHRForException faz mais do que apenas Get-HR-For-Exception Let8217s começar pela primeira vez procurando Em um pequeno fragmento de código: Isso parece perfeitamente bem, certo Não realmente. Acontece que esta API é realmente mal nomeado, e ele realmente faz mais do que apenas recuperar o HR do objeto de exceção. Usando esta API incorretamente poderia lhe dar alguns problemas estranhos, como lançar fora uma exceção, incorreta antigos. Então, o que a API realmente faz? Além de retornar o HRESULT, essa função também define o objeto thread IErrorInfo atual para ser o objeto de exceção. Cada thread tem um objeto COM IErrorInfo associado, defaulting para NULL. Este objeto IErrorInfo representa a falha da última chamada API COM, que é tipo de como GetLastError () Win32 API, ou errno C api. A partir do objeto IErrorInfo, você pode obter mais informações, como a descrição do erro, contexto do arquivo de ajuda, etc, que fornece mais informações sobre o erro. Ao definir IErrorInfo objeto para o objeto de exceção (na verdade configuração para a implementação IErrorInfo do objeto de exceção, que é compartilhado por todos os objetos gerenciados), que são essencialmente dizendo a seu interlocutor COM, quothey, há uma falha, it8217s este objeto de exceção, e Você deve fazer algo sobre itquot, que é obviamente uma má idéia se você só deseja recuperar o HR. Em muitos casos, isso poderia passar despercebido, se o chamador / callee COM manipula IErrorInfo corretamente. Por quotcorrectlyquot, quero dizer que eles seguem o protocolo COM IErrorInfo, que são basicamente: 1. O chamador usar IErrorInfo do segmento atual ao chamar uma interface COM que explicily diz que o apoio quotI IErrorInfoquot 2. O receptor (que implementa a interface COM) que diz QuotI suporte IErrorInfoquot, deve limpar / definir IErrorInfo antes de retornar. Isto é muito semelhante ao GetLastError () / errno, certo Se este for o caso, o definido incorretamente IErrorInfo no segmento, normalmente quer ser substituído / desmarcada por alguns implementação de interface que suporta IErrorInfo, ou ignorado. No entanto, porque o protocolo que eu descrevi na verdade não é muito bem compreendida por todos os desenvolvedores COM, I8217ve muitas vezes visto casos em que o componente COM apenas dizem quotsure, apoio IErrorInfo em cada interfacequot COM, e eles don8217t set / clara IErrorInfo em tudo. E, em seguida, o chamador dessa interface COM mal implantado, acabaria usando o IErrorInfo definido por GetHRForException chamar mais cedo e é levar a acreditar que há um erro. Por exemplo, let8217s considere o seguinte cenário: Algum componente COM A chama em código. NET código. NET lançar uma exceção, dizem código IOException. NET captura a exceção, e chamar Marshal. GetHRForException, que define IErrorInfo a essa exceção código IOException. NET põe em outro componente COM B, põe em IB. Func IB. Func falhou e retornar algum código de falha HR, dizem EOUTOFMEMORY CLR vê o código de falha de RH, e pedir o componente COM B quotdo-lhe apoio IErrorInfoquot e B responde quotsure, por notquot , exceto que doesn8217t realmente apoiá-lo e doesn8217t set / clara IErrorInfo CLR recuperar o IErrorInfo, e vê que é realmente uma exceção gerenciada, e joga fora a exceção IOException em vez de OutOfMemoryException. Agora, você pode estar se perguntando: O que é realmente essa API destinada para, em primeiro lugar É realmente usado em locais em interoperabilidade COM, onde você deseja retornar o HRESULT e definir IErrorInfo por si mesmo. Isso não acontece muitas vezes 8211 a maioria das pessoas seria feliz o suficiente para permitir que a interoperabilidade COM cuida dessa parte, convertendo Exception para HR e IErrorInfo (o que, acontece chamar Marshal. GetHRForException). Então, a menos que você realmente saiba o que está fazendo, meu conselho é ficar longe de Marshal. GetHRForException. E se você realmente, realmente quiser apenas obter o HRESULT para uma exceção específica Você deve usar propriedade Exception. HResult. Permitir uma exceção para propagar fora do método produz comportamento incorreto. (Na verdade, o common language runtime falha ao passar uma exceção para um cliente COM chamando esse método através de uma tabela v.) Desde que eu removi todos os atributos PreserveSig de todos os meus métodos de interface e mudaram para um completamente baseado em exceção Abordagem para a minha biblioteca, isso seria ruim. Em meus objetos COM, eu uso quotthrowquot o tempo todo para enviar de volta erros para o chamador (gerenciado e não gerenciado) e eu ainda não vi um problema. Eu lanço uma COMException, eo HRESULT acaba na chamada hr. O que é mais, o cliente (não gerenciado) pode recuperar a interface IErrorInfo para receber o texto que eu jogar juntamente com o código de erro. São estes documentos antigos que não foram atualizados para refletir o comportamento atual Talvez Im incompreensão o que está tentando me dizer Ou há algum horrível gotcha esperando para me morder no umm, futuro Sexta-feira, 20 de julho de 2007 2:44 Respostas Ok , Eu poderia ter exagerado o quotsinquot bit aqui. Eu me concentrei muito em deixar exceções C escape fora da chamada de método COM. O que na verdade era um pecado nos dias não gerenciados, há muito tempo para mim. O fato de que ele funciona é bastante convincente evidência de que o wrapper CCW está captando COMException e gerando o valor de retorno HRESULT a partir disso. É provavelmente maior do que isso, Id imagine que pega Exceção e chama Marshal. GetHRForException método automaticamente. Teria que, não há nenhuma maneira que um cliente COM poderia pegar uma exceção gerenciada. Id dizer que você é bom para ir, desculpe a confusão. A documentação pode ser um pouco mais apertado aqui. Sábado, 21 de julho de 2007 21:27 Todas as respostas Sim, você está cometendo um grande pecado. Você está esperando o cliente COM para capturar a exceção gerenciada. Isso vai falhar miseravelmente quando o cliente não é um aplicativo gerenciado e irá encerrar o cliente. COMException é somente para uso pelo run-time. Você deve retornar falhas por meio do valor de retorno HRESULT. Eles, por sua vez tipicamente gerar exceções no cliente (como COMException em um aplicativo gerenciado). Estou surpreso sua abordagem funciona em tudo. Alguns clientes COM instalam um manipulador de exceção SEH para interceptar exceções assíncronas (divisão por zero, estouro de pilha, acesso à memória inválido, coisas assim). Talvez ele funciona porque esse manipulador intercepta o COMException. Mas isso é um detalhe de implementação do cliente. C clientes para um quase nunca fazer isso. Sábado, 21 de julho de 2007 18:28 throw novo COMException (quotRemoving córregos não suportados. EnotImplemented) O HRESULT I get da chamada c é ENOTIMPL, como seria de esperar. Eu vaguei pelas configurações de c, e encontrei quotEnable c exceptionsquot e eu defini-lo para quotNo. quot Ainda assim, acabei de voltar a hora que eu esperava. Didnt ver qualquer outra coisa que aplicam. E não, eu não estou compilando o programa c com suporte clr. Na verdade, aqui está o conteúdo da janela do quotcommand linequot: / Od / D quotWIN32quot / D quotDEBUGquot / D quotCONSOLEquot / D quotUNICODEquot / D quotUNICODEquot / Gm / RTC1 / MDd / FoquotDebugquot /FdquotDebugvc80.pdbquot / W3 / nologo / c / Wp64 / ZI / TP / errorReport: prompt Apenas suas opções básicas de compilação. Estou executando no Vista, mas não parece que isso deve importar. Talvez isso é algo que mudou ao longo do tempo Ou há alguma outra opção de compilação c Eu deveria desligar Ok, eu poderia ter exagerado o quotsinquot bit aqui. Eu me concentrei muito em deixar exceções C escape fora da chamada de método COM. O que na verdade era um pecado nos dias não gerenciados, há muito tempo para mim. O fato de que ele funciona é bastante convincente evidência de que o wrapper CCW está captando COMException e gerando o valor de retorno HRESULT a partir disso. É provavelmente maior do que isso, Id imagine que pega Exceção e chama Marshal. GetHRForException método automaticamente. Teria que, não há nenhuma maneira que um cliente COM poderia pegar uma exceção gerenciada. Id dizer que você é bom para ir, desculpe a confusão. A documentação pode ser um pouco mais apertado aqui. Sábado, 21 de julho de 2007 21:27 Ok, eu estava preocupado. Eu tinha puxado para fora centenas de linhas do código do quotif SUCCEEDEDquot e suprimido PreserveSig das centenas dos métodos. Ter que colocar tudo de volta foi. Assustador Obrigado por me deixar passar este passado. Sábado, 21 de julho de 2007 21h50 Microsoft está conduzindo uma pesquisa on-line para entender sua opinião sobre o site da Msdn. Se você optar por participar, o questionário on-line será apresentado a você quando você deixar o site Msdn. Você gostaria de participar

No comments:

Post a Comment