PInvoke NetLocalGroupGetMembers 遇到 FatalExecutionEngineError
PInvoke NetLocalGroupGetMembers runs into FatalExecutionEngineError
我需要在 C# 中使用 win32 NetLocalGroupGetMembers
。我找到并测试了三种解决方案。这三个都失败了 FatalExecutionEngineError
。框架是.net 4.0
这是一个完整的例子:
参考api:
static class NetworkAPI
{
[DllImport("Netapi32.dll")]
public extern static int NetLocalGroupGetMembers([MarshalAs(UnmanagedType.LPWStr)] string servername, [MarshalAs(UnmanagedType.LPWStr)] string localgroupname, int level, out IntPtr bufptr, int prefmaxlen, out int entriesread, out int totalentries, out int resumehandle);
[DllImport("Netapi32.dll")]
public extern static int NetApiBufferFree(IntPtr Buffer);
// LOCALGROUP_MEMBERS_INFO_1 - Structure for holding members details
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct LOCALGROUP_MEMBERS_INFO_1
{
public int lgrmi1_sid;
public int lgrmi1_sidusage;
public string lgrmi1_name;
}
}
调用函数:
static void Main(string[] args)
{
int EntriesRead;
int TotalEntries;
int Resume;
IntPtr bufPtr;
string groupName = "Administrators";
NetworkAPI.NetLocalGroupGetMembers(null, groupName, 1, out bufPtr, -1, out EntriesRead, out TotalEntries, out Resume);
if (EntriesRead > 0)
{
NetworkAPI.LOCALGROUP_MEMBERS_INFO_1[] Members = new NetworkAPI.LOCALGROUP_MEMBERS_INFO_1[EntriesRead];
IntPtr iter = bufPtr;
// EntriesRead has the correct quantity of members of the group, so the group is found
for (int i = 0; i < EntriesRead; i++)
{
// --------------------------------------------------
// ==> here the FatalExecutionEngineError happens:
Members[i] = (NetworkAPI.LOCALGROUP_MEMBERS_INFO_1)Marshal.PtrToStructure(iter, typeof(NetworkAPI.LOCALGROUP_MEMBERS_INFO_1));
//
// --------------------------------------------------
iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(NetworkAPI.LOCALGROUP_MEMBERS_INFO_1)));
Console.WriteLine(Members[i].lgrmi1_name);
}
NetworkAPI.NetApiBufferFree(bufPtr);
}
}
我看到以下错误:
- 恢复句柄是一个指针。对该参数使用
ref IntPtr resumehandle
,并在第一次调用时传递 IntPtr.Zero
。或者,如果您不需要使用恢复句柄,则将参数声明为 IntPtr resumehandle
并传递 IntPtr.Zero
。有关完整详细信息,请参阅 MSDN 上的功能文档。
- 结构体的
lgrmi1_sid
成员是一个指针。声明如下:public IntPtr lgrmi1_sid
.
- 将
IntPtr
转换为 int
将导致 64 位上的指针 t运行cation。直接在 IntPtr
上使用算术,或者对于旧的 C# 版本转换为 long
。前者更好,像这样:iter += Marshal.SizeOf(typeof(NetworkAPI.LOCALGROUP_MEMBERS_INFO_1));
.
- 您没有检查 return 值是否有错误。
修复这些错误,您的程序将 运行 正确。
为了完整起见,这里是如何调用的代码
NetLocalGroupGetMembers
.
我按照 David 的建议更正了代码。还有一个来自 Martin Liversage 的建议,我没有实施。但它可能有用。
如果喜欢,请不要点赞这个答案,而是点赞答案 ,谁发现了错误。
参考api:
public static class NetworkAPI
{
[DllImport("Netapi32.dll")]
public extern static uint NetLocalGroupGetMembers([MarshalAs(UnmanagedType.LPWStr)] string servername, [MarshalAs(UnmanagedType.LPWStr)] string localgroupname, int level, out IntPtr bufptr, int prefmaxlen, out int entriesread, out int totalentries, out IntPtr resumehandle);
[DllImport("Netapi32.dll")]
public extern static int NetApiBufferFree(IntPtr Buffer);
// LOCALGROUP_MEMBERS_INFO_1 - Structure for holding members details
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct LOCALGROUP_MEMBERS_INFO_1
{
public IntPtr lgrmi1_sid;
public int lgrmi1_sidusage;
public string lgrmi1_name;
}
// documented in MSDN
public const uint ERROR_ACCESS_DENIED = 0x0000005;
public const uint ERROR_MORE_DATA = 0x00000EA;
public const uint ERROR_NO_SUCH_ALIAS = 0x0000560;
public const uint NERR_InvalidComputer = 0x000092F;
// found by testing
public const uint NERR_GroupNotFound = 0x00008AC;
public const uint SERVER_UNAVAILABLE = 0x0006BA;
}
调用函数:
static void Main(string[] args)
{
int EntriesRead;
int TotalEntries;
IntPtr Resume;
IntPtr bufPtr;
string groupName = "Administratoren";
string computerName = null; // null for the local machine
uint retVal = NetworkAPI.NetLocalGroupGetMembers(computerName, groupName, 1, out bufPtr, -1, out EntriesRead, out TotalEntries, out Resume);
if(retVal != 0)
{
if (retVal == NetworkAPI.ERROR_ACCESS_DENIED) { Console.WriteLine("Access denied"); return; }
if (retVal == NetworkAPI.ERROR_MORE_DATA) { Console.WriteLine("ERROR_MORE_DATA"); return; }
if (retVal == NetworkAPI.ERROR_NO_SUCH_ALIAS) { Console.WriteLine("Group not found"); return; }
if (retVal == NetworkAPI.NERR_InvalidComputer) { Console.WriteLine("Invalid computer name"); return; }
if (retVal == NetworkAPI.NERR_GroupNotFound) { Console.WriteLine("Group not found"); return; }
if (retVal == NetworkAPI.SERVER_UNAVAILABLE) { Console.WriteLine("Server unavailable"); return; }
Console.WriteLine("Unexpected NET_API_STATUS: " + retVal.ToString());
return;
}
if (EntriesRead > 0)
{
NetworkAPI.LOCALGROUP_MEMBERS_INFO_1[] Members = new NetworkAPI.LOCALGROUP_MEMBERS_INFO_1[EntriesRead];
IntPtr iter = bufPtr;
for (int i = 0; i < EntriesRead; i++)
{
Members[i] = (NetworkAPI.LOCALGROUP_MEMBERS_INFO_1)Marshal.PtrToStructure(iter, typeof(NetworkAPI.LOCALGROUP_MEMBERS_INFO_1));
//x64 safe
iter += Marshal.SizeOf(typeof(NetworkAPI.LOCALGROUP_MEMBERS_INFO_1));
Console.WriteLine(Members[i].lgrmi1_name);
}
NetworkAPI.NetApiBufferFree(bufPtr);
}
}
我需要在 C# 中使用 win32 NetLocalGroupGetMembers
。我找到并测试了三种解决方案。这三个都失败了 FatalExecutionEngineError
。框架是.net 4.0
这是一个完整的例子:
参考api:
static class NetworkAPI
{
[DllImport("Netapi32.dll")]
public extern static int NetLocalGroupGetMembers([MarshalAs(UnmanagedType.LPWStr)] string servername, [MarshalAs(UnmanagedType.LPWStr)] string localgroupname, int level, out IntPtr bufptr, int prefmaxlen, out int entriesread, out int totalentries, out int resumehandle);
[DllImport("Netapi32.dll")]
public extern static int NetApiBufferFree(IntPtr Buffer);
// LOCALGROUP_MEMBERS_INFO_1 - Structure for holding members details
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct LOCALGROUP_MEMBERS_INFO_1
{
public int lgrmi1_sid;
public int lgrmi1_sidusage;
public string lgrmi1_name;
}
}
调用函数:
static void Main(string[] args)
{
int EntriesRead;
int TotalEntries;
int Resume;
IntPtr bufPtr;
string groupName = "Administrators";
NetworkAPI.NetLocalGroupGetMembers(null, groupName, 1, out bufPtr, -1, out EntriesRead, out TotalEntries, out Resume);
if (EntriesRead > 0)
{
NetworkAPI.LOCALGROUP_MEMBERS_INFO_1[] Members = new NetworkAPI.LOCALGROUP_MEMBERS_INFO_1[EntriesRead];
IntPtr iter = bufPtr;
// EntriesRead has the correct quantity of members of the group, so the group is found
for (int i = 0; i < EntriesRead; i++)
{
// --------------------------------------------------
// ==> here the FatalExecutionEngineError happens:
Members[i] = (NetworkAPI.LOCALGROUP_MEMBERS_INFO_1)Marshal.PtrToStructure(iter, typeof(NetworkAPI.LOCALGROUP_MEMBERS_INFO_1));
//
// --------------------------------------------------
iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(NetworkAPI.LOCALGROUP_MEMBERS_INFO_1)));
Console.WriteLine(Members[i].lgrmi1_name);
}
NetworkAPI.NetApiBufferFree(bufPtr);
}
}
我看到以下错误:
- 恢复句柄是一个指针。对该参数使用
ref IntPtr resumehandle
,并在第一次调用时传递IntPtr.Zero
。或者,如果您不需要使用恢复句柄,则将参数声明为IntPtr resumehandle
并传递IntPtr.Zero
。有关完整详细信息,请参阅 MSDN 上的功能文档。 - 结构体的
lgrmi1_sid
成员是一个指针。声明如下:public IntPtr lgrmi1_sid
. - 将
IntPtr
转换为int
将导致 64 位上的指针 t运行cation。直接在IntPtr
上使用算术,或者对于旧的 C# 版本转换为long
。前者更好,像这样:iter += Marshal.SizeOf(typeof(NetworkAPI.LOCALGROUP_MEMBERS_INFO_1));
. - 您没有检查 return 值是否有错误。
修复这些错误,您的程序将 运行 正确。
为了完整起见,这里是如何调用的代码
NetLocalGroupGetMembers
.
我按照 David 的建议更正了代码。还有一个来自 Martin Liversage 的建议,我没有实施。但它可能有用。
如果喜欢,请不要点赞这个答案,而是点赞
参考api:
public static class NetworkAPI
{
[DllImport("Netapi32.dll")]
public extern static uint NetLocalGroupGetMembers([MarshalAs(UnmanagedType.LPWStr)] string servername, [MarshalAs(UnmanagedType.LPWStr)] string localgroupname, int level, out IntPtr bufptr, int prefmaxlen, out int entriesread, out int totalentries, out IntPtr resumehandle);
[DllImport("Netapi32.dll")]
public extern static int NetApiBufferFree(IntPtr Buffer);
// LOCALGROUP_MEMBERS_INFO_1 - Structure for holding members details
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct LOCALGROUP_MEMBERS_INFO_1
{
public IntPtr lgrmi1_sid;
public int lgrmi1_sidusage;
public string lgrmi1_name;
}
// documented in MSDN
public const uint ERROR_ACCESS_DENIED = 0x0000005;
public const uint ERROR_MORE_DATA = 0x00000EA;
public const uint ERROR_NO_SUCH_ALIAS = 0x0000560;
public const uint NERR_InvalidComputer = 0x000092F;
// found by testing
public const uint NERR_GroupNotFound = 0x00008AC;
public const uint SERVER_UNAVAILABLE = 0x0006BA;
}
调用函数:
static void Main(string[] args)
{
int EntriesRead;
int TotalEntries;
IntPtr Resume;
IntPtr bufPtr;
string groupName = "Administratoren";
string computerName = null; // null for the local machine
uint retVal = NetworkAPI.NetLocalGroupGetMembers(computerName, groupName, 1, out bufPtr, -1, out EntriesRead, out TotalEntries, out Resume);
if(retVal != 0)
{
if (retVal == NetworkAPI.ERROR_ACCESS_DENIED) { Console.WriteLine("Access denied"); return; }
if (retVal == NetworkAPI.ERROR_MORE_DATA) { Console.WriteLine("ERROR_MORE_DATA"); return; }
if (retVal == NetworkAPI.ERROR_NO_SUCH_ALIAS) { Console.WriteLine("Group not found"); return; }
if (retVal == NetworkAPI.NERR_InvalidComputer) { Console.WriteLine("Invalid computer name"); return; }
if (retVal == NetworkAPI.NERR_GroupNotFound) { Console.WriteLine("Group not found"); return; }
if (retVal == NetworkAPI.SERVER_UNAVAILABLE) { Console.WriteLine("Server unavailable"); return; }
Console.WriteLine("Unexpected NET_API_STATUS: " + retVal.ToString());
return;
}
if (EntriesRead > 0)
{
NetworkAPI.LOCALGROUP_MEMBERS_INFO_1[] Members = new NetworkAPI.LOCALGROUP_MEMBERS_INFO_1[EntriesRead];
IntPtr iter = bufPtr;
for (int i = 0; i < EntriesRead; i++)
{
Members[i] = (NetworkAPI.LOCALGROUP_MEMBERS_INFO_1)Marshal.PtrToStructure(iter, typeof(NetworkAPI.LOCALGROUP_MEMBERS_INFO_1));
//x64 safe
iter += Marshal.SizeOf(typeof(NetworkAPI.LOCALGROUP_MEMBERS_INFO_1));
Console.WriteLine(Members[i].lgrmi1_name);
}
NetworkAPI.NetApiBufferFree(bufPtr);
}
}