{"id":66003,"date":"2006-11-20T14:15:00","date_gmt":"2006-11-20T14:15:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2006\/11\/20\/how-can-i-add-a-user-to-a-group-if-i-dont-know-the-distinguished-name-of-that-user\/"},"modified":"2006-11-20T14:15:00","modified_gmt":"2006-11-20T14:15:00","slug":"how-can-i-add-a-user-to-a-group-if-i-dont-know-the-distinguished-name-of-that-user","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-add-a-user-to-a-group-if-i-dont-know-the-distinguished-name-of-that-user\/","title":{"rendered":"How Can I Add a User to a Group If I Don&#8217;t Know the Distinguished Name of That User?"},"content":{"rendered":"<p><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\"><\/p>\n<p>Hey, Scripting Guy! How can I add a user to an Active Directory group if I don\u2019t know the distinguished name of that user?<\/p>\n<p>&#8212; VO<\/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\"><a href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><img decoding=\"async\" class=\"farGraphic\" title=\"Script Center\" border=\"0\" alt=\"Script Center\" align=\"right\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" height=\"288\"><\/a><\/p>\n<p>Hey, VO. You know, if we wanted to take the easy way out here we\u2019d just tell you, \u201cSorry, but if you don\u2019t know the distinguished name of the user you <i>can\u2019t<\/i> add that user to an Active Directory group.\u201d <\/p>\n<table id=\"E6C\" 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>. If you want to get technical, even the distinguished name isn\u2019t good enough: you really need to know the ADsPath of the user (a value similar to this: <b>LDAP:\/\/cn=Ken Myer, ou=Finance, dc=fabrikam, dc=com<\/b>). But we\u2019ll let that slide; after all, if you <i>do<\/i> have the distinguished name (<b>cn=Ken Myer, ou=Finance, dc=fabrikam, dc=com<\/b>) then you can generate the ADsPath just by sticking <b>LDAP:\/\/<\/b> on the front.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>In other words, if we just wanted to dismiss this question without even trying, pointing out that this simply can\u2019t be done, well, we\u2019d be well within our rights to do so; after all, it <i>can\u2019t<\/i> be done. But you know what? That would be taking the easy way out. And when have you ever known the Scripting Guys to take the easy way out?<\/p>\n<p>OK, true: we forgot about that. And that. That other time? Well, that wasn\u2019t really our fault; we did the best we could. The entire month of July? Come on, it was <i>summer<\/i>, for crying out loud; everyone takes the easy way out during the summer. And \u2013 well, OK, we get the point. But this time we absolutely will <i>not<\/i> take the easy way out. No way.<\/p>\n<p>Well, OK. But at least we\u2019ll answer your question.<\/p>\n<p>Let\u2019s recap the situation here. We want to add a user to an Active Directory group. To do that we need to know the ADsPath for the user. However, we <i>don\u2019t<\/i> know the ADsPath for the user. Our prospects for success here seem kind of bleak, don\u2019t they?<\/p>\n<p>Nah. You say you don\u2019t know the ADsPath for the user? That\u2019s fine; we\u2019ll just go out and <i>find<\/i> the ADsPath for the user:<\/p>\n<pre class=\"codeSample\">On Error Resume Next\nConst ADS_SCOPE_SUBTREE = 2\nSet objConnection = CreateObject(\"ADODB.Connection\")\nSet objCommand =   CreateObject(\"ADODB.Command\")\nobjConnection.Provider = \"ADsDSOObject\"\nobjConnection.Open \"Active Directory Provider\"\nSet objCommand.ActiveConnection = objConnection\nobjCommand.Properties(\"Page Size\") = 1000\nobjCommand.Properties(\"Searchscope\") = ADS_SCOPE_SUBTREE\nobjCommand.CommandText = _\n    \"SELECT ADsPath FROM 'LDAP:\/\/dc=fabrikam,dc=com' WHERE objectCategory='user' \" &amp; _\n        \"AND samAccountName = 'kenmyer'\"\nSet objRecordSet = objCommand.Execute\nobjRecordSet.MoveFirst\nDo Until objRecordSet.EOF\n    strADsPath = objRecordSet.Fields(\"ADsPath\").Value\n    Set objGroup = GetObject(\"LDAP:\/\/cn=Finance Managers,ou=Finance,dc=fabrikam,dc=com\")\n    objGroup.Add(strADsPath)\n    objRecordSet.MoveNext\nLoop\n<\/pre>\n<p>What we\u2019re doing here is assuming that you know <i>something<\/i> about the user in question. (Admittedly if you don\u2019t know <i>anything<\/i> about the user then it\u2019s going to be a bit more difficult to locate that user and add him or her to a group.) For example, even though you don\u2019t know the user\u2019s distinguished name there\u2019s a very good chance that you know his or her <b>samAccountName<\/b> (which, for all intents and purposes, is just the user\u2019s logon name). Therefore, all we have to do is search Active Directory for a user with that particular samAccountName (a good attribute to search for, by the way, because samAccountNames must be unique within a domain). After we locate the user we can grab his or her ADsPath. And once we have the ADsPath we <i>can<\/i> add that user to an Active Directory group.<\/p>\n<p>That\u2019s exactly what we do in our script. At the risk of taking the easy way out (heaven forbid!) we won\u2019t explain the ins and outs of searching Active Directory in any detail today; if you need more information take a look at our two-part series <a href=\"http:\/\/null\/technet\/scriptcenter\/resources\/tales\/sg0405.mspx\"><b>Dude, Where\u2019s My Printer?<\/b><\/a> About all we <i>will<\/i> do is point out that this is the query we use to search the fabrikam.com domain (<b>&#8216;<\/b><b>LDAP:\/\/dc=fabrikam,dc=com&#8217;<\/b>) for a user (<b>objectCategory=\u2019user\u2019<\/b>) that has a logon name of <i>kenmyer<\/i> (<b>samAccountName = &#8216;kenmyer&#8217;<\/b>):<\/p>\n<pre class=\"codeSample\">objCommand.CommandText = _\n    \"SELECT ADsPath FROM 'LDAP:\/\/dc=fabrikam,dc=com' WHERE objectCategory='user' \" &amp; _\n        \"AND samAccountName = 'kenmyer'\"\n<\/pre>\n<p>When we execute this query (using the <b>Execute<\/b> method) we\u2019ll get back a recordset containing the ADsPath of each and every user who has the samAccountName <i>kenmyer<\/i>. Because samAccountNames must be unique in the domain, that recordset will contain \u2013 at most \u2013 just one item: the ADsPath of the user we want to add to the group.<\/p>\n<p>That\u2019s great, except for one thing: now that we have a recordset what do we do with it? Well, to begin with, we set up a Do Until loop that runs until we\u2019ve looped through all the records in our recordset; in other words until the recordset\u2019s <b>EOF<\/b> (end-of-file) property is True. (And yes, we need to set up a loop like this even though we\u2019ll never have more than one record in the recordset.) Inside that loop we use this line of code to grab the value of the user\u2019s ADsPath and store it in a variable named strADsPath:<\/p>\n<pre class=\"codeSample\">strADsPath = objRecordSet.Fields(\"ADsPath\").Value\n<\/pre>\n<p>Once we have the ADsPath we can then add the user to the group. That\u2019s a task that requires two lines of code: one line to bind to the group account in Active Directory; the other to call the <b>Add<\/b> method and add the new group member, making sure we pass the ADsPath of the user to the Add method. In other words:<\/p>\n<pre class=\"codeSample\">Set objGroup = GetObject(\"LDAP:\/\/cn=Finance Managers,ou=Finance,dc=fabrikam,dc=com\")\nobjGroup.Add(strADsPath)\n<\/pre>\n<p>After adding the user to the group we call the <b>MoveNext<\/b> method to advance to the next record in the recordset. Because we don\u2019t <i>have<\/i> a next record in our recordset that causes us to exit the loop, which in turn brings the script to a close. The net result? The user gets added to the group, and without us doing very much beyond writing a few lines of code, most of which is boilerplate code for searching Active Directory.<\/p>\n<p>In all fairness, we should add that, at least when it comes to being lazy and not trying very hard, the Scripting Guys are mere amateurs compared to some people. Several years ago the Scripting Guy who writes this column came home to find that his cable TV was no longer working. When he called the cable company (which has since gone out of business) he was told that the cable had been shut off because he hadn\u2019t paid his bill.<\/p>\n<p>\u201cI\u2019m <i>positive<\/i> we paid the bill,\u201d said the Scripting Guy, \u201cLet me get the checkbook and \u2013\u201c<\/p>\n<p>\u201cWould that be check number 1895, dated July 14th?\u201d interrupted the cable guy.<\/p>\n<p>\u201cYes,\u201d said the Scripting Guy. \u201cHow did you know that?\u201d<\/p>\n<p>\u201cI\u2019m looking at the check right now,\u201d said the cable guy. \u201cApparently we received it about three weeks ago. However, Marcie has been on vacation since then so it\u2019s just been sitting on her desk. I was supposed to enter all these checks into the computer, but I haven\u2019t gotten around to it.\u201d<\/p>\n<p>\u201cSo you shut off our cable for non-payment of our bill even though you received our payment three weeks ago?\u201d asked the Scripting Guy.<\/p>\n<p>\u201cYeah. Kind of funny, isn\u2019t it?\u201d<\/p>\n<p>Well, not really. What <i>was<\/i> funny was when the cable guy said it would take an additional three weeks to restore service. <\/p>\n<p>\u201cWait a minute,\u201d said the Scripting Guy who writes this column. \u201cIt takes three weeks to restore existing service, yet you can activate a brand-new account in a week?\u201d<\/p>\n<p>\u201cThese things take time,\u201d replied the cable guy, who paused for a moment and then added, \u201cThere: I just flipped the switch and your cable has been restored. Try not to let this happen again, OK?\u201d<\/p>\n<p>Now <i>that<\/i> was a company who knew about taking the easy way out!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I add a user to an Active Directory group if I don\u2019t know the distinguished name of that user? &#8212; VO Hey, VO. You know, if we wanted to take the easy way out here we\u2019d just tell you, \u201cSorry, but if you don\u2019t know the distinguished name of the [&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":[7,19,3,5],"class_list":["post-66003","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-active-directory","tag-activex-data-objects-ado","tag-scripting-guy","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I add a user to an Active Directory group if I don\u2019t know the distinguished name of that user? &#8212; VO Hey, VO. You know, if we wanted to take the easy way out here we\u2019d just tell you, \u201cSorry, but if you don\u2019t know the distinguished name of the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/66003","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=66003"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/66003\/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=66003"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=66003"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=66003"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}