September 26, 2009

Good Weekend

Hope everyone is having a great weekend!

September 25, 2009

Active Directory and C# III

To continue this series of posts, I'd now like to talk about groups and my group helper class. It is actually quite simple and kind of looks just like the User helper. You can download all the files from here. I will upload this file from this post next week.

Before we get started, I wanted to tell you all that if you do any AD programming you should look at a book written by Joe Kaplan and Ryan Dunn . It is really the best book out there. The authors also have a site here for you to look at and a forum which is helpful. My next bit of code actually relies on code from their book. They have the code available on thei site and it can be found here. You can use the entire build or just some of the files. The main one for me was PasswordExpires (Listing 10.8, 10.9, & 10.10 in full). I use a few others in the root of their project as well ... it might be just easier to include their project. Go out and buy the book though...it is great!
using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
using System.Security.Principal;
using DotNetDevGuide.DirectoryServices;
using ActiveDs;
using DotNetDevGuide.DirectoryServices.Chapter10;

namespace AdLib
{
public class AdDomain
{
private const int ADS_UF_ACCOUNTDISABLE = 2;
private DomainPolicy _policy;

//UsersSearchPath can be from a config location
public void CreateUser(string userName, Dictionary props)
{
CreateUser(userName, UsersSearchPath, props);
}

public void CreateUser(string userName, string path, Dictionary props)
{
path = GetFullPath(path);

using (DirectoryEntry parent = OpenEntry(path))
{
DirectoryEntry user = parent.Children.Add(
String.Format("CN={0}", userName),
"user"
);

using (user)
{
// Set default props
user.Properties["sAMAccountName"].Add(userName);
user.CommitChanges();


// Set user defined props
foreach (string propName in props.Keys)
{
if (propName.ToLower() == "password")
continue;

user.Properties[propName].Add(props[propName]);
user.CommitChanges();
}

if (props.ContainsKey("password"))
((IADsUser)user.NativeObject).SetPassword((string)props["password"]);

user.CommitChanges();

EnableAccount(user);
}
}
}

private void EnableAccount(DirectoryEntry entry)
{
int userAccountControl = (int)entry.Properties["userAccountControl"][0];
userAccountControl &= ~ADS_UF_ACCOUNTDISABLE;
entry.Properties["userAccountControl"][0] = userAccountControl;
entry.CommitChanges();
}

//GroupsSearchPath can be from a config location
public void CreateGroup(string groupName, int type)
{
CreateGroup(groupName, type, GroupsSearchPath);
}

public void CreateGroup(string groupName, int type, string groupOU)
{
groupOU = GetFullPath(groupOU);

using (DirectoryEntry parent = OpenEntry(groupOU))
{
DirectoryEntry group = parent.Children.Add(
String.Format("CN={0}", groupName),
"group"
);

using (group)
{
group.Properties["sAMAccountName"].Add(groupName);

if(type != (int)GroupType.Unknown)
group.Properties["groupType"].Add(type);

group.CommitChanges();
}
}
}

private string GetFullPath(string subPath)
{
//server from config
if (string.IsNullOrEmpty(Server))
return string.Format("LDAP://{0}", subPath);
else
//server from config
return string.Format("LDAP://{0}/{1}", Server, subPath);
}

public DirectoryEntry OpenEntry(string path)
{
if (path.StartsWith("LDAP://", StringComparison.InvariantCultureIgnoreCase) == false)
{
path = GetFullPath(path);
}

return new DirectoryEntry(
path,
Username, //from config
Password, //from config
AuthenticationTypes.Secure
);
}
I'll finish this class up next week.

September 24, 2009

Active Directory and C# II

To continue this series of posts, I'd now like to talk about groups and my group helper class. It is actually quite simple and kind of looks just like the User helper. You can download all the files from here.
using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
using ActiveDs;

namespace AdLib
{
public class AdGroup : IDisposable
{
private DirectoryEntry _entry;
private IADsGroup _group;

public AdGroup(DirectoryEntry entry)
{
if (entry == null)
throw new ArgumentNullException("entry");

_entry = entry;
_group = (IADsGroup)entry.NativeObject;
}

public DirectoryEntry Entry
{
get { return _entry; }
}

public IADsGroup NativeObject
{
get { return _group; }
}

#region IDisposable Members

public void Dispose()
{
_entry.Dispose();
}

void IDisposable.Dispose()
{
Dispose();
}

#endregion
}
}
Of course, we would also need to understand what a GroupType in AD really is:
using System;
using System.Collections.Generic;
using System.Text;

namespace AdLib
{
[Flags]
public enum GroupType : int
{
Unknown = 0,
LocalDistribution = 4,
LocalSecurity = (4 | -2147483648),
GlobalDistribution = 2,
GlobalSecurity = (2 | -2147483648),
UniversalDistribution = 8,
UniversalSecurity = (8 | -2147483648)
}
}
In the next post, we will talk about domains and eventually how this all fits together.

September 23, 2009

Active Directory and C#

I have done a lot of work in the last few years with AD and C#. I figured now that I shared a whole bunch of AzMan stuff, it is only logical that I share some AD helper classes as well. Some of the code can of course be written differently now in the world of .NET 3.5. However, what is written is still relevant and works well. Like the AzMan posts, this will be a bunch of posts tied together to make an application. Unlike AzMan, this will be slower since there is a A LOT more in AD than in AzMan.

One thing that I'll point out is that I rely on ActiveDS more than DirectoryEntry....so for those against this, I am sorry :)

I'd like to start off with the AdUser class that I use from my AdLibrary which you can download from here:
using System;
using System.Collections.Generic;
using System.Text;
using ActiveDs;
using System.DirectoryServices;

namespace AdLib
{
public class AdUser : IDisposable
{
private DirectoryEntry _entry;
private IADsUser _user;

public AdUser(DirectoryEntry entry)
{
if (entry == null)
throw new ArgumentNullException("entry");

_entry = entry;
_user = (IADsUser)entry.NativeObject;
}

public DirectoryEntry Entry
{
get { return _entry; }
}

public IADsUser NativeObject
{
get { return _user; }
}

#region IDisposable Members

public void Dispose()
{
_entry.Dispose();
}

void IDisposable.Dispose()
{
Dispose();
}

#endregion
}
}
To be honest, not much can be done with this. However, combined with all the other classes in the upcoming posts you will see how it all ties together.

September 22, 2009

Powershell Recycle App Pool

I had a need for this today on a IIS 6 box and came across this post on Stack Overflow. SO always has the answer for these things. This script combined with the last post on remoting I should be able to do this from a remote machine! I'll let you know if it works.

September 21, 2009

Powershell Remoting without Admin Permissions

This article shows how it can be done by adding Powershell Session Users to the local group and setting some other permissions. This is great since before this I always was doing some form of impersonation to get this to work!

September 20, 2009

Happy Sunday!

I hope everyone has a great day today!