指定パスに新規ユーザーを作成する方法

System.DirectoryServices.AccountManagement を使用して、Active Directoryにユーザーを新規作成する処理をしていました。

指定したパスにユーザーを作成したい場合は、PrincipalContextをインスタンス化する際に引数を渡してあげればOKでした。

例えば、「OU=employee,OU=Users,DC=domain,DC=sqlazure,DC=jp」にユーザーを追加したい場合は、次のように書けばいい。

var ou = "OU=employee,OU=Users,DC=domain,DC=sqlazure,DC=jp"
var principalContext = new PrincipalContext(ContextType.Domain, hostname, ou, AdUser, AdPassword)
var userprincipal = new UserPrincipalGloops(principalContext)
.
.
.
userprincipal.Save();

「サーバーがプロセスを実行しようとしません。」というエラーの対処

System.DirectoryServices.AccountManagement を使用して、Active Directoryにユーザーを追加する処理をしていました。

                using (var principalContext = new PrincipalContext(ContextType.Domain, host, ou, AdUser, AdPassword))
                {
                    using (var userprincipal = new UserPrincipalGloops(principalContext))
                    {
                        if (!string.IsNullOrEmpty(lastName))
                        {
                            userprincipal.GivenName = familiyName;
                        }
                        if (!string.IsNullOrEmpty(familiyName))
                        {
                            userprincipal.Surname = familiyName;
                        }
                        if (!string.IsNullOrEmpty(roma))
                        {
                            userprincipal.Name = roma;
                        }
                        if (!string.IsNullOrEmpty(familiyName) && !string.IsNullOrEmpty(lastName))
                        {
                            userprincipal.DisplayName = String.Format("{0} {1}", familiyName, lastName);
                        }
                        if (!string.IsNullOrEmpty(mail))
                        {
                            userprincipal.EmailAddress = mail;
                        }
                        if (!string.IsNullOrEmpty(employeeNumber))
                        {
                            userprincipal.EmployeeNumber = employeeNumber;
                        }
                        if (!string.IsNullOrEmpty(idm))
                        {
                            userprincipal.Description = idm;
                        }
                        if (!string.IsNullOrEmpty(idm))
                        {
                            userprincipal.SamAccountName = account;
                        }
                        userprincipal.SetPassword(password);
                        userprincipal.Enabled                  = true;
                        userprincipal.PasswordNeverExpires     = true;
                        userprincipal.UserCannotChangePassword = true;
                        try
                        {
                            userprincipal.Save();
                        }
                        catch (Exception ex)
                        {
                            Logger.Warn("[Create Ad Account] " + ex.Message, ex);
                            return string.Format("NoCreate:{0}",ex.Message);
                        }
                    }
                }

userprincipa.save()で、例外が発生して、「サーバーがプロセスを実行しようとしません。」と言われちゃいます。(いやいや、実行しろよ!と突っ込みたくなったり)

今回、employee numberに情報を格納するために、プリンシパルの拡張をしていました。

MSDNのサンプルでは、プリンシパルの拡張の冒頭が次のようになっていました。
なので、あまり深く考えずにコピペしたのが運の尽き。

[DirectoryRdnPrefix("CN")]
[DirectoryObjectClass("inetOrgPerson")]
public class InetOrgPerson : UserPrincipal
{

「DirectoryObjectClass」が拡張するクラス名を入れておけば良さそうに見えます。実際、それでも既存ユーザーの更新では問題なく動作するように見えます。

しかし、ユーザーの新規作成時には動作しません。
userを指定すると、例外が発生せずにユーザーを新規作成できるようになりました。

[DirectoryRdnPrefix("CN")]
[DirectoryObjectClass("user")]
public class UserPrincipalGloops: UserPrincipal
{

2時間ぐらいはまった…。