{"id":54123,"date":"2009-03-24T21:26:00","date_gmt":"2009-03-24T21:26:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/03\/24\/hey-scripting-guy-how-can-i-create-more-than-one-user-assign-attribute-values-and-assign-the-users-to-groups\/"},"modified":"2009-03-24T21:26:00","modified_gmt":"2009-03-24T21:26:00","slug":"hey-scripting-guy-how-can-i-create-more-than-one-user-assign-attribute-values-and-assign-the-users-to-groups","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-create-more-than-one-user-assign-attribute-values-and-assign-the-users-to-groups\/","title":{"rendered":"Hey, Scripting Guy! How Can I Create More Than One User, Assign Attribute Values, and Assign the Users to Groups?"},"content":{"rendered":"<h2><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\" \/> <\/h2>\n<p>Hey, Scripting Guy! I enjoyed your article yesterday about creating a local user account. However, for my purposes I need to be able to create more than one user. Also I would like to be able to assign values to attributes such as the description. If it is not asking too much, I would also like to be able to assign the user to a group. After all, a user that is not a member of a group is pretty much useless from a security perspective.<\/p>\n<p>&#8211; WC<\/p>\n<p><img decoding=\"async\" border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\" \/><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\" \/> <\/p>\n<p>Hi WC,<\/p>\n<p>Users go into groups. Groups get assigned permission to access resources. MCSE 101 stuff! When we were taking one of my first MCP exams for Windows NT 3.51, we had a test that harped on that over and over again. If you remembered that mantra, you could pass the exam. The test was boring! In the end, we quit reading the questions, and just read the answers. If the answer was something that looked like &#8220;place the user in a group\u2014give the group permission to access the resource,&#8221; we selected that answer. By the way, we passed. Oh, you wanted a script didn&#8217;t you?<\/p>\n<table id=\"EXC\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td>\n<p class=\"lastInCell\">This week we will be looking at scripting Windows PowerShell as it applies to local account management. This is an area that comes up from time to time and for which there are not an awful lot of resources from which to choose. We have these tasks in the Script Center Script Repository pretty well hidden away in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/ds\/local\/default.mspx\" target=\"_blank\">Other Directory Services<\/a> category. There are some great scripts in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/csc\/scripts\/local\/default.mspx\" target=\"_blank\">Community-Submitted Scripts Center<\/a>. Local account management has been a favorite topic of the \u201cHey, Scripting Guy!\u201d articles over the years, and as a result we have a good selection of articles grouped together in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/local.mspx\" target=\"_blank\">\u201cHey, Scripting Guy!\u201d archive<\/a>. The most extensive reference you will find is the MSDN coverage of the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa772237(VS.85).aspx\" target=\"_blank\">WinNT ADSI provider<\/a>.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>We decided to write the <b>ReadCSVCreateLocalUsersAddToGroup.ps1<\/b> script. We don&#8217;t really have this exact VBScript on the Script Center. Here is <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/ds\/local\/groups\/logpvb06.mspx\" target=\"_blank\">a script that adds a user to a local group<\/a>, and here is <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/ds\/local\/users\/lousvb03.mspx\" target=\"_blank\">a script that creates a local user<\/a>. You would need to combine them and then add the code to read a text file if you wanted to reproduce the <b>ReadCSVCreateLocalUSersAddToGroup.ps1<\/b> script in VBScript.<\/p>\n<pre class=\"codeSample\">$computer = $Env:ComputerName\n$text = \"C:\\fso\\LocalUsers.txt\"\n$user = import-csv -path $text\n   foreach($strUser in $user)\n    {\n     $user = $struser.user\n     $password = $struser.password\n     $description =  $struser.description\n     $group = $struser.group\n     Clear-Host\n     $ObjOU = [ADSI]\"WinNT:\/\/$computer\"\n     $objUser = $objOU.Create(\"User\", $user)\n     $objUser.setpassword($password)\n     $objUser.put(\"description\",$description)\n     $objUser.SetInfo()\n     $objGroup = [ADSI]\"WinNT:\/\/$computer\/$group\"\n     $objGroup.add(\"WinNT:\/\/$computer\/$user\")\n     $objGroup.SetInfo()\n    }\n<\/pre>\n<p>The&nbsp;first thing we do is create a variable named <b>$computer<\/b> and assign the name of the local computer to it. We obtain the name of the local computer by reading the value of the environmental variable <b>ComputerName<\/b>. This value is obtained from the <b>Environmental<\/b> PSDrive as seen here:<\/p>\n<pre class=\"codeSample\">$computer = $Env:ComputerName<\/pre>\n<p>After we have the computer name, we type the path to the <b>LocalUsers.txt<\/b> file and assign the string to the <b>$text<\/b> variable. The <b>LocalUsers<\/b> file is actually a comma separated value (CSV) file. We just got tired of it opening up in Microsoft Excel each time we accidently double clicked it, so we gave it a .txt extension. Now if we accidently double click it, the contents are immediately displayed in Notepad. The contents of the <b>LocalUsers.txt<\/b> file are seen here:<\/p>\n<pre class=\"codeSample\">$text = \"C:\\fso\\LocalUsers.txt\"<\/pre>\n<p><img decoding=\"async\" border=\"0\" alt=\"Image of the contents of the LocalUsers.txt file\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0324\/hsg-3-24-9-1.jpg\" width=\"500\" height=\"121\" \/> <\/p>\n<p>&nbsp;<\/p>\n<p>After we specify the path to the <b>LocalUsers.txt<\/b> file, we feed it to the <b>Import-Csv<\/b> cmdlet. The resulting custom WIndows PowerShell object is stored in the <b>$user<\/b> variable. If we were to use the <b>Import-Csv<\/b> cmdlet without storing the returned object in a variable, the results would look very similar to the text file itself. We will be able to access these values via a dotted notation later on in the script.<\/p>\n<pre class=\"codeSample\">PS C:\\&gt; Import-Csv -Path C:\\fso\\localUsers.txt\n\nuser                password            description         group\n----                --------            -----------         -----\nauser               P@ssword1           a user from script  users\nbuser               P@ssword1           b user from script  users\ncuser               P@ssword1           c user from script  users\n<\/pre>\n<p>The command that reads the csv file is shown here: <\/p>\n<pre class=\"codeSample\">$user = import-csv -path $text<\/pre>\n<p>Next we need to walk through the collection of user information that is contained in the <b>$user<\/b> variable. To do this, we use the ForEach statement as seen here. <\/p>\n<pre class=\"codeSample\">   ForEach($strUser in $user)\n    {\n<\/pre>\n<p>It is time to populate the variables we will use when creating the user. We decide to recycle the <b>$user<\/b> variable to hold the user name from the csv file. We store the password in the <b>$password<\/b> variable, the description goes in the <b>$description<\/b> variable, and the group name goes into the <b>$group<\/b> variable: <\/p>\n<pre class=\"codeSample\">$user = $struser.user\n     $password = $struser.password\n     $description =  $struser.description\n     $group = $struser.group\n<\/pre>\n<p>We now use the <b>Clear-Host<\/b> function to remove any distracting information that may be displayed on the Windows PowerShell console window. This is seen here: <\/p>\n<pre class=\"codeSample\">Clear-Host<\/pre>\n<p>When we have populated all the variables, we now make the connection to the local account database. To do this, we use the <b>[adsi]<\/b> type accelerator, and specify the WinNT ADSI provider. We feed it the computer name stored in the <b>$computer<\/b> variable and store the returned object in the <b>$objOU<\/b> variable as seen here:<\/p>\n<pre class=\"codeSample\">$ObjOU = [ADSI]\"WinNT:\/\/$computer\"<\/pre>\n<p>After we have made the connection to the local account database, we call the <b>create<\/b> method. We tell it we want to create a user, and we give it the name of the user from the <b>$user<\/b> variable. This is seen here:<\/p>\n<pre class=\"codeSample\">$objUser = $objOU.Create(\"User\", $user)<\/pre>\n<p>We now need to assign a password for the local user. To do this, we use the <b>setpassword<\/b> method and we give it the password contained in the <b>$password<\/b> variable:<\/p>\n<pre class=\"codeSample\">$objUser.setpassword($password)<\/pre>\n<p>After setting the password, we decide to assign a description to the user. To do this we use the <b>put<\/b> method to write to the <b>description<\/b> attribute the value we stored in the <b>$description<\/b> variable: <\/p>\n<pre class=\"codeSample\">$objUser.put(\"description\",$description)<\/pre>\n<p>Next we need to commit the information back to the account database. To do this, we use the <b>SetInfo<\/b> method as seen here: <\/p>\n<pre class=\"codeSample\">$objUser.SetInfo()<\/pre>\n<p>At this point, the user account actually has been created. There are not very many attributes exposed for a local user account. The <b>auser<\/b> user dialog box is seen here:<\/p>\n<p><img decoding=\"async\" border=\"0\" alt=\"Image of the auser user dialog box\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0324\/hsg-3-24-9-2.jpg\" width=\"404\" height=\"448\" \/> <\/p>\n<p>&nbsp;<\/p>\n<p>We need for the user account to exist before attempting to assign the user account to a group. It may seem obvious to some, but it is impossible to assign a nonexistent user to a group. To assign a user to a group, we need to first grab the <b>Group<\/b> object. To do this, we once again dig out the <b>[ADSI]<\/b> type accelerator, and once again we use the WinNT ADSI provider, and we use the computer name from the <b>$computer<\/b> variable and the group that was specified in the <b>$group<\/b> variable. We store the <b>Group<\/b> object that is returned in the <b>$objGroup<\/b> variable as seen here: <\/p>\n<pre class=\"codeSample\">$objGroup = [ADSI]\"WinNT:\/\/$computer\/$group\"<\/pre>\n<p>Now we use the <b>add<\/b> method from the <b>Group<\/b> object to add the user to the group. We need to use the WinNT provider together with the name of the computer and the name of the user to be able to add the user to the group. This is seen here:<\/p>\n<pre class=\"codeSample\">$objGroup.add(\"WinNT:\/\/$computer\/$user\")<\/pre>\n<p>Now that we have connected to the group, and used the <b>add<\/b> method from the group to add the user to the group, it is time to commit the changes to the account database. We do this by using the <b>SetInfo<\/b> method as shown here:<\/p>\n<pre class=\"codeSample\">$objGroup.SetInfo()\n    }\n<\/pre>\n<p>We open the Users group property sheet as seen in the following image, and all of our newly created user accounts have been added to the Users group. So the script worked.<\/p>\n<p><img decoding=\"async\" border=\"0\" alt=\"Image of the Users group property sheet\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/march\/hey0324\/hsg-3-24-9-3.jpg\" width=\"404\" height=\"448\" \/> <\/p>\n<p>&nbsp;<\/p>\n<p>Well, WC, that is it. Users go into groups, and we can use the <b>[adsi]<\/b> type accelerator and the WinNT provider to make it happen. Hope you enjoy the script. We will see you tomorrow as Local Account Management Week continues. Until tomorrow, keep cool.<\/p>\n<p>&nbsp;<\/p>\n<p><b>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I enjoyed your article yesterday about creating a local user account. However, for my purposes I need to be able to create more than one user. Also I would like to be able to assign values to attributes such as the description. If it is not asking too much, I would also [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[44,197,23,24,3,198,45],"class_list":["post-54123","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-groups","tag-local-account-management","tag-local-accounts-and-windows-nt-4-0-accounts","tag-other-directory-services","tag-scripting-guy","tag-users","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I enjoyed your article yesterday about creating a local user account. However, for my purposes I need to be able to create more than one user. Also I would like to be able to assign values to attributes such as the description. If it is not asking too much, I would also [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=54123"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54123\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=54123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}