我正在尝试包装下面声明的Secur32.dll的EnumerateSecurityPackages函数:
SECURITY_STATUS SEC_Entry EnumerateSecurityPackages(
__in PULONG pcPackages,
__in PSecPkgInfo *ppPackageInfo
);
我有以下C#代码,但在尝试运行时遇到AccessViolationException。在调试器中,pcPackages变量确实设置正确,但我认为我对SecPkgInfos数组做错了。
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgInfo
{
public ulong fCapabilities;
public ushort wVersion;
public ushort wRPCID;
public ulong cbMaxToken;
public string Name;
public string Comment;
}
[DllImport("Secur32.dll")]
public extern static int EnumerateSecurityPackages(
ref ulong pcPackages,
ref SecPkgInfo[] ppPackageInfo
);
///Calling code
ulong count = 0;
SecPkgInfo[] buffer = new SecPkgInfo[256];
EnumerateSecurityPackages(ref count, ref buffer);
任何想法我做错了什么?
答案 0 :(得分:1)
您对SecPkgInfo的定义不正确,C是ULONG
!= C#的ulong
。您还需要非常清楚地指定如何通过MarshalAs编组名称和注释
答案 1 :(得分:1)
试试这段代码,它是从VB.Net(我的母语)转换而来,但在C#中运行正常。只需致电Call_EnumerateSecurityPackages()
,它就会为您返回一个列表。
public static List<SecPkgInfo> Call_EnumerateSecurityPackages()
{
//Will hold the number of security packages found
UInt32 count = 0;
//Will hold a pointer to our array
IntPtr SourcePoint = IntPtr.Zero;
//Call function
int MSG = EnumerateSecurityPackages(ref count, ref SourcePoint);
//See if there was an error
if (MSG == 0)
{
//Create a copy of our pointer so that we can clear it later
IntPtr ArrayPtr = new IntPtr(SourcePoint.ToInt32());
//The type of our structure
Type T = typeof(SecPkgInfo);
//The size of our structure
int ObjSize = Marshal.SizeOf(T);
//We'll store our information in a standard list object
List<SecPkgInfo> SecPackages = new List<SecPkgInfo>();
//Create a loop and increment our pointer by the size of the SecPkgInfo structure, effectively walking the array
for (ulong I = 0; I <= (count - 1); I++)
{
//This converts the current bytes at the pointer to the given structure
SecPackages.Add((SecPkgInfo)Marshal.PtrToStructure(ArrayPtr, T));
//Increment our pointer by the size of the structure
ArrayPtr = IntPtr.Add(ArrayPtr, ObjSize);
}
//Cleanup our pointer
MSG = FreeContextBuffer(ref SourcePoint);
//Make sure cleanup worked
if (MSG == 0)
{
//Return our values
return SecPackages;
}
else
{
//Do something better with the error code here
throw new ApplicationException("Error cleaning up pointer");
}
}
else
{
//Do something better with the error code here
throw new ApplicationException("Error calling native function");
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SecPkgInfo
{
//ulong is 32 bit so we need to use a 32 bit int
public UInt32 fCapabilities;
//ushort is 16 bit
public UInt16 wVersion;
public UInt16 wRPCID;
public UInt32 cbMaxToken;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string Name;
[MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
public string Comment;
}
[DllImport("Secur32.dll")]
public static extern int EnumerateSecurityPackages(ref UInt32 pcPackages, ref IntPtr ppPackageInfo);
[DllImport("Secur32.dll")]
public static extern int FreeContextBuffer(ref IntPtr pvContextBuffer);
以后使用,这是VB版本:
Public Shared Function Call_EnumerateSecurityPackages() As List(Of SecPkgInfo)
''//Will hold the number of security packages found
Dim count As UInt32 = 0
''//Will hold a pointer to our array
Dim SourcePoint As IntPtr
''//Call function
Dim MSG = EnumerateSecurityPackages(count, SourcePoint)
''//See if there was an error
If MSG = 0 Then
''//Create a copy of our pointer so that we can clear it later
Dim ArrayPtr As New IntPtr(SourcePoint.ToInt32())
''//The type of our structure
Dim T = GetType(SecPkgInfo)
''//The size of our structure
Dim ObjSize = Marshal.SizeOf(T)
''//We will store our information in a standard list object
Dim SecPackages As New List(Of SecPkgInfo)
''//Create a loop and increment our pointer by the size of the SecPkgInfo structure, effectively walking the array
For I = 0 To (count - 1)
''//This converts the current bytes at the pointer to the given structure
SecPackages.Add(CType(Marshal.PtrToStructure(ArrayPtr, T), SecPkgInfo))
''//Increment our pointer by the size of the structure
ArrayPtr = IntPtr.Add(ArrayPtr, ObjSize)
Next
''//Cleanup our pointer
MSG = FreeContextBuffer(SourcePoint)
''//Make sure cleanup worked
If MSG = 0 Then
''//Return our values
Return SecPackages
Else
''//Do something better with the error code here
Throw New ApplicationException("Error cleaning up pointer")
End If
Else
''//Do something better with the error code here
Throw New ApplicationException("Error calling native function")
End If
End Function
<StructLayout(LayoutKind.Sequential)>
Public Structure SecPkgInfo
Public fCapabilities As UInt32 ''//ulong is 32 bit so we need to use a 32 bit int
Public wVersion As UInt16 ''//ushort is 16 bit
Public wRPCID As UInt16
Public cbMaxToken As UInt32
<MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)> Public Name As String
<MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)> Public Comment As String
End Structure
<DllImport("Secur32.dll")>
Public Shared Function EnumerateSecurityPackages(ByRef pcPackages As UInt32, ByRef ppPackageInfo As IntPtr) As Integer
End Function
<DllImport("Secur32.dll")>
Public Shared Function FreeContextBuffer(ByRef pvContextBuffer As IntPtr) As Integer
End Function