Getting a list of domain group membership for a user account

I was looking for a way to get a list of a user’s associated domain groups. The first pass was to query AD using DirectorySearcher but the PrincipalContext was a less painful route to get what I needed. The method below will get the list of groups that the user belong to. Note that the user returned from the logonUserIdentity.Name will be in domain\user format. We split that apart so we can pass in the user part and also construct a string. That’s not the exact code I used since we have two different domains but it gets the idea across.

Update: I discovered that I needed to use the user name and password of a domain account for the PrincipalContext call. I installed the application on a virtual machine under IIS 7 and it was failing since the pool identity, NETWORKSERVICE, did not have rights to query AD. I ended up getting an exception:

DirectoryServicesCOMException (0x80072020): An operations error occurred

    public List<string> GetUserDomainGroups(WindowsIdentity logonUserIdentity)
        List<string> groupList = new List<string>();

        string[] user = logonUserIdentity.Name.Split("\\".ToCharArray());
        user[0] += ".com";

        SecurityKey securityKey = GetSecurityKeyFromConfiguration();

        using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain, user[0], securityKey.UserName, securityKey.Password))
            using (Principal principal = Principal.FindByIdentity(ctx, user[1]))
                if (principal != null)
                    PrincipalSearchResult<Principal> groups = principal.GetGroups();
                    using (groups)
                        groupList.AddRange(groups.Select(group => group.SamAccountName));

        return groupList;

Converting strings/byte arrays to encoded strings

I ran into this problem not to long ago where I needed to round trip strings between a coded format and their normal human readable format.

The basic idea was to take the string, and convert it to a byte array and then make a string representing the values in the byte array.  The resulting string would be used for a query string parameter and a few other things.

An example: If I have two words I would put a | between them.  hello there would be hello|there and the coded form would be 68656C6C6F7C7468657265

After a bit of digging I found a couple of threads on the net that gave me these two bits of code to go both directions.

string coded = new string(Encoding.UTF8.GetBytes(asciiString).SelectMany(x => x.ToString(“X2”).ToCharArray()).ToArray())

And to go back to the normal string

string notcoded = Encoding.UTF8.GetString(Enumerable.Range(0, hexString.Length / 2).Select(x => Byte.Parse(hexString.Substring(2 * x, 2), NumberStyles.HexNumber)).ToArray())

Not to bad at all with the LINQ in there, before that was around there were loops to get the whole thing done.

Reading Excel Files

I’ve run into the problem a few times of needing to convert rows in an Excel file into an object for some kind of processing. I found an example that was pretty trim in what it was doing so I ended up using it as a model for a new template class.

The basic idea is that you create a new class and provide the overrides for converting a row into an object and after the main method returns you end up with a Collection where T is the type of Data Transfer Object (DTO) that your application can use.

One more modification that I’m planning on adding is to stream the DTOs to a method instead of returning a collection. Calling a processor will allow for a large number of rows to be processed without storing the DTOs in a collection and thus not incurring the memory overhead.

Here is the code so far: [more]

1:using System;
2:using System.Collections.ObjectModel;
3:using System.Data.OleDb;
4:using System.IO;
6:namespace SomeNameSpace
7: {
8:publicclass DigestExcel
9: {
11:/// True if exceptions should be thrown during processing
13:publicbool ThrowExceptions { get; set; }
16:/// Output StringToWrite to a log
18:/// A string to be written to a log
19:protectedvirtualvoid WriteLogFileEntry(string StringToWrite)
20: {
21:// This method should be implemented if logging is desired
22: }
25:/// Convert a row to a DTO
27:/// The DataReader to build DTOs from
28:/// A new DTO object
29:protectedvirtual T ParseDataRow(OleDbDataReader DataReader)
30: {
31:// This method should be implemented
32:thrownew NotImplementedException(“You must implement ParseDataRow”);
33: }
36:/// Reads each row of an Excel file sheet and returns a collection of DTOs
38:/// The fully qualified path to the exxcell file
39:/// The sheet/tab name to be processed
40:/// A collection of T objects
41:public Collection ProcessExcelFile(string FileName, string SheetName)
42: {
43: Collection objectList = new Collection();
45: OleDbConnection conn = new OleDbConnection();
47: {
48: WriteLogFileEntry(String.Format(“Opening File: {0}”, FileName));
50:// Make sure the file exists first
51:if( File.Exists( FileName ) == false )
52: {
53:thrownew FileNotFoundException(String.Format(” Unable to locate requested file, aborting: {0}”, FileName));
54: }
56: conn = new OleDbConnection(“Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” + FileName + “;Extended Properties=\”Excel 8.0;\””);
57: conn.Open();
59: OleDbCommand cmd = new OleDbCommand(String.Format(“SELECT * FROM [{0}$]”, SheetName), conn);
61: OleDbDataReader dataReader = cmd.ExecuteReader();
63:int rowCounter = 0;
64:while (dataReader.Read())
65: {
66:// Advance the row number for logging
67: ++rowCounter;
69: WriteLogFileEntry(String.Format(” Processing data row {0}”, rowCounter));
72: {
73:// Add the next row to the collection
74: objectList.Add(ParseDataRow(dataReader));
75: }
76:catch(Exception up)
77: {
78:string exceptionMessage = String.Format(” Exception processing row {0}: {1}”, rowCounter, up.Message);
80:// If we throw exceptions up then the outer catch will describe the exception so we wont log it here
81:if( ThrowExceptions )
82: {
83:thrownew ApplicationException(exceptionMessage, up);
84: }
86:// If there is an exception then log it
87: WriteLogFileEntry(exceptionMessage);
88: }
89: }
90: }
91:catch(Exception up)
92: {
93:string exceptionMessage = String.Format(” Exception processing file {0}: {1}”, FileName, up.Message);
95:// If there is an exception then log it
96: WriteLogFileEntry(exceptionMessage);
98:if (ThrowExceptions)
99: {
100:thrownew ApplicationException(exceptionMessage, up);
101: }
102: }
104: {
105: conn.Close();
106: WriteLogFileEntry(” Processing file completed”);
107: }
109:return objectList;
110: }
111: }
112: }
In order to use the template you can define a new class and inherit from the DigestExcel class like this:
1:publicclass DigestSample : DigestExcel
2: {
3:protectedoverridevoid WriteLogFileEntry(string StringToWrite)
4: {
5: Console.WriteLine(StringToWrite);
6: }
8:protectedoverride SampleDTO ParseDataRow(System.Data.OleDb.OleDbDataReader DataReader)
9: {
10: SampleDTO newRow = new SampleDTO();
12: newRow.Value1 = DataReader[0].ToString().Trim();
13: newRow.Value2 = DataReader[1].ToString().Trim();
15:return newRow;
16: }
17: }