当面向.NET Framework的代码调用某些方法时,Windows PowerShell、其他动态语言和动态执行的 C# 代码中的异常

应用对象
Windows Vista Service Pack 2 Windows 7 Service Pack 1 Windows Server 2008 Service Pack 2 Windows Server 2008 R2 Service Pack 1 Windows 8 Windows Server 2012 Datacenter Windows Server 2012 Datacenter Windows Server 2012 Essentials Windows Server 2012 Foundation Windows Server 2012 Foundation Windows Server 2012 Standard Windows Server 2012 Standard Windows Server 2012 R2 Datacenter Windows Server 2012 R2 Essentials Windows Server 2012 R2 Foundation Windows Server 2012 R2 Standard Windows 8.1

症状

当面向 Microsoft .NET Framework 4.5.1 或 Microsoft .NET Framework 4.5.2 的代码动态绑定到方法 (时,例如,使用 Windows PowerShell、IronPython、IronRuby 或其他动态语言中的脚本) 调用 System.Runtime.InteropServices.Marshal.SizeOf 方法或System.Runtime.InteropServices.Marshal.PtrToStructure 方法可能会遇到以下问题。

注意 已编译为托管可执行文件的代码不会显示这些问题,除非该代码使用 C# 中的动态关键字 (keyword) 。

问题 1

对 System.Runtime.InteropServices.Marshal.SizeOf 的调用将引发以下 MethodInvocationException 异常:

注意

类型“类型名称>”<不能作为非托管结构进行封送;无法计算有意义的大小或偏移量。

问题 2

对 System.Runtime.InteropServices.Marshal.PtrToStructure 的调用将引发以下 MethodInvocationException 异常:

注意

指定的结构必须是 blittable 或具有布局信息。

          

问题 3

对 System.Runtime.InteropServices.Marshal.PtrToStructure 的调用将引发以下 RuntimeBinderException 异常:

注意

无法将类型“void”隐式转换为“object”。

          

原因

出现此问题的原因是脚本引擎和动态语言可能会绑定到.NET Framework中引入的新重载。 具体而言,以前使用 Marshal.SizeOf (Type) 的调用现在可能调用 Marshal.SizeOf<T> (T) ,而使用 Marshal.PtrToStructure (IntPtr、Type) 的调用现在可能调用 Marshal.PtrToStructure<T> (IntPtr, T) 。 此更改会导致方法或运行时绑定器引发异常。

解决方法

若要解决此问题,请更改代码,以便在语言允许的情况下使用正确的重载。 如果无法指定特定方法重载,请更改代码,使其正确使用新方法重载。

对于 C# 动态调用

在对 SizeOf 或 PtrToStructure 方法的调用中添加到 System.Type 的强制转换。 例如:

object obj = System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, (System.Type)type);
int size = System.Runtime.InteropServices.Marshal.SizeOf((System.Type)type);

注意 仅当方法的其中一个参数是动态时,才需要执行此操作。

对于Windows PowerShell脚本

在对 SizeOf 或 PtrToStructure 方法的调用中添加到 System.Type 的强制转换。 例如:

$size = [System.Runtime.InteropServices.Marshal]::SizeOf([System.Type] $type)

$obj = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ptr, [System.Type] $type)

对于 IronPython 脚本

创建类型的新类型实例,然后使用新方法重载。 例如:

typeInstance = type()

size = System.Runtime.InteropServices.Marshal.SizeOf(typeInstance)

obj = System.Runtime.InteropServices.Marshal.PtrToStructure(ptr, typeInstance)

状态

Microsoft 已确认在 "适用于" 部分中所列的 Microsoft 产品中存在问题。

参考资料