{"id":328,"date":"2006-11-27T05:00:00","date_gmt":"2006-11-27T13:00:00","guid":{"rendered":"http:\/\/testblog.sapien.com\/index.php\/2006\/11\/27\/now-where-did-i-put-that-user\/"},"modified":"2006-11-27T05:00:00","modified_gmt":"2006-11-27T13:00:00","slug":"now-where-did-i-put-that-user","status":"publish","type":"post","link":"https:\/\/dev.sapien.com\/blog\/2006\/11\/27\/now-where-did-i-put-that-user\/","title":{"rendered":"Now where did I put that user?"},"content":{"rendered":"<p>Working with Active Directory in PowerShell will require a bit of a paradigm shift for scripters used to working with ADSI in VBScript. But it&#8217;s not necessarily a bad thing.&nbsp; For example, in PowerShell it is very easy to find objects in Active Directory with a searcher object. Once you have the object reference, you can connect to it and work with its properties pretty much as you did in VBScript. Let me show you a PowerShell script that finds a user in Active Directory given its sAMAccountname and then lists the available properties.<\/p>\n<p>Let&#8217;s look at the script in its entirety first.<\/p>\n<p><span style=\"font-family: Courier New,Courier,mono;\">#GetUserInfo.ps1<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">#http:\/\/www.scriptinganswers.com<\/span><br style=\"font-family: Courier New,Courier,mono;\"><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">function Find-User<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">{<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">Param ($sam=$(throw &#8220;you must enter a sAMAccountname&#8221;))<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">$searcher=New-Object DirectoryServices.DirectorySearcher<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">$searcher.Filter=&#8221;(&amp;(objectcategory=person)(objectclass=user)(sAMAccountname=&#8221;+$sam+&#8221;))&#8221;<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">$results=$searcher.FindOne()<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">if ($results.path.length -gt 1)<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; { <\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; return $results<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; }<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; else<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; {<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; return &#8220;Not Found&#8221;<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; }<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;}<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;#main body of the script<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;$sam=Read-Host &#8220;Enter a sAMAccountname&#8221;<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;$User=Find-User $sam<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;if ($User -eq &#8220;Not Found&#8221;) <\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; {<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; Write-Host -foregroundcolor RED $sam.ToUpper() &#8220;was not found in the directory.&#8221;<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; }<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; else<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; {<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; $objUser=$User.GetDirectoryEntry()<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">#&nbsp;&nbsp;&nbsp; Show all available user properties<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; Write-Host `n<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; Write-host &#8220;DN is&#8221;$objUser.DistinguishedName<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; write-host &#8220;UPN is&#8221;$objUser.UserPrincipalName<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; write-host `n<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; write-host &#8220;Other available properties:&#8221;<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; $objUser|Get-Member<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">#&nbsp;&nbsp;&nbsp; Use code like this if you wanted to update a property<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">#&nbsp;&nbsp;&nbsp; $objUser.Description=&#8221;Updated by PowerShell&#8221;<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">#&nbsp;&nbsp;&nbsp; $objUser.SetInfo()<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; }<\/span><\/p>\n<p>Jump down to the main body of the script. It begins by prompting the administrator for a sAMAccountname. Then it takes that name and passes it as a parameter to the Find-User function defined at the beginning of the script. The function defines a DirectorySearcher object including a filter that basically says, find me a user object where the sAMAccountname equals the value of $sam.&nbsp; I then create an object, $results, to hold the results of the search. The actual search is invoked with the FindOne method. There is also a FindAll method, but since I&#8217;m assuming the sAMAccountname will be unique I can stop searching at the first match.<\/p>\n<p>The search returns an directory searcher result object. I&#8217;ve put in some logic to handle situations where the account is not found by checking for the length of the returned object&#8217;s path. <\/p>\n<p><span style=\"font-family: Courier New,Courier,mono;\">if ($results.path.length -gt 1)<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; { <\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; return $results<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; }<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; else<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; {<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; return &#8220;Not Found&#8221;<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; }<\/span><\/p>\n<p>If the search was successful, $results.path will have some value and length, at which point I can use the object as the return value of the function. If there is no path, then I want to return some sort of error message.<\/p>\n<p>Assuming my search was successful, I now have a search result object. But this isn&#8217;t the actual Active Directory object . To work with all the object&#8217;s properties, I need the object. Fortunately, the search result object has a method called GetDirectoryEntry() which will return the Active Directory object.<\/p>\n<p><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;if ($User -eq &#8220;Not Found&#8221;) <\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; {<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; Write-Host -foregroundcolor RED $sam.ToUpper() &#8220;was not found in the directory.&#8221;<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; }<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; else<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp; {<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">&nbsp;&nbsp;&nbsp;&nbsp; $objUser=$User.GetDirectoryEntry()<\/span><\/p>\n<p>(You can also see that I have some code to gracefully handle the situation if the user is not found.) Now I can access properties directly like this:<\/p>\n<p><span style=\"font-family: Courier New,Courier,mono;\">Write-Host &#8220;DN is&#8221;$objUser.DistinguishedName<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">Write-host &#8220;UPN is&#8221;$objUser.UserPrincipalName<\/span><\/p>\n<p>I can pipe the object to Get-Member which will show me all the properties that are defined.<\/p>\n<p><span style=\"font-family: Courier New,Courier,mono;\">$objUser|Get-Member<\/span><\/p>\n<p>You have to remember that this list is not all the properties, only the ones with values. You can still set a property if you know the name like this:<\/p>\n<p><span style=\"font-family: Courier New,Courier,mono;\">$objUser.Description=&#8221;Updated by PowerShell&#8221;<\/span><br style=\"font-family: Courier New,Courier,mono;\"><span style=\"font-family: Courier New,Courier,mono;\">$objUser.SetInfo()<\/span><\/p>\n<p>Adapting your ADSI VBScripts to PowerShell will take some work, and in some cases it may&nbsp; be better off to start from scratch. But once you get the hang of working with the .NET directory service classes, you&#8217;ll be pretty amazed at the results.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Working with Active Directory in PowerShell will require a bit of a paradigm shift for scripters used to working with ADSI in VBScript. But it&#8217;s not necessarily a bad thing.  For example, in PowerShell it is very easy to find objects in Active Directory with a searcher object. Once you have the object reference, you can connect to it and work with its properties pretty much as you did in VBScript. Let me show you a PowerShell script that finds a user in Active Directory given its sAMAccountname and then lists the available properties.<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[2,25],"tags":[],"class_list":["post-328","post","type-post","status-publish","format-standard","hentry","category-general","category-windows-powershell"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/328","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/comments?post=328"}],"version-history":[{"count":0,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/328\/revisions"}],"wp:attachment":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/media?parent=328"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/categories?post=328"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/tags?post=328"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}