我有一些 IO 代码可以读取 try..catch 中的流。它捕获 IOException 并在捕获中调用System.Runtime.InteropServices.Marshal.GetHRForException() ,以尝试根据 HResult 采取不同的操作。像这样的东西:
try
{
stream.Read(...);
}
catch (IOException ioexc1)
{
uint hr = (uint) Marshal.GetHRForException(ioexc1);
if (hr == ...)
do_one_thing();
else
do_another();
}
该程序集使用AllowPartiallyTrustedCallersAttribute进行签名和标记。
但是在 ASP.NET 中使用 trust="medium" 运行这段代码,我得到了这个异常:
Request for the permission of type 'System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
几个问题:
- 我认为发生异常是因为 GetHRForException 调用了非托管代码,这在中等信任中是不允许的。正确的?
- 抛出此异常,不是在执行 GetHRForException 时,而是在方法被 JIT 处理时 - 对吗?(堆栈跟踪显示了我的方法,但我 99% 确定没有发生 IO 异常)
- 如果是这样,有没有办法让我改变部分信任环境中的行为,这样我就不会在不允许的地方调用 GetHRForException (非托管代码)?换句话说,如何让 JIT 在编译时成功,同时在运行时评估代码是否应该调用 GetHRForException()?像这样的东西:
catch (IOException ioexc1)
{
if (!OkToCallUnmanaged())
throw ioexc1;
uint hr = (uint) Marshal.GetHRForException(ioexc1);
if (hr == ...)
do_one_thing();
else
do_another();
}
我认为有一个运行时机制来测试权限是否可用,但一直找不到。
编辑:这篇博客文章是答案吗?微软的 ShawnFa 说你不能在一个受 LinkDemand 保护的方法周围做一个 try ... catch(SecurityException)。如果 MethodA() 调用 MethodB(),并且 MethodB() 用 LinkDemand 标记为完全信任,则使用 MethodA 检查 LinkDemand is Jit'ed。因此,为了避免 SecurityException,我需要将 Marshal.GetHRForException 提取到一个单独的方法中。那是对的吗?
应用于我的代码,MethodA() 可能是调用 Read 的代码,然后在 catch 中尝试调用 GetHRForException()。GetHRForException 是 MethodB()。当 MethodA() 为 JIT 时评估 LinkDemand。(此 LinkDemand 在我的中等信任 ASP.NET 方案中失败)。如果我将 GetHRForException 移动到一个新方法 MethodC() 中,并且仅在命令式 permission.Demand() 成功后有条件地调用 MethodC(),理论上我应该能够在 JIT 时间避免 SecurityException,因为 MethodC() 将只有在 permission.Demain() 成功后才会进行 JIT。