Adding Local User to Local Admin Group
Asked Answered
C

2

13

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;
        }
    }
}
Chilon answered 11/10, 2012 at 15:43 Comment(9)
Try to get an specific error with E.ToString() instead of E.Message.ToString()Gospodin
By the way - there's a (not new anymore) namespace called "System.DirectoryServices.AccountManagement", which will make life easyer for you.Gospodin
@Grumbler85 below is the exception... is it saying that the user does not exist?? Thanks. 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 stack trace --- at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args) at CreateITAdmin.Program.Main(String[]args) in H:\code \CS\CreateITAdmin\CreateITAdmin\Program.cs:line 37Chilon
Well perhaps you should take a look at the namespace i mentioned above, there you can create the user and add him to the group in one step.Gospodin
@Chilon - You should update the question with that additional information. The exception is clear your trying to remove a user that does not exist or is not part of a certain group.Elflock
Do you not have group policy?Gaye
@DavidHeffernan We are using an AD domain for users but this is purely for local administration for student works to do software installs without having to grant them domain admin privsChilon
What OS does the application run on? Does it run as a user that is already part of the Administrator's group, and if so, it is running "as administrator"?Tripletail
@Tripletail this was written on/for windows 7. The running user needs administrative rights on the system in question and I was only able to use this by building the code in Visual Studio and running the resulting .exe file as Administrator from windows explorerChilon
B
2

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.

Baneful answered 23/6, 2017 at 14:57 Comment(0)
B
-8

You mention that these machines are on a domain, it is much simpler to just do this with group policy.

Go in to group policy management (gpmc.msc) and create a new policy. Once you have a new policy created go to Computer Configuration->Prefrences->Local Users and Groups.enter image description here

From there right click and go to New->Local User. In the new screen set the action to Create (you can click the help button to see the difference between the modes) and enter your info for the user in that screen.

enter image description here

One you click ok the user will show up on the screen on the local users and groups page. From there right click and go to New->Local Group. On the new page set the action to Update, use the drop-down to find the group name Administrators (built-in) and select it. In the bottom section click Add... and type in by hand the same name you put in from the previous screen (itadmin in your case). At the end it should look like this

enter image description here

the Local Users and Groups page will look like this

enter image description here

It is important to notice the Order column, the update on the administrator's group must have a higher order number than the user creation command.

One you have your group policy set up apply the policy to the machines that are in the lab (be it through OU targeting or Security Filtering, or WMI Filtering). On next reboot the local itadmin user will be created on each machine.


Also a interesting note, when you choose the user when selecting who to add to the local administrators group, you can click the ... and choose a user on the domain this will allow someone to use their domain login to be a local admin on a small set of computers without giving them rights to be a admin everywhere. However they will need to be able to log in using the domain for this to work, so if you are troubleshooting a network connectivity issue your current approach may be a better thing to do.

Barbi answered 11/10, 2012 at 20:9 Comment(5)
Would the person who gave this a -1 care to explain why? This process creates a Local user with the local admin access, why was this "answer not useful"?Barbi
I downvoted this because you didn't answer the question. You gave an alternative...but the question was regarding how to accomplish this programmatically. I understand giving a programmatic alternative...but this is way off base in my opinion.Unblinking
@Brandon Please read this meta.stackoverflow.com question and answers. Creating a exe to create a user is not the correct way to be creating users like this in a domain, it can work, but its not the right way to do it.Barbi
Thanks for the link...however, I still feel the same. You didn't state that it was the wrong way...and if you had, you should also explain why. Then, if you know how to do it the "wrong way" you should supply that information, otherwise it might be better to suggest another way. "Wrong way" and "right way" are too relative to assume that what you have either learned or assumed is the wrong/right way. I, frankly, get very frustrated when I get answers like these because sometimes I'm just curious on how things work or how to do something should I ever be forced to do so.Unblinking
This isn't an old shoe or glass bottle question though. Creating a program to create users is a totally valid way to automate this kind of task. I'm surprised that you would try to direct him to a manually repetitive solution. I'm guessing the OP already knows how to mmc.Tritium

© 2022 - 2025 — McMap. All rights reserved.