在 C# 中获取本地组和成员名称






4.58/5 (8投票s)
2002 年 9 月 25 日

151322

1822
如何使用 Win32 API 在 C# 中获取本地组和成员
引言
几天前,我阅读了 Phil Bolduc 的 C# 服务器枚举器 文章。他使用了一些 API 来获取服务器名称。之后,我决定采用他的风格,并使用其他函数,如 NetLocalGroupEnum
和 NetLocalGroupGetMembers
。这些函数顾名思义,会检查本地计算机,获取组名和组成员。如果你想在你的网络中获取这些名称,你可以使用 NetGroupEnum
和 NetGroupGetUsers
。这两个函数的定义与前两个函数完全相同。
代码列表
首先,我定义一个内部类,并命名为 Win32API
。然后,我将函数和结构导入到其中。
internal class Win32API
{
#region Win32 API Interfaces
[DllImport( "netapi32.dll", EntryPoint = "NetApiBufferFree" )]
internal static extern void NetApiBufferFree(IntPtr bufptr);
[DllImport( "netapi32.dll", EntryPoint = "NetLocalGroupGetMembers" )]
internal static extern uint NetLocalGroupGetMembers(
IntPtr ServerName,
IntPtr GrouprName,
uint level,
ref IntPtr siPtr,
uint prefmaxlen,
ref uint entriesread,
ref uint totalentries,
IntPtr resumeHandle);
[DllImport( "netapi32.dll", EntryPoint = "NetLocalGroupEnum" )]
internal static extern uint NetLocalGroupEnum(
IntPtr ServerName,
uint level,
ref IntPtr siPtr,
uint prefmaxlen,
ref uint entriesread,
ref uint totalentries,
IntPtr resumeHandle);
[StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct LOCALGROUP_MEMBERS_INFO_1
{
public IntPtr lgrmi1_sid;
public IntPtr lgrmi1_sidusage;
public IntPtr lgrmi1_name;
}
[StructLayoutAttribute(LayoutKind.Sequential, CharSet=CharSet.Auto)]
internal struct LOCALGROUP_INFO_1
{
public IntPtr lpszGroupName;
public IntPtr lpszComment;
}
#endregion
}
LOCALGROUP_MEMBER_INFO_1
和 LOCALGROUP+INFO_1
是两个接收有关组和成员信息的结构体。正如他们的名字、注释和 SID 所暗示的那样。
在演示项目中,使用这些函数的方式非常清晰。我的窗体上有一个按钮,当你点击它时,它会获取组名和成员名,并在树视图中显示每个组,并在子节点中显示它们的成员。我还添加了一些注释以使一切清晰明了。
private void groupbtn_Click(object sender, System.EventArgs e)
{
//defining values for getting group names
uint level = 1, prefmaxlen = 0xFFFFFFFF,
entriesread = 0, totalentries = 0;
//Values that will receive information.
IntPtr GroupInfoPtr,UserInfoPtr;
GroupInfoPtr = IntPtr.Zero;
UserInfoPtr = IntPtr.Zero;
Win32API.NetLocalGroupEnum(
IntPtr.Zero, //Server name.it must be null
level,//level can be 0 or 1 for groups.
//For more information see LOCALGROUP_INFO_0
//and LOCALGROUP_INFO_1
ref GroupInfoPtr,//Value that will be receive information
prefmaxlen,//maximum length
ref entriesread,//value that receives the count of
//elements actually enumerated.
ref totalentries,//value that receives the approximate total
//number of entries that could have been
//enumerated from the current resume position.
IntPtr.Zero);
//this string array will hold comments of each group
commentArray = new string[totalentries];
grouptv.Nodes.Clear();
label1.Visible = true;
//getting group names and add them to tree view
for(int i = 0;i< totalentries ;i++)
{
//converting unmanaged code to managed codes
//with using Marshal class
int newOffset = GroupInfoPtr.ToInt32() +
LOCALGROUP_INFO_1_SIZE * i;
Win32API.LOCALGROUP_INFO_1 groupInfo =
(Win32API.LOCALGROUP_INFO_1)Marshal.PtrToStructure(
new IntPtr(newOffset),
typeof(Win32API.LOCALGROUP_INFO_1));
string currentGroupName =
Marshal.PtrToStringAuto(groupInfo.lpszGroupName);
//storing group comment in an string array to
//show it in a label later
commentArray[i] = Marshal.PtrToStringAuto(groupInfo.lpszComment);
//add group name to tree
grouptv.Nodes.Add(currentGroupName);
//defining value for getting name of members in each group
uint prefmaxlen1 = 0xFFFFFFFF, entriesread1 = 0,
totalentries1 = 0;
//paramaeters for NetLocalGroupGetMembers is
//like NetLocalGroupEnum.
Win32API.NetLocalGroupGetMembers(IntPtr.Zero,
groupInfo.lpszGroupName,1,
ref UserInfoPtr,prefmaxlen1,
ref entriesread1,ref totalentries1,
IntPtr.Zero);
//getting members name
for(int j = 0; j< totalentries1; j++)
{
//converting unmanaged code to managed codes with
//using Marshal class
int newOffset1 = UserInfoPtr.ToInt32() +
LOCALGROUP_MEMBERS_INFO_1_SIZE * j;
Win32API.LOCALGROUP_MEMBERS_INFO_1 memberInfo =
(Win32API.LOCALGROUP_MEMBERS_INFO_1)Marshal.PtrToStructure(
new IntPtr(newOffset1),
typeof(Win32API.LOCALGROUP_MEMBERS_INFO_1));
string currentUserName =
Marshal.PtrToStringAuto(memberInfo.lgrmi1_name);
//adding member name to tree view
grouptv.Nodes[i].Nodes.Add(currentUserName);
}
//free memory
Win32API.NetApiBufferFree(UserInfoPtr);
}
//free memory
Win32API.NetApiBufferFree(GroupInfoPtr);
}
注意
源代码必须启用不安全代码编译。