{"id":4750,"date":"2012-10-30T00:01:00","date_gmt":"2012-10-30T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2012\/10\/30\/create-test-users-in-a-test-active-directory-environment-by-using-powershell\/"},"modified":"2012-10-30T00:01:00","modified_gmt":"2012-10-30T00:01:00","slug":"create-test-users-in-a-test-active-directory-environment-by-using-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/create-test-users-in-a-test-active-directory-environment-by-using-powershell\/","title":{"rendered":"Create Test Users in a Test Active Directory Environment by Using PowerShell"},"content":{"rendered":"<p><b>Summary<\/b>: Microsoft Scripting Guy, Ed Wilson, creates a bunch of test users in a test AD&nbsp;DS environment by using Windows PowerShell.<\/p>\n<p><strong><img decoding=\"async\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" \/>&nbsp;<\/strong>Hey, Scripting Guy! I have a problem at work. It seems that the people who fill out titles and descriptions for the users in Active Directory do not follow a standard naming convention&mdash;heck, they do not even follow any sort of standard at all. For a decade, this was not really much of a problem as most people did not even know what Active Directory was, nor did they notice when you changed the name either. Anyway, our users are now using Outlook to try to search Active Directory to find people based upon job titles. The problem is these searches are not working very well. Here is why: Consider the title of Senior Network Engineer. In Active Directory, it appears in more than a dozen varieties. A few examples are Sr. Network Engineer, Sr. NetEng, Sr Net Eng, SR NETENG, SR. NETENG, SR. NETWORK ENG, SENIOR NETWORK ENGINEER, and so forth. This is just one job title, and our company has thousands of employees spread all over the globe with hundreds of job titles. Help!<\/p>\n<p>&mdash;SH<\/p>\n<p><img decoding=\"async\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" \/>Hello SH,<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. I am sorry you are having problems with the user descriptions and titles in your AD&nbsp;DS environment. The long-term solution is to use something that limits the user&rsquo;s ability to specify random titles. This is the great thing about a drop-down list because you are only permitted to select from specific values. A Windows PowerShell script that used parameter validation would also work to constrain the garbage from entering the system.<\/p>\n<p>To come up with a script that will do what you need requires me to populate my test environment with similar types of data. This is one of those things where three scripts are required: a setup script, a solution script, and a cleanup script. The cleanup script will be required prior to the solution script because unless I get things perfect the first time, I can run my cleanup script. Today, I will write the setup script; tomorrow, the cleanup script; and the next day, I will write the solution script.<\/p>\n<h2>Creating an array of titles<\/h2>\n<p>I decided that the first thing I would do is create an array of titles. This is useful from a number of perspectives. Obviously, I will use it for creating the descriptions and the titles of the users; however, I will also use it when it comes time to check for bad titles, because arrays in Windows PowerShell have a <b>contains<\/b><i> <\/i>method. I do not want to simply go through AD&nbsp;DS and change everyone&rsquo;s title to Senior Network Engineer&mdash;although it might be a nice way to give everyone a promotion. Therefore, I need to know what bad titles are, and if I see one of the bad titles, then I will change it to a good title. If the title is not found, I will not make the change. Here is the array of bad titles.<\/p>\n<p style=\"padding-left: 30px\">$title = @(<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Sr. NetEng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;SR. NetEng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Senior NetEng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Sr. Network Engineer&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;sr. network engineer&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;sr. neteng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Senior Network Engineer&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Sr. Net Eng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;SR NET ENG&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;SR. NETENG&#8217;)<\/p>\n<p>To illustrate using the <b>contains<\/b><i> <\/i>method, I highlight and run only the above code block, and in the executable pane (immediate window) at the bottom of the Windows PowerShell ISE, I call the <b>contains<\/b><i> <\/i>method. As appears here, it returns a Boolean value (true \/ false).<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $title = @(<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Sr. NetEng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;SR. NetEng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Senior NetEng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Sr. Network Engineer&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;sr. network engineer&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;sr. neteng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Senior Network Engineer&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Sr. Net Eng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;SR NET ENG&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;SR. NETENG&#8217;)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $title.Contains(&#8220;sr neteng&#8221;)<\/p>\n<p style=\"padding-left: 30px\">False<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $title.Contains(&#8220;sr net eng&#8221;)<\/p>\n<p style=\"padding-left: 30px\">False<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $title.Contains(&#8220;sr. neteng&#8221;)<\/p>\n<p style=\"padding-left: 30px\">True<\/p>\n<h2>Creating an Organizational Unit<\/h2>\n<p>Now, I need to create the organizational unit (OU). In the ActiveDirectory module (available through the RSAT tools or by remoting into a domain controller), I use the <b>New-ADOrganizationalUnit<\/b> cmdlet. I need to specify the name of the OU, and the path where the OU will reside. In addition, because this is a test OU, I do not want it protected from accidental deletion, so I assign false to the -ProtectedFromAccidentalDeletion:$false parameter. This command is shown here.<\/p>\n<p style=\"padding-left: 30px\">IPMO *active*<\/p>\n<p style=\"padding-left: 30px\">&nbsp;New-ADOrganizationalUnit -Name Testou -Path &#8216;dc=iammred,dc=net&#8217; `<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; -ProtectedFromAccidentalDeletion:$false<\/p>\n<p>If I do not unprotect the OU from accidental deletion, then it is more trouble to delete it when the time comes (and it is very difficult to delete it from the GUI tools).<\/p>\n<h2>Create 100 users with random titles in a specific OU<\/h2>\n<p>Next, I need to create 100 users with random titles. The first thing I do is use the range operator to create 100 numbers in an array, then I pipe the numbers to the <b>Foreach-Object<\/b> cmdlet. Inside the Scriptblock for the <b>Foreach-Object<\/b> cmdlet (the curly brackets), I first call the <b>Get-Random<\/b> cmdlet to get a random number between 1 and 9. I will use that random number to index into the array of bad titles when I create the new user. Next, I call the <b>New-ADUser<\/b> cmdlet and specify a name by using <b>NewTestUser<\/b> as the root of the name and the next range operator number to distinguish the name. I need to use the <b>OtherAttributes<\/b><i> <\/i>parameter to supply attributes of the user object other than the main ones. The <b>OtherAttributes<\/b><i> <\/i>parameter accepts a hash block of information&mdash;the attribute name and the value for that attribute. I decided to use the bad title for both the description and the title attributes. This is because the description shows up more easily on the user object when viewed in Active Directory Users and Computers. Here is the code to accomplish the task of creating 100 users with random titles. I use the <b>path<\/b><i> <\/i>parameter to ensure the users appear in the appropriate test OU, and not in the root of Active Directory.<\/p>\n<p style=\"padding-left: 30px\">1..100 | Foreach-Object {<\/p>\n<p style=\"padding-left: 30px\">&nbsp;$r = Get-Random -Minimum 0 -Maximum 10<\/p>\n<p style=\"padding-left: 30px\">&nbsp;New-ADUser -Name &#8220;newtestuser$_&#8221; `<\/p>\n<p style=\"padding-left: 30px\">&nbsp; -OtherAttributes @{title=$title[$r];Description=$title[$r]} `<\/p>\n<p style=\"padding-left: 30px\">&nbsp; -Path &#8220;ou=testou,dc=iammred,dc=net&#8221; }<\/p>\n<h2>The complete script<\/h2>\n<p>The complete script is shown here.<\/p>\n<p style=\"padding-left: 30px\">$title = @(<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Sr. NetEng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;SR. NetEng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Senior NetEng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Sr. Network Engineer&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;sr. network engineer&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;sr. neteng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Senior Network Engineer&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;Sr. Net Eng&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;SR NET ENG&#8217;,<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&#8216;SR. NETENG&#8217;)<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;IPMO *active*<\/p>\n<p style=\"padding-left: 30px\">&nbsp;New-ADOrganizationalUnit -Name Testou -Path &#8216;dc=iammred,dc=net&#8217; `<\/p>\n<p style=\"padding-left: 30px\">&nbsp;&nbsp;&nbsp; -ProtectedFromAccidentalDeletion:$false<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;1..100 | Foreach-Object {<\/p>\n<p style=\"padding-left: 30px\">&nbsp;$r = Get-Random -Minimum 0 -Maximum 10<\/p>\n<p style=\"padding-left: 30px\">&nbsp;New-ADUser -Name &#8220;newtestuser$_&#8221; `<\/p>\n<p style=\"padding-left: 30px\">&nbsp; -OtherAttributes @{title=$title[$r];Description=$title[$r]} `<\/p>\n<p style=\"padding-left: 30px\">&nbsp; -Path &#8220;ou=testou,dc=iammred,dc=net&#8221; }<\/p>\n<p>When I run the script, it creates a new OU named TestOU, and inside the OU it creates 100 test users with random titles and descriptions. The users, OU, and descriptions in Active Directory Users and Computers are shown in the following figure.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1121.hsg-10-30-12-01.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1121.hsg-10-30-12-01.png\" alt=\"Screenshot of Active Directory Users and Computers\" title=\"Screenshot of Active Directory Users and Computers\" \/><\/a><\/p>\n<p>SH, that is all there is to using Windows PowerShell to create a bunch of test users in AD&nbsp;DS and to assign random titles and descriptions to the users. Active Directory week will continue tomorrow when I will talk about changing the descriptions and the titles to match a standard naming convention.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, creates a bunch of test users in a test AD&nbsp;DS environment by using Windows PowerShell. &nbsp;Hey, Scripting Guy! I have a problem at work. It seems that the people who fill out titles and descriptions for the users in Active Directory do not follow a standard naming convention&mdash;heck, they [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[7,3,8,20,45],"class_list":["post-4750","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-active-directory","tag-scripting-guy","tag-searching-active-directory","tag-user-accounts","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, creates a bunch of test users in a test AD&nbsp;DS environment by using Windows PowerShell. &nbsp;Hey, Scripting Guy! I have a problem at work. It seems that the people who fill out titles and descriptions for the users in Active Directory do not follow a standard naming convention&mdash;heck, they [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/4750","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\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=4750"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/4750\/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=4750"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=4750"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=4750"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}