当面向 .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 异常:

注意

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

问题 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 产品中存在问题。

参考资料