Wednesday 25 January 2017

Gethrforexception

J'ai un code IO qui lit un flux dans un try..catch. Il attrape IOException et appelle System. Runtime. InteropServices. Marshal. GetHRForException () dans le catch, dans une tentative de prendre différentes actions basées sur le HResult. Quelque chose comme ceci: Mais en exécutant ce code dans ASP. NET avec trustmedium, je reçois cette exception: Quelques questions: Je pense que l'exception se produit parce que GetHRForException appelle dans le code non géré, ce qui n'est pas permis dans la confiance moyenne. Correct Cette exception est lancée, pas au moment de l'exécution de GetHRForException, mais au moment où la méthode est JITed - Correct (Le stacktrace montre ma méthode, mais je suis certain qu'une exception IO n'a pas eu lieu). Si oui, Est-il un moyen pour moi de varier le comportement dans un environnement de confiance partielle, de sorte que je n'appelez pas le GetHRForException (code non géré) où il n'est pas permis En d'autres termes, comment puis-je permettre au JIT de réussir à la compilation, Évaluer au moment de l'exécution si le code doit appeler GetHRForException () quelque chose comme ceci: Je pense qu'il ya un mécanisme d'exécution pour tester si les autorisations sont disponibles, mais havent été en mesure de le trouver. MODIFIER . Est cet article de blog la réponse ShawnFa de Microsoft dit que vous ne pouvez pas faire un essai. Catch (SecurityException) autour d'une méthode protégée par un LinkDemand. Si MethodA () appelle MethodB () et MethodB () est marqué avec LinkDemand pour la confiance totale, puis le LinkDemand est vérifié avec MethodA est Jited. Par conséquent, pour éviter la SecurityException, je dois extraire Marshal. GetHRForException dans une méthode distincte. Est-ce correct Appliqué à mon code, MethodA () pourrait être le code qui appelle Read, et puis dans le catch essaie d'appeler GetHRForException (). GetHRForException est MethodB (). Le LinkDemand est évalué lorsque MethodA () est JITd. (Ce LinkDemand échoue dans mon scénario ASP. NET de confiance moyenne). Si je déplace la GetHRForException dans une nouvelle méthode, MethodC (), et conditionnellement appeler MethodC () seulement après un imperatif permission. Demand () réussit, théoriquement je devrais être capable d'éviter la SecurityException à JIT time, parce que MethodC () JITd seulement après l'autorisation. Demain () réussit. Demandé Jul 12 09 at 14:20 La méthode requise est SecurityPermission. IsUnrestricted (). Il retourne un vrai ou un faux indiquant si l'autorisation est autorisée ou non. Il n'exige pas une autorisation, comme le fait SecurityPermission. Demand (). J'utilise IsUnresticted avec SecurityPermissionFlag. UnmanagedCode pour voir si l'assembly est autorisé à appeler le code non géré et puis appeler le code non managé uniquement si autorisé. Il ya une autre torsion. Le compilateur JIT, lors de la compilation d'une méthode, vérifie pour LinkAccessPermission LinkDemands sur toute méthode appelée ma méthode à compiler. Marshal. GetHRForException () est marqué avec un LinkDemand. Par conséquent, ma méthode qui appelle Marshal. GetHRForException () lancera une exception SecurityException uncatchable au moment de la compilation JIT, lorsqu'elle est exécutée dans un environnement restreint, comme ASP. NET avec confiance moyenne. Par conséquent, nous ne devons jamais JIT la méthode qui appelle Marshal. GetHRForException () dans ce cas, ce qui signifie que j'ai besoin de sortir Marshal. GetHRForException () dans une méthode distincte dans mon code qui est appelé (et donc JITted) seulement lorsque UnmanagedCode est libre. Voici un exemple de code: répondu Jul 20 09 at 17:56 Oui - la confiance moyenne ne permettra pas les appels dans le code non géré. Le seul niveau de confiance qui le permet est la pleine confiance. Ça dépend. Les demandes CAS peuvent avoir lieu à l'exécution, mais l'environnement d'hébergement peut également se promener et chercher des choses qu'il ne peut pas faire. Vous pouvez tester pour voir si vous pouvez faire un appel au code non géré en utilisant une demande CAS avec une instance de SecurityPermission. Le code pour faire une demande CAS ressemble à ceci a répondu Jul 12 09 at 14:32 OK, c'est une excellente info. Cela couvre la partie b du Q3. Mais que dire de la partie a Comment puis-je obtenir la compilation JIT pour réussir Puis-je marquer ma méthode avec un attribut de sécurité ou. Rappelez-vous, ma théorie est que l'erreur SecurityPermission ne se produit pas à l'exécution, il se passe pendant JIT - et je pense que vous avez confirmé que c'est possible. La question est donc de savoir comment écrire le code pour permettre au JIT de compiler. Ndash Cheeso Jul 12 09 at 15:50 Cela devrait se produire au moment de l'exécution, sinon l'assemblage ne serait même pas chargé - et pour que cela se produise l'assemblage doit être marqué comme nécessitant l'autorisation. Même alors cela pourrait être une vérification d'exécution, comme cela se produira sur la charge d'assemblage, qui pourrait être à l'exécution. Ndash blowdart Jul 12 09 at 16:24 Différent type de contrôle, les exigences de lien sont des attributs sur une méthode, et sont effectivement vérifiés à JIT temps. Il est assez utilisé par le cadre lui-même et il est rare de le voir en dehors de la source CLR. Ce que je démontre est une demande impérative, pas un déclaratif comme un SecurityPermission (SecurityAction. LinkDemand, Unrestricted true) ndash blowdart Jul 12 09 à 18: 55Marshal. GetHRForException fait plus que juste Get-HR-For-Exception Let8217s commencer par regarder À un petit extrait de code: Cela semble parfaitement bien, droit Pas vraiment. Il s'avère que cette API est en fait mal nommé, et il ne fait plus que simplement récupérer le HR de l'objet d'exception. L'utilisation incorrecte de cette API pourrait vous donner quelques problèmes bizarres, comme jeter une exception incorrecte, ancienne. Donc ce que l'API fait réellement Outre le fait de vous renvoyer le HRESULT, cette fonction définit également l'objet IErrorInfo thread actuel pour être l'objet d'exception. Chaque thread a un objet COM IErrorInfo associé, par défaut à NULL. Cet objet IErrorInfo représente l'échec du dernier appel de l'API COM, qui ressemble en quelque sorte à l'API Win32 de GetLastError () ou à l'api de errno C. À partir de l'objet IErrorInfo, vous pouvez obtenir plus d'informations telles que la description de l'erreur, le contexte du fichier d'aide, etc., qui vous donne plus d'informations sur l'erreur. En définissant IErrorInfo objet à l'objet d'exception (en fait le paramètre à l'IErrorInfo implémentation de l'objet d'exception, qui est partagé par tous les objets gérés), vous êtes essentiellement dire à vos appelants COM, quothy, il ya un échec, it8217s cet objet d'exception et Vous devriez faire quelque chose à ce sujet, ce qui est évidemment une mauvaise idée si vous voulez seulement récupérer le HR. Dans de nombreux cas, cela pourrait passer inaperçu, si votre COM callercallee gère IErrorInfo correctement. Par quotcorrectlyquot, je veux dire qu'ils suivent le protocole COM IErrorInfo, qui sont fondamentalement: 1. L'appelant utiliser IErrorInfo du thread actuel lors de l'appel d'une interface COM qui dit explicitement quotI support IErrorInfoquot 2. L'appelé (qui implémente l'interface COM) qui dit QuotI support IErrorInfoquot, doit clearset IErrorInfo avant de revenir. Ceci est très similaire à GetLastError () errno, right Si c'est le cas, le IErrorInfo incorrectement défini dans le thread, serait généralement soit overwrittencleared par une implémentation d'interface qui supporte IErrorInfo, ou ignoré. Toutefois, parce que le protocole que j'ai décrit n'est en fait pas très bien compris par chaque développeur COM, I8217ve souvent vu cas où le composant COM dire quotsure, je soutiens IErrorInfo sur chaque interface COM, et ils don8217t setclear IErrorInfo à tous. Et puis, l'appelant de cette interface mal implémentée COM, finirait par utiliser l'IErrorInfo mis par GetHRForException appel plus tôt, et est conduit à croire qu'il ya une erreur. Par exemple, let8217s envisager le scénario suivant: Certains composant COM appelle dans le code. NET. NET code jeter une exception, disons IOException. NET code capte l'exception et appelez Marshal. GetHRForException, qui définit IErrorInfo à cette exception IOException. NET code Appelle dans un autre composant COM B, les appels dans IB. Func IB. Func a échoué et retourner un code d'échec de ressources, disons EOUTOFMEMORY CLR voit le code d'échec de ressources humaines, et demandez le composant COM B quotdo vous soutenez IErrorInfoquot, et B quotsure réponses, pourquoi notquot , Sauf qu'il doesn8217t vraiment le soutenir et il doesn8217t setclear IErrorInfo CLR récupérer le IErrorInfo, et voit que c'est en fait une exception gérée, et jette l'exception IOException au lieu de OutOfMemoryException. Maintenant, vous pourriez vous demander: Qu'est-ce que cette API est vraiment destiné à la première place Il est effectivement utilisé dans les endroits dans interop COM, où vous voulez retourner le HRESULT et IErrorInfo set par vous-même. Ce doesn8217t arrive très souvent 8211 la plupart des gens seraient heureux de laisser COM interop prend soin de cette partie en convertissant Exception à HR et IErrorInfo (qui, arrive à appeler Marshal. GetHRForException). Donc, à moins que vous ne sachiez vraiment ce que vous faites, mon conseil est de rester loin de Marshal. GetHRForException. Que faire si vous voulez vraiment obtenir le HRESULT pour une exception spécifique Vous devez utiliser la propriété Exception. HResult.


No comments:

Post a Comment