{"id":55503,"date":"2008-05-23T01:47:00","date_gmt":"2008-05-23T01:47:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/05\/23\/hey-scripting-guy-how-can-i-use-windows-powershell-to-determine-whether-a-local-user-account-exists\/"},"modified":"2008-05-23T01:47:00","modified_gmt":"2008-05-23T01:47:00","slug":"hey-scripting-guy-how-can-i-use-windows-powershell-to-determine-whether-a-local-user-account-exists","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-use-windows-powershell-to-determine-whether-a-local-user-account-exists\/","title":{"rendered":"Hey, Scripting Guy! How Can I Use Windows PowerShell to Determine Whether a Local User Account Exists?"},"content":{"rendered":"<p><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\" \/> <\/p>\n<p>Hey, Scripting Guy! How can I use Windows PowerShell to determine if a specified local user account exists on a computer?<br \/>&#8212; MM<\/p>\n<p><img decoding=\"async\" height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\" \/><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\" \/><a href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><img decoding=\"async\" class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\" \/><\/a> <\/p>\n<p>Hey, MM. Have you ever heard the expression \u201cgood things come to those who wait\u201d? Well, to tell you the truth, the Scripting Guys have never put much credence in that old saying; after all, the Scripting Guy who writes this column has been waiting for <i>years<\/i> for the New York Yankees to call him and ask him to come play outfield for them. So far he\u2019s heard nothing, absolutely nothing.<\/p>\n<table class=\"dataTable\" id=\"E5C\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p><b>Note to the <\/b><b>New York<\/b><b> Yankees front office.<\/b> If it\u2019s a question about money, then by all means please call this Scripting Guy collect.<\/p>\n<p>After all, he\u2019ll just charge the call to Microsoft anyway.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>The point is, the Scripting Guy who writes this column has spent the past few years sitting around waiting for the New York Yankees to call. That\u2019s pretty much the same thing many of you have been doing: maybe not waiting for the New York Yankees to call, but instead waiting for the Scripting Guys to write a Windows PowerShell version of the world-famous <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/tools\/scripto2.mspx\"><b>Scriptomatic<\/b><\/a>. Well, to be honest, that\u2019s not going to happen: the Scripting Guy who writes this column simply can\u2019t afford to leave his desk, go down to the laboratory, and start tinkering with a PowerShell version of the Scriptomatic. After all, what if the Yankees call while he\u2019s down there?<\/p>\n<p>But you know what? As it turns out, sometimes good things <i>do<\/i> come to those who wait. Granted, the Scripting Guys aren\u2019t going to write a PowerShell version of the Scriptomatic. But that\u2019s OK, because Ed Wilson <i>has<\/i>.<\/p>\n<p>For those of you don\u2019t know him, Ed Wilson is a Microsoft scripting guru; a world-class educator; and a prolific author. (Prolific? The Scripting Guy who writes this column feels smug because he writes one measly little article each day. Ed Wilson pretty much writes a new <i>book<\/i> each day.) No sooner did Ed finish up with <a href=\"http:\/\/www.microsoft.com\/MSPress\/books\/10329.aspx\" target=\"_blank\"><b>Windows PowerShell Step-by-Step<\/b><\/a> then he turned around and wrote a new book, <a href=\"http:\/\/www.microsoft.com\/MSPress\/books\/9541.aspx\" target=\"_blank\"><b>Windows PowerShell Scripting Guide<\/b><\/a>. And, along with the new book, Ed also found the time to put together the Windows PowerShell Scriptomatic.<\/p>\n<table class=\"dataTable\" id=\"EPE\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p class=\"lastInCell\"><b>Note<\/b>. We have this sinking feeling that the New York Yankees have also called Ed and asked him to take over in centerfield for them. But we\u2019re too afraid to ask Ed about that.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>At any rate, if you\u2019re looking for a quick and easy way to write WMI scripts using Windows PowerShell (and we know that you are), it\u2019s hard to top Ed\u2019s new PowerShell Scriptomatic. For more information, and for a link to the download file, <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/tools\/psomatic.mspx\"><b>click here<\/b><\/a>.<\/p>\n<p>No, not here. Click up there.<\/p>\n<p>That\u2019s better.<\/p>\n<p>So what does all this have to do with you, MM? Well, now that we think about it, not much. After all, the PowerShell Scriptomatic writes WMI scripts, and you don\u2019t really need to (or want to) use WMI here; instead, you want to do ADSI. In this case, the PowerShell Scriptomatic won\u2019t help you all that much.<\/p>\n<p>However, this script should help a little (and, believe it or not, it\u2019s a scripting-related item that Ed Wilson <i>didn\u2019t<\/i> write!):<\/p>\n<pre class=\"codeSample\">$objComputer = [ADSI](\"WinNT:\/\/atl-ws-001,computer\")\n\n$colUsers = ($objComputer.psbase.children |\n    Where-Object {$_.psBase.schemaClassName -eq \"User\"} |\n        Select-Object -expand Name)\n\n$blnFound = $colUsers -contains \"kenmyer\"\n\nif ($blnFound)\n    {\"The user account exists.\"}\nelse\n    {\"The user account does not exist.\"}\n<\/pre>\n<p>Well, there you have it, MM. See you later.<\/p>\n<p>Oh, right: you\u2019d like an explanation of <i>how<\/i> this script works, wouldn\u2019t you? (Trust us, we\u2019d <i>all<\/i> like an explanation of how this script works; there\u2019s some crazy-looking code in there, isn\u2019t there?) Tell you what: let\u2019s break the code down line-by-line and see what we can come up with.<\/p>\n<p>And if we can\u2019t come up with something we have no doubt that Ed Wilson will.<\/p>\n<p>We actually start out in simple enough fashion, using the <b>[ADSI]<\/b> \u201ctype adapter\u201d to make a connection to the computer atl-ws-001. What\u2019s a type adapter? Well, in this case it\u2019s a shortcut way to tell PowerShell that you want to work with ADSI. Could you write this same script without using the type adapter? Sure; however, to do that you\u2019d have to delve into the .NET Framework and create \u2013 and use \u2013 an instance of the System.DirectoryServices.DirectoryEntry class. Needless to say, the type adapter approach is much easier.<\/p>\n<p>Like we said, line 1 is simple enough. Line 2 is a different story, to say the least:<\/p>\n<pre class=\"codeSample\">$colUsers = ($objComputer.psbase.children |\n    Where-Object {$_.psBase.schemaClassName -eq \"User\"} |\n        Select-Object -expand Name)\n<\/pre>\n<p>So what\u2019s going on here? Good question. By default, any time you use Windows PowerShell and ADSI to connect to a computer you get back a limited set of properties and methods for that computer; in fact, all you get back are the following:<\/p>\n<pre class=\"codeSample\">Name                        MemberType \n------                      ----------\nConvertDNWithBinaryToString CodeMethod \nConvertLargeIntegerToInt64  CodeMethod \nName                        Property   \nOperatingSystem             Property   \nOperatingSystemVersion      Property   \nOwner                       Property   \nProcessor                   Property   \nProcessorCount              Property\n<\/pre>\n<p>That\u2019s nice, but \u2013 as you can see \u2013 there\u2019s nothing in the list that suggests we can retrieve a collection of all the user accounts on that computer. Have we already hit a dead end?<\/p>\n<p>No, far from it. When you use Windows PowerShell to connect to an object (not just a computer but any object) PowerShell often makes a \u201cbest guess\u201d as to which properties and methods you are interested in. (OK, it\u2019s not really a guess; instead PowerShell follows a predetermined recipe for returning properties and methods.) Often times that works just fine, but sometimes it doesn\u2019t; sometimes \u2013 like in this case \u2013 you don\u2019t get back the properties and methods that you really need.<\/p>\n<p>That\u2019s where the <b>PSBase<\/b> object comes in. As the name implies (kind of, anyway) the PSBase object is the base on which the PowerShell object was built; more important, the PSBase object contains <i>all<\/i> the properties and methods of the object in question. If we look at the properties and methods of $objComputer.PSBase we see, among <i>many<\/i> properties and methods, the following:<\/p>\n<pre class=\"codeSample\">Children                  Property   System.DirectoryServices.DirectoryEntries Children {get;}\n<\/pre>\n<p>As it turns out, the <b>Children<\/b> property contains all the child objects on the computer; that includes users, groups, printers, services, and what-have-you. In other words, <i>this<\/i> is the property we\u2019ve been looking for.<\/p>\n<p>Of course, the only children we\u2019re interested in at the moment are user accounts. (Um, no offense, Scripting Son.) That\u2019s why we pipe this data to the <b>Where-Object<\/b> cmdlet:<\/p>\n<pre class=\"codeSample\">Where-Object {$_.psBase.schemaClassName -eq \"User\"}\n<\/pre>\n<p>And what are we asking Where-Object to do? We\u2019re asking it to filter out anything that doesn\u2019t have a <b>SchemaClassName<\/b> equal to <i>User<\/i>. In other words, all we want to get back are user accounts.<\/p>\n<table class=\"dataTable\" id=\"ECH\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p><b>Note<\/b>. Good question: what if we wanted only the <i>group<\/i> accounts? Well, in that case our Where-Object command would look like this:<\/p>\n<pre class=\"codeSample\">Where-Object {$_.psbase.schemaclassname -eq \"Group\"}\n<\/pre>\n<p>And so on.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>After we\u2019ve run the data through Where-Object we\u2019re left with a collection containing all the information available about all the user accounts on the computer atl-ws-001. That\u2019s great, except we don\u2019t want all the information available about all the user accounts on the computer; all we want to know is if a user account named kenmyer exists on that machine. How are we supposed to determine <i>that<\/i>?<\/p>\n<p>No doubt there are a number of ways we could do this. For us the easiest approach was to take this collection and pipe it through the <b>Select-Object<\/b> cmdlet, like so:<\/p>\n<pre class=\"codeSample\">Select-Object -expand Name\n<\/pre>\n<p>What\u2019s the point of doing that? Well, all we really care about is the <b>Name<\/b> property; for this script none of the other user account properties matter to us in the least. Therefore, we use Select-Object to filter out all the properties and property values except for the user Name.<\/p>\n<p>So then what\u2019s the <b>\u2013expand<\/b> thing for? Well, when you access the Name property each name comes back in the form of an array; if we just did <b>Select-Object Name<\/b> we\u2019d get back something similar to this:<\/p>\n<pre class=\"codeSample\">{Administrator}\n{ASPNET}\n{Guest}\n{HelpAssistant}\n{jonhaas}\n{kenmyer}\n{SUPPORT_388945a0}\n<\/pre>\n<p>Strange, but true.<\/p>\n<p>Having each name come back as a little miniature array (each array containing a single name) complicates the process of determining whether a particular user account exists or not. Therefore, we use the <b>\u2013expand<\/b> parameter to tell Select-Object to \u201cexpand\u201d the property value; in the case of an array, that simply means that we want to extract each and every value inside that array. That means that, ultimately, $colUsers will contain the following values:<\/p>\n<pre class=\"codeSample\">Administrator\nASPNET\nGuest\nHelpAssistant\njonhaas\nkenmyer\nSUPPORT_388945a0\n<\/pre>\n<p>At this point things become pretty easy. You say we need to determine whether or not a user account named <i>kenmyer<\/i> exists on atl-ws-001? That\u2019s fine; after all, we can now use the <b>\u2013contains<\/b> operator to determine whether or not the value <i>kenmyer<\/i> appears as an item in our collection:<\/p>\n<pre class=\"codeSample\">$blnFound = $colUsers -contains \"kenmyer\"\n<\/pre>\n<p>The \u2013contains operator will return True ($True) if the user account exists, and return False ($False) if the user account doesn\u2019t exist. With that in mind, we can then use the following block of code to check the value of the variable $blnFound, and echo back the appropriate message:<\/p>\n<pre class=\"codeSample\">if ($blnFound)\n    {\"The user account exists.\"}\nelse\n    {\"The user account does not exist.\"}\n<\/pre>\n<p>And <i>that\u2019s<\/i> how this script works!<\/p>\n<p>We hope that helps, MM. (Incidentally, we know you have a few other questions about PowerShell, and we\u2019ll see what we can do about answering them as well.) In the meantime, we encourage everyone to check out the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/tools\/psomatic.mspx\"><b>Windows PowerShell Scriptomatic<\/b><\/a>. Oh, and we encourage the New York Yankees to give the Scripting Guy who writes this column a call. As you guys know better than anyone, you\u2019re currently paying outfielder Johnny Damon $13 million a year; you\u2019re also currently in last place in the American League East. We thought we should let you know that the Scripting Guy who writes this column is prepared to take Johnny Damon\u2019s place, and for a piddling $3 million a year at that.<\/p>\n<p>Oh: and that will almost <i>guarantee<\/i> that you\u2019ll remain in last place in the American League East. Something to think about, eh?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I use Windows PowerShell to determine if a specified local user account exists on a computer?&#8212; MM Hey, MM. Have you ever heard the expression \u201cgood things come to those who wait\u201d? Well, to tell you the truth, the Scripting Guys have never put much credence in that old saying; [&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":[9,23,24,3,45],"class_list":["post-55503","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-adsi","tag-local-accounts-and-windows-nt-4-0-accounts","tag-other-directory-services","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I use Windows PowerShell to determine if a specified local user account exists on a computer?&#8212; MM Hey, MM. Have you ever heard the expression \u201cgood things come to those who wait\u201d? Well, to tell you the truth, the Scripting Guys have never put much credence in that old saying; [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55503","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=55503"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55503\/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=55503"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=55503"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=55503"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}