Getting local groups and member names in C#






4.58/5 (8 votes)
Sep 25, 2002

150756

1822
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.