{"id":66953,"date":"2006-07-07T15:45:00","date_gmt":"2006-07-07T15:45:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2006\/07\/07\/how-can-i-determine-whether-or-not-my-local-users-are-required-to-have-a-password\/"},"modified":"2006-07-07T15:45:00","modified_gmt":"2006-07-07T15:45:00","slug":"how-can-i-determine-whether-or-not-my-local-users-are-required-to-have-a-password","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-determine-whether-or-not-my-local-users-are-required-to-have-a-password\/","title":{"rendered":"How Can I Determine Whether or Not My Local Users are Required to Have a Password?"},"content":{"rendered":"<p><IMG 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\"> \n<P>Hey, Scripting Guy! How can I determine whether or not my local users are required to have a password?<BR><BR>&#8212; GT<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG 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\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"TechNet Script Center\" border=\"0\" alt=\"TechNet Script Center\" align=\"right\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" height=\"288\"><\/A> \n<P>Hey, GT. You know, rather than beat around the bush we decided to come right out and admit it: yes, the rumors that have been circulating around the Internet are true. One of the Scripting Guys, his brothers, his son, and various Scripting Nephews have been playing a strange, customized version of Wiffle Ball in the Scripting Parents\u2019 front yard for more than 20 years. To say that this one-on-one game leans towards the defensive side of things would be an understatement: after all, it\u2019s not unusual to have a game that goes 15 innings before anyone scores. The unofficial record for most runs scored in a game is 5 and, in 20 years of continual, oft-times cut-throat playing, no one has ever hit back-to-back home runs in a game.<\/P>\n<P>Until now. Yes, it\u2019s true: on a recent visit home one of the Scripting Guys (Greg is far too modest to admit that it was he) smacked back-to-back home runs in the fourth inning, and off the Scripting Son, no less. It was, without a doubt, the happiest day of this Scripting Guy\u2019s life. And probably the greatest sporting achievement of the 21<SUP>st<\/SUP> century. (OK, sure, Barry Bonds hit 73 home runs in one season. But home runs are a dime-a-dozen in the big leagues. We\u2019d like to see Barry hit 73 homers in the Scripting Parents\u2019 front yard.)<\/P>\n<TABLE id=\"E4C\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Disclaimer<\/B>. In all fairness, we should note that in the fifth inning one of the balls disappeared forever into the neighbor\u2019s yard while another split in half; consequently, the game ended a bit prematurely. The Scripting Son claims that, because the game did not go five innings, the two home runs do not count. The Scripting Son is wrong.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Of course, by now you\u2019re probably wondering, \u201cWhat the heck does this have to do with determining whether or not local users are required to have a password?\u201d Well, to tell you the truth, GT, absolutely nothing. It\u2019s just that, for the Scripting Guy in question, the high points in his life continue to get fewer and farther between. He has to take a moment to revel in whatever glory he can, whenever he can.<\/P>\n<P>OK; that\u2019s enough reveling. Here\u2019s a script that can determine whether or not local users are required to have a password:<\/P><PRE class=\"codeSample\">Const ADS_UF_PASSWD_NOTREQD = &amp;H0020 <\/p>\n<p>Set colUsers = GetObject(&#8220;WinNT:\/\/atl-fs-01&#8221;)\ncolUsers.Filter = Array(&#8220;User&#8221;)<\/p>\n<p>For Each objUser in colUsers\n   If objUser.UserFlags AND ADS_UF_PASSWD_NOTREQD Then\n        Wscript.Echo objUser.Name &amp; &#8220;: Password not required.&#8221;\n    Else\n        Wscript.Echo objUser.Name &amp; &#8220;: Password required.&#8221;\n    End If\nNext\n<\/PRE>\n<P>You\u2019re right: it\u2019s nowhere <I>near<\/I> as exciting as back-to-back home runs, is it? (But, then again, not <I>everyone<\/I> can hit back-to-back homers, if you know what we mean.) However, while the script might not be very exciting, it <I>is<\/I> kind of useful. With that in mind, let\u2019s sit down and see if we can figure out how it works.<\/P>\n<P>As you can see, we start out by defining a constant named ADS_UF_PASSWD_NOTREQD and setting the value to &amp;H0020; we\u2019ll explain why we do that in just a moment. After that we use this line of code to connect to the System Account Management (SAM) database on the computer atl-fs-01:<\/P><PRE class=\"codeSample\">Set colUsers = GetObject(&#8220;WinNT:\/\/atl-fs-01&#8221;)\n<\/PRE>\n<P>By default, any time we connect to the SAM database we get back information for all sorts of things, including local users, local groups, installed services, installed printers, etc. Because we\u2019re only interested in user accounts we then use the <B>Filter<\/B> property to filter out everything in the returned collection except those self-same user accounts:<\/P><PRE class=\"codeSample\">colUsers.Filter = Array(&#8220;User&#8221;)\n<\/PRE>\n<P>Got all that? Good. Now that we have a collection of all the user accounts (and only the user accounts) found on the computer atl-fs-01, our next step is to examine each of those accounts and determine whether or not a password is required. That\u2019s what we do here:<\/P><PRE class=\"codeSample\">If objUser.UserFlags AND ADS_UF_PASSWD_NOTREQD Then\n<\/PRE>\n<P>Yes, that <I>is<\/I> kind of an odd-looking line of code, isn\u2019t it? As it turns out, information about whether or not a user requires a password is stored in the <B>UserFlags<\/B> attribute. UserFlags is a \u201cbitmask\u201d attribute; that means it\u2019s an attribute that actually contains information about a number of properties, including such things as whether or not a user password expires, whether or not the account itself expires, and whether the user is allowed to change his or her password. For a complete list of properties stored in the UserFlags attribute see the topic <A href=\"http:\/\/msdn.microsoft.com\/library\/en-us\/adsi\/adsi\/ads_user_flag_enum.asp\" target=\"_blank\"><B>ADS_USER_FLAG_ENUM<\/B><\/A> in the ADSI SDK.<\/P>\n<P>Oh, what the heck: here are some of the other more useful properties (as well as their constants and values) that can be managed using UserFlags:<\/P>\n<TABLE id=\"EPE\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Property<\/B><\/P><\/TD>\n<TD>\n<P class=\"lastInCell\"><B>Constant<\/B><\/P><\/TD>\n<TD>\n<P class=\"lastInCell\"><B>Value<\/B><\/P><\/TD><\/TR>\n<TR class=\"evenRecord\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">Logon script will be executed<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">ADS_UF_SCRIPT<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">&amp;H0001<\/P><\/TD><\/TR>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">Account is disabled<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">ADS_UF_ACCOUNTDISABLE<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">&amp;H0002<\/P><\/TD><\/TR>\n<TR class=\"evenRecord\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">Account requires a home directory<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">ADS_UF_HOMEDIR_REQUIRED<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">&amp;H0008<\/P><\/TD><\/TR>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">Account is locked out<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">ADS_UF_LOCKOUT<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">&amp;H0010<\/P><\/TD><\/TR>\n<TR class=\"evenRecord\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">Account does not require a password<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">ADS_UF_PASSWD_NOTREQD<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">&amp;H0020<\/P><\/TD><\/TR>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">User cannot change password<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">ADS_UF_PASSWD_CANT_CHANGE<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">&amp;H0040<\/P><\/TD><\/TR>\n<TR class=\"evenRecord\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">Encrypted text password allowed<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">&amp;H0080<\/P><\/TD><\/TR>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">Account password never expires<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">ADS_UF_DONT_EXPIRE_PASSWD<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">&amp;H10000<\/P><\/TD><\/TR>\n<TR class=\"evenRecord\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">Smartcard required for logon<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">ADS_UF_SMARTCARD_REQUIRED<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">&amp;H40000<\/P><\/TD><\/TR>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\">Password has expired<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">ADS_UF_PASSWORD_EXPIRED<\/P><\/TD>\n<TD>\n<P class=\"lastInCell\">&amp;H800000<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Explaining how bitmask values work lies a bit outside the scope of this column; for more details, see this <A href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkId=24419\" target=\"_blank\"><B>Scripting Guys webcast<\/B><\/A>. For now, we\u2019ll simply note that a bitmask is like a control panel with a series of switches, switches that can either be on or off. When we execute a line of code like <B>If objUser.UserFlags AND ADS_UF_PASSWD_NOTREQD Then<\/B> what we\u2019re really doing is checking to see if the switch labeled ADS_UF_PASSWD_NOTREQD (the switch that tells us whether or not the user is required to have a password) is on. If it is, that means that user does not have to have a password; in turn, we then echo back the user <B>Name<\/B> and the fact that no password is required:<\/P><PRE class=\"codeSample\">script.Echo objUser.Name &amp; &#8220;: Password not required.\n<\/PRE>\n<TABLE id=\"E1H\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P class=\"lastInCell\"><B>Note<\/B>. Be careful not to get mixed up here. Remember, the attribute is <B>Password is not required<\/B>, not <B>Password is required.<\/B> If the switch is on the user doesn\u2019t have to have a password. (Because it\u2019s true that no password is required.)<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>If ADS_UF_PASSWD_NOTREQD is off that means a password <I>is<\/I> required (again, that seems backwards, but think about it for a second). Thus we echo back the fact that this user requires a password:<\/P><PRE class=\"codeSample\">Wscript.Echo objUser.Name &amp; &#8220;: Password required.\n<\/PRE>\n<P>When all is said and done we should get back information similar to this:<\/P><PRE class=\"codeSample\">Administrator: Password required.\nASPNET: Password not required.\nKen Myer: Password required.\npilarackerman: Password required.\nGuest: Password not required.\nHelpAssistant: Password required.\nTest: Password required.\n<\/PRE>\n<P>Very nice.<\/P>\n<P>Admittedly, working with bitmasks can be a bit confusing, especially when it comes time to modify these values. However, simply reading the values isn\u2019t <I>too<\/I> bad: you just need to use the proper constant and value. For example, would you like to know whether or not a user\u2019s password will ever expire? Well, to do that, define a constant named ADS_UF_DONT_EXPIRE_PASSWD, set the value to &amp;H10000, and modify the output section of the script accordingly:<\/P><PRE class=\"codeSample\">Const ADS_UF_DONT_EXPIRE_PASSWD = &amp;H10000 <\/p>\n<p>Set colUsers = GetObject(&#8220;WinNT:\/\/atl-fs-01&#8221;)\ncolUsers.Filter = Array(&#8220;User&#8221;)<\/p>\n<p>For Each objUser in colUsers\n   If objUser.UserFlags AND ADS_UF_DONT_EXPIRE_PASSWD Then\n        Wscript.Echo objUser.Name &amp; &#8220;: Password does not expire.&#8221;\n    Else\n        Wscript.Echo objUser.Name &amp; &#8220;: Password expires.&#8221;\n    End If\nNext\n<\/PRE>\n<P>See? That\u2019s not so bad.<\/P>\n<P>And now for something <I>really<\/I> cool: after hitting back-to-back home runs, on the very next pitch the Scripting Guy lined a double off the birdbath. And then he followed that by &#8211; wait, we\u2019re not done yet; we still have lots more to tell you. In fact, we \u2026 guys? Hello? Guys?<\/P>\n<P>Hmmm; the network must have gone down again.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I determine whether or not my local users are required to have a password?&#8212; GT Hey, GT. You know, rather than beat around the bush we decided to come right out and admit it: yes, the rumors that have been circulating around the Internet are true. One of the Scripting [&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":[23,24,3,5],"class_list":["post-66953","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-local-accounts-and-windows-nt-4-0-accounts","tag-other-directory-services","tag-scripting-guy","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I determine whether or not my local users are required to have a password?&#8212; GT Hey, GT. You know, rather than beat around the bush we decided to come right out and admit it: yes, the rumors that have been circulating around the Internet are true. One of the Scripting [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/66953","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=66953"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/66953\/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=66953"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=66953"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=66953"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}