I am writing a C# program to be pushed out the labs I work in. The program is to create a local admin account(itadmin), set the password, set the password to never expire, and add the account to the local Administrators group. The program creates the new user account and sets everything correctly but when it attempts to add it to the admin group I get a very nondescript exception. Do I have the add to group correct in the first place? What am I missing?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
namespace CreateITAdmin
{
class Program
{
static void Main(string[] args)
{
try
{
string userName = "itadmin";
string userPassword = "password";
Console.WriteLine("Building System Information");
DirectoryEntry localMachine = new DirectoryEntry("WinNT://.,computer");
DirectoryEntry newUser = localMachine.Children.Add(userName, "user");
DirectoryEntry admGroup = new DirectoryEntry("WinNT://./Administrators,group");
Console.WriteLine("Building User Information");
newUser.Properties["FullName"].Value = "IT Administrative User";
newUser.Invoke("Put", new object[] { "UserFlags", 0x10000 });
Console.WriteLine("Setting User Password");
newUser.Invoke("SetPassword", new object[] { userPassword });
newUser.CommitChanges();
Console.WriteLine("Adding itadmin to Administrators Group");
admGroup.Invoke("Add", "WinNT://./" + newUser);
Console.WriteLine("Cleaning Up");
localMachine.Close();
newUser.Close();
admGroup.Close();
}
catch (System.DirectoryServices.DirectoryServicesCOMException E)
{
Console.WriteLine(E.Message.ToString());
Console.ReadLine();
}
catch (System.Runtime.InteropServices.COMException E)
{
Console.WriteLine(E.Message.ToString());
Console.ReadLine();
}
catch (System.Reflection.TargetInvocationException E)
{
Console.WriteLine(E.Message.ToString());
Console.ReadLine();
}
catch (Exception E)
{
Console.WriteLine(E.Message.ToString());
Console.ReadLine();
}
Console.WriteLine();
Console.WriteLine("Press Any Key to Continue");
Console.ReadLine();
return;
}
}
}
The code output is below:
Building System Information
Building User Information
Setting User Password
Adding itadmin to Administrators Group
Exception has been thrown by the target of an invocation.
Any insight would be greatly appriciated.
UPDATE 1: With the help of @Grumbler85 the exceptionis listed below:
System.Reflection.TargetInvocationException: Exception has been thrown by the target
of an invocation. ---> System.Runtime.InteropServices.COMException: A member could not
be added to or removed from the local group because the member does not exist. --- End
of inner exception stacktrace --- at System.DirectoryServices.DirectoryEntry.Invoke
(String methodName,Object[]args) at CreateITAdmin.Program.Main(String[]args)in
H:\code\CS\CreateITAdmin\CreateITAdmin\Program.cs:line 37
Also with the help of @Grumbler85 I have been working on updating the library use to System.DirectoryServices.AccountManagement. It seems to be a lot easier and a lot more straight forward in use. More updates/details to come as I progress.
Update 2: I know this is a quick follow up but I was able to complete the update to the new namespace. After a minor hiccup with defining the machine, I was able to successfully create a user, set the password, update the password to never expire, and add the user to the administrators group. Thanks to @Grumbler85 for the update to the new namespace. The new code is below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
namespace CreateITAdmin
{
class Program
{
static void Main(string[] args)
{
string userName = "itadmin";
string userPassword = "IT-Engineering1";
PrincipalContext systemContext = null;
try
{
Console.WriteLine("Building System Information");
systemContext = new PrincipalContext(ContextType.Machine, null);
}
catch (Exception E)
{
Console.WriteLine("Failed to create System Context.");
Console.WriteLine("Exception: " + E);
Console.WriteLine();
Console.WriteLine("Press Any Key to Continue");
Console.ReadLine();
return;
}
//Check if user object already exists
Console.WriteLine("Checking if User Exists.");
UserPrincipal usr = UserPrincipal.FindByIdentity(systemContext, userName);
if (usr != null)
{
Console.WriteLine(userName + " already exists. Exiting!!");
Console.ReadLine();
return;
}
//Create the new UserPrincipal object
Console.WriteLine("Building User Information");
UserPrincipal userPrincipal = new UserPrincipal(systemContext);
userPrincipal.Name = userName;
userPrincipal.DisplayName = "IT Administrative User";
userPrincipal.PasswordNeverExpires = true;
userPrincipal.SetPassword(userPassword);
userPrincipal.Enabled = true;
try
{
Console.WriteLine("Creating New User");
userPrincipal.Save();
}
catch (Exception E)
{
Console.WriteLine("Failed to create user.");
Console.WriteLine("Exception: " + E);
Console.WriteLine();
Console.WriteLine("Press Any Key to Continue");
Console.ReadLine();
return;
}
GroupPrincipal groupPrincipal = null;
try
{
groupPrincipal = GroupPrincipal.FindByIdentity(systemContext, "Administrators");
if (groupPrincipal != null)
{
//check if user is a member
Console.WriteLine("Checking if itadmin is part of Administrators Group");
if (groupPrincipal.Members.Contains(systemContext, IdentityType.SamAccountName, userName))
{
Console.WriteLine("Administrators already contains " + userName);
return;
}
//Adding the user to the group
Console.WriteLine("Adding itadmin to Administrators Group");
groupPrincipal.Members.Add(userPrincipal);
groupPrincipal.Save();
return;
}
else
{
Console.WriteLine("Could not find the group Administrators");
}
}
catch (Exception E)
{
Console.WriteLine("Exception adding user to group.");
Console.WriteLine("Exception: " + E);
Console.WriteLine();
Console.WriteLine("Press Any Key to Continue");
Console.ReadLine();
}
Console.WriteLine("Cleaning Up");
groupPrincipal.Dispose();
userPrincipal.Dispose();
systemContext.Dispose();
Console.WriteLine();
Console.WriteLine("Press Any Key to Continue");
Console.ReadLine();
return;
}
}
}
For Update 3 (for Multi Language support)
Please use build in identifiers --> "Well Known SIDs" for build in accounts or groups:
var sAdministrators = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid , null).Translate(typeof(NTAccount)).Value;
groupPrincipal = GroupPrincipal.FindByIdentity(systemContext, IdentityType.Name, sAdministrators.ToString());
and not: ..... FindByIdentity(systemContext, "Administrators");
Because if you want to use it "world wide" and outside of the engl. world you will get an error. Example: Germany use "VORDEFINIERT\Administratoren" as Name.