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. NET com confiança, recebo esta exceção: algumas dúvidas: acho que a exceção está ocorrendo porque o GetHRForException invoca 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 JITADO - Corrigido (O stacktrace mostra meu método, mas tenho 99 certeza 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 ligo o GetHRForException (código não gerenciado) onde ele não é permitido. Em outras palavras, como posso permitir que o JIT seja bem-sucedido no tempo de compilação, enquanto também Avaliando no 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 não conseguiu encontrá-lo. EDITAR. 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 () estiver marcado com LinkDemand para confiança total, o LinkDemand é verificado com MethodA is Jited. Portanto, para evitar o SecurityException, preciso extrair Marshal. GetHRForException para um método separado. Isso é correto Aplicado ao meu código, MethodA () pode ser o código que chama Leitura e, em seguida, na tentativa tenta chamar GetHRForException (). GetHRForException é MethodB (). O LinkDemand é avaliado quando MethodA () é JITd. (Este LinkDemand falha no meu cenário ASP. NET de confiança média). Se eu mover o GetHRForException para um novo método, MethodC () e condicionalmente chamar MethodC () somente após uma permissão imperativa. Dandand (), ele deve teoricamente evitar o SecurityException no JIT, porque MethodC () será JITd somente após a permissão. Demain () é bem-sucedido. Perguntou Jul 12 09 às 14:20 O método necessário é SecurityPermission. IsUrestratado (). Retorna um verdadeiro ou falso indicando se a permissão é permitida ou não. Não exige uma permissão, assim como o SecurityPermission. Demand (). Eu uso IsUnresticted com SecurityPermissionFlag. UnmanagedCode para ver se o assembly pode chamar o código não gerenciado e, em seguida, chamar o código não gerenciado somente se permitido. Há um toque adicional. O compilador JIT, ao compilar um método, verifica CodeAccessPermission LinkDemands em qualquer método chamado meu o método a ser compilado. Marshal. GetHRForException () é marcado com um LinkDemand. Por isso, meu método que chama Marshal. GetHRForException () lançará uma SecurityException insatisfatória no momento da compilação JIT, quando executado em um ambiente restrito, como o 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 quebrar Marshal. GetHRForException () em um método separado no meu código que é chamado (e, portanto, JITted) somente quando UnmanagedCode é Irrestrito. Heres algum código de exemplo: respondeu Jul 20 09 às 17:56 Sim - confiança média não permitirá chamadas em código não gerenciado. O único nível de confiança que o permite é confiança total. Depende. As exigências de CAS podem ocorrer no tempo de execução, mas o ambiente de hospedagem também pode andar e procurar coisas que não pode fazer. Você pode testar para ver se você pode fazer uma chamada para código não gerenciado usando uma demanda de CAS com uma instância de SecurityPermission. O código para fazer uma demanda do CAS parece que isso foi respondido 12 de julho 09 às 14:32 OK, esta é uma ótima informação. Isso abrange a parte b do Q3. E quanto a parte de como faço para obter a compilação JIT para ter sucesso Posso marcar meu método com um atributo de segurança ou. Lembre-se, minha teoria é que o erro SecurityPermission não está ocorrendo no tempo de execução, está acontecendo durante o JIT - e 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 12 de julho de 09 às 15:50 Isso deveria estar acontecendo no tempo de execução, caso contrário, a montagem não seria mesmo carregada - e para que isso aconteça, a montagem precisa ser marcada como exigindo a permissão. Mesmo assim, esse é, sem dúvida, uma verificação de tempo de execução, pois isso ocorrerá na carga de montagem, que pode ser em tempo de execução. Ndash blowdart 12 de julho de 09 às 16:24 O tipo diferente de verificação, as demandas de links são atributos em um método e, de fato, são verificadas no tempo JIT. É muito usado pela própria estrutura e é raro vê-lo fora da fonte CLR. O que eu demonstro é uma demanda imperativa, e não uma declarativa como uma SecurityPermission (SecurityAction. LinkDemand, Unrestricted true) ndash blowdart Jul 12 09 em 18: 55Marshal. GetHRForException faz mais do que apenas Get-HR-For-Exception Let8217s primeiro comece olhando Em um pequeno trecho de código: isso parece perfeitamente bom, certo, não realmente. 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 IErrorInfo do segmento atual como 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 GetLastError () Win32 API 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. Configurando o objeto IErrorInfo para o 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 COM, quotey, há uma falha, it8217s 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 callercallee COM lidar com o IErrorInfo corretamente. Por quotcorrectlyquot, quero dizer, eles seguem o protocolo COM IErrorInfo, que são basicamente: 1. O chamador usa IErrorInfo do tópico atual ao chamar uma interface COM que explicitamente diz que o suporte ao IErrorInfoquot 2. O destinatário (que implementa a interface COM) que diz Quero apoio IErrorInfoquot, deve limpar IErrorInfo antes de retornar. Isso é muito semelhante ao GetLastError () errno, direito Se este for o caso, o IErrorInfo configurado incorretamente no tópico, normalmente seria substituído por alguma implementação de interface que suporte o IErrorInfo ou seja ignorada. No entanto, porque o protocolo que descrevi não é muito bem compreendido por cada desenvolvedor COM, I8217ve casos frequentemente vistos em que o componente COM apenas diz quotsure, eu apoio o IErrorInfo em cada interface COM e eles não definem o IErrorInfo. 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, let8217s consideram o seguinte cenário: Algumas partes do componente COM invocam o código. NET do. NET. Lança uma exceção, diz que o código IOException. NET captura a exceção e chama Marshal. GetHRForException, que define o IErrorInfo para esta exceção do código IOException. NET Chamadas para outro componente COM B, chamadas para IB. Func IB. Func falhou e retornar algum código de falha de RH, diga que EOUTOFMEMORY CLR vê o código de falha de HR e peça ao componente COM B quotdo você apoia IErrorInfoquot e B responde quotsure, porque não , Exceto que ele realmente não o aceita e ele não define o IErrorInfo CLR recuperar o IErrorInfo e vê que ele é realmente uma exceção gerenciada e lança a exceção IOException em vez de OutOfMemoryException. Agora, você pode estar se perguntando: Para o que esta API realmente se destina, em primeiro lugar, é realmente usado em lugares no interoperabilidade COM, onde você deseja retornar o HRESULT e definir o IErrorInfo sozinho. Isso não ocorre muito frequentemente. A maioria das pessoas ficaria feliz o suficiente para permitir que a interoperabilidade COM cuide dessa parte, convertendo Exception para HR e IErrorInfo (o que, por acaso, chama 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 quiser realmente obter o HRESULT para uma Exceção específica, você deve usar a propriedade Exception. HResult.
No comments:
Post a Comment