Question

Ive created a Directory Searcher to pull multiple properties from each user.

objSearchADAM = new DirectorySearcher(objADAM);
objSearchADAM.PropertiesToLoad.Add("givenname");
objSearchADAM.PropertiesToLoad.Add("lastlogontimestamp");
ect...
objSearchResults = objSearchADAM.FindAll();

I then enumerate them, and convert the interger8 timestamp to standard date/time, and save to csv file with

 List<string> timeProps = new List<string>() { "lastlogontimestamp", "accountexpires", "pwdlastset", "lastlogoff", "lockouttime", "maxstorage", "usnchanged", "usncreated", "usndsalastobjremoved", "usnlastobjrem", "usnsource" };

            foreach (SearchResult objResult in objSearchResults)
            {
                objEntry = objResult.GetDirectoryEntry();


                ResultPropertyCollection myResultProp = objResult.Properties;
                foreach (string myKey in myResultProp.PropertyNames)
                {


                    foreach (Object myCollection in myResultProp[myKey])
                    {

                        Object sample = myCollection;


                        if (timeProps.Contains(myKey))
                        {
                            String times = sample.ToString();
                            long ft = Int64.Parse(times);
                            DateTime date;
                            try
                            {

                                date = DateTime.FromFileTime(ft);
                            }
                            catch (ArgumentOutOfRangeException ex)
                            {
                                date = DateTime.MinValue;
                                Console.WriteLine("Out of range: " + ft);
                                Console.WriteLine(ex.ToString());
                            }
                            sample = date;
                            Console.WriteLine("{0}{1}", myKey.PadRight(25), sample);
                            objWriter.WriteLine("{0}{1}", myKey.PadRight(25), sample);
                        }
                        else
                        {
                            Console.WriteLine("{0}{1}", myKey.PadRight(25), sample);
                            objWriter.WriteLine("{0}{1}", myKey.PadRight(25), sample);
                        }
                    }

now i need to create an object for each user with the strings from each result that i can put into an SQL command ive built. where the LDAP query to SQL would be givenname = FirstName and lastlogontimestamp = LastLogon and so on.

StringBuilder sb = new StringBuilder();
sb.Append("INSERT INTO activedirectory.dimUserST (FirstName, LastName) VALUES (@FirstName, @LastName)");
loadStagingCommand.Parameters.AddWithValue("@FirstName", FirstName).DbType =    DbType.AnsiString;
ect...
loadStagingCommand.CommandText = sb.ToString();
loadStagingCommand.ExecuteNonQuery();

i tried to use IDictionary in my first foreach (similar to code found here http://ideone.com/vChWD ) but couldn't get it to work. I read about IList and reflection, but im not sure how i could incorporate these.

UPDATE I researched and found ExpandoObjects and attempted to write in code based off of what i saw in here Creating Dynamic Objects however i run this new code I return "employeenumber System.Collections.Generic.List`1[System.Dynamic.ExpandoObject]"

if(employeeNumber.Contains(myKey))
                        {


                        string[] columnNames = { "EmployeeNumber" };
                        List<string[]> listOfUsers = new List<string[]>();
                        for (int i = 0; i < 10; i++)
                        {
                            listOfUsers.Add(new[] { myKey});
                        }

                        var testData = new List<ExpandoObject>();

                        foreach (string[] columnValue in listOfUsers)
                        {
                            dynamic data = new ExpandoObject();
                            for (int j = 0; j < columnNames.Count(); j++)
                            {
                                ((IDictionary<String, Object>)data).Add(columnNames[j], listOfUsers[j]);
                            }
                            testData.Add(data);
                          Console.WriteLine("{0}{1}", myKey.PadRight(25), testData);
                        objWriter.WriteLine("{0}{1}", myKey.PadRight(25), testData);
                        }

                        }

I am obviously missing something here and cant seem to wrap my head around what the problem is. I might even be going about this the wrong way. Basically all i need to do is pull users and their properties from Active Directory and put into SQL database tabels. And I've worked out how to do both separately, but I cant figure out how to put it all together.

Was it helpful?

Solution

If the CSV is just being used to cache the results, you could use a Dictionary to store the contents of the search results instead. Separating your code into functions could be helpful:

private static object GetFirstValue(ResultPropertyCollection properties, 
                                       string propertyName)
{
    var propertyValues = properties[propertyName];
    var result = propertyValues.Count == 0 ? null : propertyValues[0];
    return result;
}

Then you could either use a dictionary to hold the property values, or you could create a type:

var results = new List<Dictionary<string, object>>();

foreach(SearchResult objResult in objSearchResults)
{
    var properties = objResult.Properties;

    var propertyDictionary = new Dictionary<string, object> { 
       {"FirstName", GetFirstValue(properties, "givenname")},
       {"LastName", GetFirstValue(properties, "sn")},
       {"UserName", GetFirstValue(properties, "samaccountname")},
    };

    results.Add(propertyDictionary);
}

Now you have a list of property bags.

This could also be a simple LINQ statement:

var results = objSearchResults.OfType<SearchResult>()
    .Select(s => s.Properties)
    .Select(p => new {
       FirstName = (string)GetFirstValue(properties, "givenname"),
       LastName = (string)GetFirstValue(properties, "sn"),
       UserName = (string)GetValue(properties, "samaccountname"),
       AccountExpires = GetDateTimeValue(properties, "accountexpires")
    });

Use the dictionaries like this:

foreach(var item in results)
{
    var command = new SqlCommand();
    ...
    command.Parameters.AddWithValue("firstName", item["FirstName"]);
    ...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top