我的代码通过 P/Invoke 使用 SSPI dll (security.dll) 中的方法,它在每个测试平台(Windows XP、Windows Server 2003 x86 和 x64)上都运行良好,但我们正在处理中迁移到 Windows Server 2008,并发现 P/Invoke 调用使进程崩溃。
我整理了以下重现代码:
using System;
using System.Runtime.InteropServices;
namespace TestPInvoke
{
class Program
{
static void Main(string[] args)
{
try
{
// The following code works on all platforms tested (Windows Server 2003 x86/x64, Windows Server 2008 x64, Windows XP, Windows Vista)
var table1 = (SecurityFunctionTable)Marshal.PtrToStructure(InitReturningPtr(), typeof(SecurityFunctionTable));
Console.WriteLine(table1.dwVersion);
Console.WriteLine(table1.EnumerateSecurityPackages.ToInt64().ToString("x16"));
Console.ReadLine();
// This call crashes only on Windows Server 2008 and Windows Vista (but works fine on XP and 2K3)
var table2 = InitReturningClass();
Console.WriteLine(table2.dwVersion);
Console.WriteLine(table2.EnumerateSecurityPackages.ToInt64().ToString("x16"));
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
Console.ReadLine();
}
[DllImport("security.dll", EntryPoint = "InitSecurityInterfaceW")]
public static extern IntPtr InitReturningPtr();
[DllImport("security.dll", EntryPoint = "InitSecurityInterfaceW")]
public static extern SecurityFunctionTable InitReturningClass();
[StructLayout(LayoutKind.Sequential)]
public class SecurityFunctionTable
{
public uint dwVersion;
public IntPtr EnumerateSecurityPackages;
public IntPtr QueryCredentialsAttributes;
// ...omitted for brevity
}
}
}
问题并不孤立于这个特定的 DLL 或函数,但我尝试过的任何 P/Invoke 调用都显示了问题,其中 native 函数的返回值是指向隐式编码到类中的结构的指针.
因为我有一个功能性的解决方法(使用 Marshal.PtrToStructure),这不是一个主要问题,但我很想知道为什么它在 XP 和 2k3 上没有(明显的)问题,但在 Vista 和 2k8 上却没有,并且是否有任何方法可以修复类返回方法以避免更丑陋的显式编码。
最佳答案
使用 Marshal.PtrToStructure
是正确的做法。这在 XP/Server 2003 上运行的事实纯属巧合,因为代码一直存在错误。
关于c# - 仅在 Vista/Windows Server 2008 上出现 P/Invoke 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3284408/