Developer

How do I... Enumerate windows groups in .NET Framework 1.1?

In the .NET Framework version 1.1 there is no easy way to enumerate which windows groups the current user is a member of. It is a mystery why Microsoft chose not to include this functionality — some people say they ran out of time, others say it was simply overlooked. The odd part is that the functionality actually does exist, but instead of being a fully documented public method, it is a sparsely documented non-public static method hidden in the WindowsIdentity class.

Accessing this method is anything but straight forward, and some would even say dangerous. You must access this functionality via reflection, and since there is no official documentation you can't be sure how long this method will be supported. There are times, though, when you have to have it, and questioning the availability of support just doesn't fit into the timeline.

This blog post is available in PDF for as TechRepublic download, which includes a sample Visual Studio Project highlighting the techniques explored.

Hidden in WindowsIdentity

The function we're going to use is called _GetRoles, and as mentioned previously it is a private static method within the WindowsIdentity class. To access the _GetRoles method we will use reflection and the InvokeMethod function available from the Type object. The following is a step-by-step description on how to do this:

1. Get the current WindowsIdentity.

Our first task is to get the current WindowsIdentity that represents the user who is running our application. This is done by simply calling WindowsIdentity.GetCurrent(), as shown:

//Get the current WindowsIdentity
WindowsIdentity currentUser = WindowsIdentity.GetCurrent();

2. Get a Type object that represents the WindowsIdentity class

We will use this Type object to call InvokeMember. The code to get this object is shown:

//Get the Type object of WindowsIdentity
Type type = typeof(WindowsIdentity);

3. Call InvokeMember on our Type object

This step is by far the most complicated, although still fairly easy to grasp. We need to call InvokeMember on the Type object we got from WindowsIdentity and pass in the function we want to Invoke. In this case that function is _GetRoles. The code to accomplish this is shown in Listing A.

Listing A

//Use InvokeMember to access the private method

// "_GetRoles" method.

object result = type.InvokeMember("_GetRoles", BindingFlags.Static |

BindingFlags.InvokeMethod |

BindingFlags.NonPublic,

null,

currentUser,

new object[] { currentUser.Token },

null);

A couple notes should be made here. For one, the BindingFlags sent to InvokeMember are necessary because _GetRoles is a nonpublic, static, method. Another thing to notice is that we're sending currentUser.Token into InvokeMember as a parameter for _GetRoles. It could be possible that _GetRoles does some unsafe operations and for this reason Microsoft decided to leave it private.

4. Convert the result to a string array

Now that we have our result object from the invocation of _GetRoles we simply cast it into a string array as shown;

//Convert the result to a string array
string[] groups = (string[])result;
The final result, when you put all these pieces together should be similar to the code shown in Listing B. This code will simply return a string array that contains all of the current user's group memberships

Listing B

public static string[] GetGroups()

{

//Get the current WindowsIdentity

WindowsIdentity currentUser = WindowsIdentity.GetCurrent();

//Get the Type object of WindowsIdentity

Type type = typeof(WindowsIdentity);

//Use InvokeMember to access the private method

// "_GetRoles" method. This method returns an array

// of strings - each string represents a Windows group.

object result = type.InvokeMember("_GetRoles",

BindingFlags.Static |

BindingFlags.InvokeMethod |

BindingFlags.NonPublic, null, currentUser,

new object[] { currentUser.Token }, null);

//Return the group array

return (string[])result;

}

What about the 2.0 Framework?

In .NET 2.0, Microsoft has disabled this functionality - there is now a much easier way to access the current user's group membership. This code is shown in Listing C.

Listing C

        public static List<string> GetGroups()

{

WindowsIdentity identity = WindowsIdentity.GetCurrent();

List<string> groups = new List<string>();

IdentityReferenceCollection identityReferences = identity.Groups;

foreach (IdentityReference identityReference in identityReferences)

{

NTAccount account =

(NTAccount)identityReference.Translate(typeof(NTAccount));

groups.Add(account.Value);

}

return groups;

}

One last note

Even though Microsoft removed the _GetRoles function in the 2.0 Framework, the code will still compile. Only it will throw an exception during runtime. So be sure to update your code to the method shown in Listing C after you upgrade to the 2.0 framework!

Editor's Picks

Free Newsletters, In your Inbox