Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Getting local groups and member names in C#

0.00/5 (No votes)
24 Sep 2002 1  
How to get local groups and members with Win32 API in C#

Introduction

Some days before, I read the C# Server Enumerator article by Phil Bolduc. He used some API to get server names. After that I decided to use his style and use some other functions like NetLocalGroupEnum and NetLocalGroupGetMembers. These functions as their name shows look into the local computer and get group names and group members. If you want to get these names in your network you can use NetGroupEnum and NetGroupGetUsers. These two function are defined exactly the same as the first two.

Code Listing

First I define an internal class and name it Win32API. Then I import functions and structures there.

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 and LOCALGROUP+INFO_1 are two structures that receive information about groups and members. Like their names, comments, SIDs.

Using these functions is made very clear in the demo project. There is a button in my form and when you click it, it gets group and member names and shows each group in a tree view and shows their members in sub-nodes. I also added some comments to make everything clear.

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);
}

Note:

The source code must be compiled with unsafe code enabled.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here