{"id":67123,"date":"2006-06-13T16:13:00","date_gmt":"2006-06-13T16:13:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2006\/06\/13\/how-can-i-populate-a-list-box-with-the-cns-of-all-the-ous-in-my-domain\/"},"modified":"2006-06-13T16:13:00","modified_gmt":"2006-06-13T16:13:00","slug":"how-can-i-populate-a-list-box-with-the-cns-of-all-the-ous-in-my-domain","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-populate-a-list-box-with-the-cns-of-all-the-ous-in-my-domain\/","title":{"rendered":"How Can I Populate a List Box With the CNs of All the OUs in My Domain?"},"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 populate a list box with the CNs of all the OUs in my domain?<BR><BR>&#8212; AK<\/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=\"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> \n<P>Hey, AK. That\u2019s an interesting question, AK, and we\u2019ll do our best to answer it. Of course, we should point out that the United States soccer team has just finished losing to the Czech Republic in the World Cup, and we\u2019re so broken-hearted and disconsolate that we can barely type, let alone write. Therefore, if this column is poorly-written or if it doesn\u2019t make any sense, well, you understand why.<\/P>\n<TABLE id=\"EYC\" 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>. OK, granted, the Scripting Guy who writes this column doesn\u2019t exactly consider himself a soccer fan; in fact, he spent the weekend watching college baseball on TV rather than the World Cup. In fact, he\u2019s just <I>pretending<\/I> to be broken-hearted; that way he has an excuse in case this turns out to be a less-than-stellar column. (Usually he tries to blame lousy columns on his editor, but she always edits those parts out. But seeing as how she <I>is<\/I> a soccer fan and she <I>is<\/I> disconsolate about the U.S. loss, well, maybe he can sneak this past her.)<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>At any rate, under the most trying of circumstances (like we said, AK, surely you &#8211; and our editor &#8211; understand), here\u2019s what we came up with:<\/P><PRE class=\"codeSample\">&lt;SCRIPT Language=&#8221;VBScript&#8221;&gt;\n    Sub Window_onLoad\n        On Error Resume Next<\/p>\n<p>        Const ADS_SCOPE_SUBTREE = 2<\/p>\n<p>        Set objConnection = CreateObject(&#8220;ADODB.Connection&#8221;)\n        Set objCommand =   CreateObject(&#8220;ADODB.Command&#8221;)\n        objConnection.Provider = &#8220;ADsDSOObject&#8221;\n        objConnection.Open &#8220;Active Directory Provider&#8221;\n        Set objCommand.ActiveConnection = objConnection<\/p>\n<p>        objCommand.Properties(&#8220;Page Size&#8221;) = 1000\n        objCommand.Properties(&#8220;Searchscope&#8221;) = ADS_SCOPE_SUBTREE <\/p>\n<p>        objCommand.CommandText = _\n            &#8220;SELECT Name, ADsPath FROM &#8216;LDAP:\/\/dc=fabrikam,dc=com'&#8221; &amp; _\n                &#8221; WHERE objectCategory=&#8217;organizationalUnit&#8217; ORDER BY Name&#8221;  \n        Set objRecordSet = objCommand.Execute<\/p>\n<p>        objRecordSet.MoveFirst\n        Do Until objRecordSet.EOF\n            Set objOption = Document.createElement(&#8220;OPTION&#8221;)\n            objOption.Text = objRecordSet.Fields(&#8220;Name&#8221;).Value\n            objOption.Value = objRecordSet.Fields(&#8220;ADsPath&#8221;).Value\n            AvailableOUs.Add(objOption)\n            objRecordSet.MoveNext\n        Loop\n    End Sub<\/p>\n<p>    Sub ShowOUPath\n        Msgbox AvailableOUs.Value\n    End Sub\n&lt;\/SCRIPT&gt;<\/p>\n<p>&lt;body&gt;\n    &lt;select size=&#8221;10&#8243; name=&#8221;AvailableOUs&#8221; style=&#8221;width:300&#8243;&gt;&lt;\/select&gt;&lt;p&gt;\n    &lt;input id=runbutton type=&#8221;button&#8221; value=&#8221;Show OU Path&#8221; onClick=&#8221;ShowOUPath&#8221;&gt;\n&lt;\/body&gt;\n<\/PRE>\n<P>This is a bit longer than most of the scripts you see in this column, so let\u2019s take care of the easy things first. To begin with, the body of the HTA consists of just two items, a list box named AvailableOUs and a button with the label <B>Show OU Path<\/B>:<\/P><PRE class=\"codeSample\">&lt;select size=&#8221;10&#8243; name=&#8221;AvailableOUs&#8221; style=&#8221;width:300&#8243;&gt;&lt;\/select&gt;&lt;p&gt;\n&lt;input id=runbutton type=&#8221;button&#8221; value=&#8221;Show OU Path&#8221; onClick=&#8221;ShowOUPath&#8221;&gt;\n<\/PRE>\n<TABLE id=\"EUD\" class=\"dataTable\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD>\n<P><B>Note<\/B>. If you aren\u2019t familiar with HTAs, well, too bad!<\/P>\n<P>Um, we mean, check out the <A href=\"http:\/\/null\/technet\/scriptcenter\/hubs\/htas.mspx\"><B>HTA Developers Center<\/B><\/A> here in the Script Center. Sorry; you know, what with the U.S. losing and everything, well, we\u2019re just not ourselves today.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Both of these controls are pretty rudimentary. The button has been configured to run a subroutine named ShowOUPath any time said button gets clicked. Meanwhile, we don\u2019t do much with the list box other than configure it to show 10 items at a time (<B>size=&#8221;10&#8243;<\/B>) and to be 300 pixels wide (<B>style=&#8221;width:300&#8243;<\/B>). As you can see, we didn\u2019t even specify any items to appear in this list box. That\u2019s by design: after all, we want to dynamically populate the list box with the names of the OUs in our domain.<\/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><B>Note<\/B>. Yes, you <I>did<\/I> say you wanted to populate the list box with the <I>CNs<\/I> of all your OUs. We decided to go with Name simply because the CN is an optional attribute and won\u2019t necessarily be configured for all your OUs. However, we\u2019ll show you how to modify the code to use the CN if you so desire.<\/P>\n<P>No, we\u2019re not doing this because of the World Cup. We\u2019re <I>always<\/I> nice like that!<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>As for the subroutine ShowOUPath, all we do there is echo back the ADsPath for the OU selected in the list box (as you\u2019ll see, the corresponding ADsPath is assigned as the value for each OU in the list box):<\/P><PRE class=\"codeSample\">Msgbox AvailableOUs.Value\n<\/PRE>\n<P>That\u2019s not particularly exciting, but it <I>is<\/I> useful: after all, if you know the ADsPath then you can bind directly to the OU in Active Directory. <\/P>\n<P>That leaves us with the two most important aspects of this code: retrieving the list of OUs from Active Directory, and dynamically adding those OUs to a list box. We\u2019ve included both of these tasks within a single subroutine named Window_onLoad. As you probably know, any time an HTA or Web page includes a subroutine named Winodw_onLoad, that subroutine is automatically invoked any time the HTA\/page is loaded or refreshed. By placing these two tasks in Window_onLoad we ensure that each time we start the HTA we\u2019ll conduct an Active Directory search and load an up-to-date set of OU names into the list box.<\/P>\n<P>As we noted, to retrieve the list of OUs we do an Active Directory search; that\u2019s what this big block of code is all about:<\/P><PRE class=\"codeSample\">Const ADS_SCOPE_SUBTREE = 2<\/p>\n<p>Set objConnection = CreateObject(&#8220;ADODB.Connection&#8221;)\nSet objCommand =   CreateObject(&#8220;ADODB.Command&#8221;)\nobjConnection.Provider = &#8220;ADsDSOObject&#8221;\nobjConnection.Open &#8220;Active Directory Provider&#8221;\nSet objCommand.ActiveConnection = objConnection<\/p>\n<p>objCommand.Properties(&#8220;Page Size&#8221;) = 1000\nobjCommand.Properties(&#8220;Searchscope&#8221;) = ADS_SCOPE_SUBTREE <\/p>\n<p>objCommand.CommandText = _\n    &#8220;SELECT Name, ADsPath FROM &#8216;LDAP:\/\/dc=fabrikam,dc=com'&#8221; &amp; _\n        &#8221; WHERE objectCategory=&#8217;organizationalUnit&#8217; ORDER BY Name&#8221;  \nSet objRecordSet = objCommand.Execute<\/p>\n<p>objRecordSet.MoveFirst\n<\/PRE>\n<P>Incidentally, we won\u2019t be able to discuss the details behind conducting an Active Directory search; that\u2019s well beyond the scope of our daily column. If you need those whys and wherefores, take a look at our two-part <I>Tales from the Script<\/I> series <A href=\"http:\/\/null\/technet\/scriptcenter\/resources\/tales\/sg0405.mspx\"><B>Dude, Where\u2019s My Printer?<\/B><\/A><\/P>\n<P>Instead, the only thing we\u2019ll make particular note of is the query we use to retrieve our information: <\/P><PRE class=\"codeSample\">objCommand.CommandText = _\n    &#8220;SELECT Name, ADsPath FROM &#8216;LDAP:\/\/dc=fabrikam,dc=com'&#8221; &amp; _\n        &#8221; WHERE objectCategory=&#8217;organizationalUnit&#8217; ORDER BY Name&#8221;\n<\/PRE>\n<P>All we\u2019re doing here is asking for the <B>Name<\/B> and the <B>ADsPath<\/B> of all the objects in the fabrikam.com domain that have an <B>objectCategory<\/B> equal to <I>organizationalUnit<\/I>. It probably goes without saying that any object with an objectCategory equal to organizationalUnit will be an OU. Oh: and because a list like this is much easier to deal with when the items are presented in alphabetical order, we\u2019ve tacked on this clause to sort the returned data by name: <B>ORDER BY Name<\/B>.<\/P>\n<P>Good point: suppose you <I>do<\/I> want to return the CN rather than the Name. That\u2019s fine; just replace any reference to the Name attribute with the CN attribute instead:<\/P><PRE class=\"codeSample\">objCommand.CommandText = _\n    &#8220;SELECT CN, ADsPath FROM &#8216;LDAP:\/\/dc=fabrikam,dc=com'&#8221; &amp; _\n        &#8221; WHERE objectCategory=&#8217;organizationalUnit&#8217; ORDER BY CN&#8221;\n<\/PRE>\n<P>And now &#8211; at long last &#8211; we get to the heart of the matter: adding the OUs to the list box. After we call the <B>Execute<\/B> method and run our query against Active Directory we get back a recordset consisting of the Name and ADsPath of each OU in the domain. To add these OUs to the list box we use the following block of code:<\/P><PRE class=\"codeSample\">Do Until objRecordSet.EOF\n    Set objOption = Document.createElement(&#8220;OPTION&#8221;)\n    objOption.Text = objRecordSet.Fields(&#8220;Name&#8221;).Value\n    objOption.Value = objRecordSet.Fields(&#8220;ADsPath&#8221;).Value\n    AvailableOUs.Add(objOption)\n    objRecordSet.MoveNext\nLoop\n<\/PRE>\n<P>What\u2019s going on here? Well, to begin with, we set up a Do Until loop that which runs until we reach the end of the recordset (<B>objRecordset.EOF<\/B>). Inside that loop we use the <B>createElement<\/B> method to create a \u201cblank\u201d list box item. For this new list box item we set the <B>Text<\/B> property to the OU Name and the <B>Value<\/B> property to the OU ADsPath:<\/P><PRE class=\"codeSample\">objOption.Text = objRecordSet.Fields(&#8220;Name&#8221;).Value\nobjOption.Value = objRecordSet.Fields(&#8220;ADsPath&#8221;).Value\n<\/PRE>\n<TABLE id=\"EHH\" 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\u2019ve decided to use the CN rather than the name, just change the code accordingly: objRecordSet.Fields(&#8220;<B>CN<\/B>&#8220;).Value.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>If you aren\u2019t familiar with HTML, the Text property is simply the text that appears in the list box; the Value property is, well, a value associated with the item. Although the Text and the Value can be identical, they don\u2019t have to be. We chose to use the Name for the Text property because that gives us nice, easy-to-read names like this:<\/P>\n<TABLE border=\"0\" cellSpacing=\"0\" cellPadding=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Administration<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Finance<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Human Resources<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Research<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>Sales<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>We then use the ADsPath as the Value; that makes it easy for someone to choose an OU, click a button, and then bind to the selected OU. The ADsPaths will look something like this:<\/P>\n<TABLE border=\"0\" cellSpacing=\"0\" cellPadding=\"0\">\n<TBODY>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>LDAP:\/\/ou=Administration,dc=fabrikam,dc=com<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>LDAP:\/\/ou=Finance,dc=fabrikam,dc=com<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>LDAP:\/\/ou=Human Resources,dc=fabrikam,dc=com<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>LDAP:\/\/ou=Research,dc=fabrikam,dc=com<\/P><\/TD><\/TR>\n<TR>\n<TD class=\"listBullet\" vAlign=\"top\">\u2022<\/TD>\n<TD class=\"listItem\">\n<P>LDAP:\/\/ou=Sales,dc=fabrikam,dc=com<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<P>As you can see, the ADsPath &#8211; while important to have &#8211; doesn\u2019t make for very good labels within the list box. <I>That\u2019s<\/I> why we use the Name as the text that appears in the list box.<\/P>\n<P>After assigning values to the Text and Value properties we then call the <B>Add<\/B> method to add the new item to the list box:<\/P><PRE class=\"codeSample\">AvailableOUs.Add(objOption)\n<\/PRE>\n<P>Believe it or not, that\u2019s all we have to do. We call the <B>MoveNext<\/B> method to move to the next item in the recordset and then repeat the process, adding the second OU to the list box. This continues until we\u2019ve reached the end of the recordset and &#8211; not coincidentally &#8211; added all the OUs to the list box. <\/P>\n<P>And now we really <I>should<\/I> get to work on our next column. Of course, that\u2019s not going to be easy, knowing that the U.S. likely needs to beat Ghana <I>and<\/I> Italy in order to advance. But, hey, the show must go on, right? Seeing as how it\u2019s annual review time, we hope our manager will appreciate how we soldier on even though we\u2019ve been emotionally devastated. <\/P>\n<P>No check that: the emotional devastation usually comes <I>after<\/I> we\u2019ve had our review.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I populate a list box with the CNs of all the OUs in my domain?&#8212; AK Hey, AK. That\u2019s an interesting question, AK, and we\u2019ll do our best to answer it. Of course, we should point out that the United States soccer team has just finished losing to the Czech [&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,4,30],"class_list":["post-67123","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-scripting-techniques","tag-web-pages-and-htas"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I populate a list box with the CNs of all the OUs in my domain?&#8212; AK Hey, AK. That\u2019s an interesting question, AK, and we\u2019ll do our best to answer it. Of course, we should point out that the United States soccer team has just finished losing to the Czech [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/67123","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=67123"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/67123\/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=67123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=67123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=67123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}