65.9K
CodeProject 正在变化。 阅读更多。
Home

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

2002 年 9 月 25 日

viewsIcon

151322

downloadIcon

1822

如何使用 Win32 API 在 C# 中获取本地组和成员

引言

几天前,我阅读了 Phil Bolduc 的 C# 服务器枚举器 文章。他使用了一些 API 来获取服务器名称。之后,我决定采用他的风格,并使用其他函数,如 NetLocalGroupEnumNetLocalGroupGetMembers。这些函数顾名思义,会检查本地计算机,获取组名和组成员。如果你想在你的网络中获取这些名称,你可以使用 NetGroupEnumNetGroupGetUsers。这两个函数的定义与前两个函数完全相同。

代码列表

首先,我定义一个内部类,并命名为 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_1LOCALGROUP+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);
}

注意

源代码必须启用不安全代码编译。

© . All rights reserved.