<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Decrypt my World : ADSI</title><link>http://blogs.msdn.com/alejacma/archive/tags/ADSI/default.aspx</link><description>Tags: ADSI</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>How to get LastLogon property for all users in a Domain (VBScript)</title><link>http://blogs.msdn.com/alejacma/archive/2009/03/12/how-to-get-lastlogon-property-for-all-users-in-a-domain-vbscript.aspx</link><pubDate>Thu, 12 Mar 2009 13:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9471522</guid><dc:creator>alejacma</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9471522.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9471522</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;The following &lt;STRONG&gt;VBScript sample &lt;/STRONG&gt;retrieves &lt;STRONG&gt;all users in Active Directory that haven't ever logged on the domain, or haven't logged on for at least maxDays &lt;/STRONG&gt;(an argument passed to the script):&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;On Error Resume Next

' Constants
'
Const ONE_HUNDRED_NANOSECOND = .000000100
Const SECONDS_IN_DAY = 86400

' Get Max Days as an argument passed to the script
'
If Not Wscript.Arguments.Count() = 1 Then
  Wscript.Echo "Syntax error, argument required"
  Wscript.Quit
End If

maxDays = CInt(Wscript.Arguments(0))

' Create the log file
'
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objLogFile = objFSO.CreateTextFile(GetPath() &amp;amp; "log.txt", 8, true)

' Get the root of the domain
'
Set objRoot = Getobject("LDAP://RootDSE")
strRoot = objRoot.Get("defaultnamingcontext")
Set objRoot = Nothing

' Create connection
'
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"

' Create command
'
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000

' Execute command to get all DCs in the domain
'
objCommand.CommandText = "&amp;lt;LDAP://OU=Domain Controllers," &amp;amp; strRoot &amp;amp; "&amp;gt;;(objectcategory=computer);name;onelevel"
Set objRecordSet = objCommand.Execute

'LogData("INFO: There are " &amp;amp; objRecordSet.RecordCount &amp;amp; " Domain Controllers.")

' Execute command to get all users in the domain
'
objCommand.CommandText = "&amp;lt;LDAP://" &amp;amp; strRoot &amp;amp; "&amp;gt;;(&amp;amp;(objectclass=user)(objectcategory=person));adspath,distinguishedname,sAMAccountName;subtree"
Set objRecordSet2 = objCommand.Execute

'LogData("INFO: There are " &amp;amp; objRecordSet2.RecordCount &amp;amp; " users.")

' Get the LastLogon for each user in each DC
'
Do Until objRecordSet2.EOF

  ' Get the LastLogon for one user in each DC, and get the maximum
  '
  objRecordSet.MoveFirst
  maxDate = 0
  Do Until objRecordSet.EOF

    ' Execute command to get LastLogon for the user in one DC
    '
    LdapPath = "LDAP://" &amp;amp; objRecordSet.Fields("name").Value &amp;amp; "/" &amp;amp; Replace(objRecordSet2.Fields("distinguishedname").Value, "/", "\/")
    set objUser = GetObject(LdapPath)

    ' Check for errors executing the command
    '
    if Err.Number &amp;lt;&amp;gt; 0 Then
      ' Error
      '
      LogData("INFO: LDAP Path = " &amp;amp; LdapPath)
      Select Case Err.Number
        Case &amp;amp;H8007203A
          Err.Description = """The server is not operational"""
        Case &amp;amp;H80005000
          Err.Description = """An invalid ADSI pathname was passed"""
        Case Else
          Err.Description = ""
      End Select 
      LogData("ERROR: " &amp;amp; Err.Number &amp;amp; " " &amp;amp; Err.Description)
    Else
      ' No error
      '
      ' Get the LastLogon
      '
      set objLastLogon = objUser.LastLogon
      myDate = 0
      If Not(IsNull(objLastLogon) Or IsEmpty(objLastLogon)) Then
        myDate = MakeDate(objLastLogon)
      End If

      ' See if it's the maximum
      '
      If myDate &amp;gt; maxDate Then
        maxDate = myDate
      End If

    End If

    ' Move on to the next DC
    '
    Err.Clear
    set objUser = nothing
    set objLastLogon = nothing
    objRecordSet.MoveNext

  Loop

  ' Show the maximum LastLogon for the user
  '
  If maxDate = 0 Then
    LogData("INFO: User """ &amp;amp; objRecordSet2.Fields("sAMAccountName").Value &amp;amp; """ never logged on.")
  ElseIf (Date() - maxDate) &amp;gt; maxDays Then 
    LogData("INFO: User """ &amp;amp; objRecordSet2.Fields("sAMAccountName").Value &amp;amp; """ logged on " &amp;amp; maxDate)
  End If

  ' Move on to the next user
  '
  objRecordSet2.MoveNext

Loop


' Close everything
'
objRecordSet.Close
Set objRecordSet = Nothing
objRecordSet2.Close
Set objRecordSet2 = Nothing
Set objCommand = Nothing
objConnection.Close
Set objConnection = Nothing

' We are done!
'
Wscript.Echo "All Done!"


'================================================================
' HELPER FUNCTIONS
'================================================================

' Get script's path
'
Function GetPath()

  Dim path
  path = WScript.ScriptFullName
  GetPath = Left(path, InStrRev(path, "\"))

End Function


' Write data to log file
'
Sub LogData(data)

  objLogFile.writeline Now() &amp;amp; ", " &amp;amp; data

End Sub


' Convert long integer to a date
'
Function MakeDate(oLInt)

  Set objShell = CreateObject("Wscript.Shell")

  lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias")

  If UCase(TypeName(lngBiasKey)) = "LONG" Then
    glngBias = lngBiasKey

  ElseIf UCase(TypeName(lngBiasKey)) = "VARIANT()" Then
    glngBias = 0

    For k = 0 To UBound(lngBiasKey)
      glngBias = lngBias + (lngBiasKey(k) * 256^k)
    Next
  End If 

  dtmDate = #1/1/1601# + (((oLInt.HighPart * (2 ^ 32)) + oLInt.LowPart) / 600000000 - glngBias) / 1440

  MakeDate = dtmDate

End Function
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9471522" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/VBScript/default.aspx">VBScript</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/ADSI/default.aspx">ADSI</category></item><item><title>How to get more than 1000 group members including foreign SAMs (VBScript)</title><link>http://blogs.msdn.com/alejacma/archive/2008/08/05/how-to-get-more-than-1000-group-members-including-foreign-sams-vbscript.aspx</link><pubDate>Tue, 05 Aug 2008 10:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8833391</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8833391.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8833391</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;We may have a &lt;STRONG&gt;group &lt;/STRONG&gt;in our &lt;STRONG&gt;Active Directory&lt;/STRONG&gt; with &lt;STRONG&gt;members&lt;/STRONG&gt; from a &lt;STRONG&gt;foreign domain&lt;/STRONG&gt;. We may try to retrieve all those members with &lt;STRONG&gt;ADSI&lt;/STRONG&gt; and a code like this: &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa746518.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa746518.aspx"&gt;Using IADs::GetInfoEx for Range Retrieval&lt;/A&gt;. The issue with this code is that we will only be able to see the &lt;STRONG&gt;SID&lt;/STRONG&gt; of &lt;STRONG&gt;foreign principals&lt;/STRONG&gt; (i.e. CN=S-1-5-21-1234567890...-123,CN=ForeignSecurityPrincipals,DC=domain,DC=com), which may not be very useful for us.&lt;/P&gt;
&lt;P&gt;The following &lt;STRONG&gt;sample&lt;/STRONG&gt; (based on above &lt;STRONG&gt;Range Retrieval&lt;/STRONG&gt; sample) will retrieve &lt;STRONG&gt;all members in a group&lt;/STRONG&gt; (&lt;STRONG&gt;including foreign principals&lt;/STRONG&gt;) and show their &lt;STRONG&gt;sAMAccountName&lt;/STRONG&gt;:&lt;/P&gt;&lt;PRE&gt;' PARAMETERS.
'
strFileName = "c:\List.txt"
strGroupDN = "CN=groupName,CN=Users,DC=domainName,DC=com"

' Bind to the group with the current credentials.
'
Set oGroup = GetObject("LDAP://" &amp;amp; strGroupDN)

' Create file for results.
'
Set fs = CreateObject("Scripting.FileSystemObject")
Set usersFile = fs.CreateTextFile(strFileName, True)

' For compatibility with all operating systems, the number of objects
' retrieved by each query should not exceed 999. The number of objects
' to retrieve should be as close as possible to 999 to reduce the number
' of round trips to the server necessary to retrieve the objects.
rangeStep = 999
lowRange = 0
highRange = lowRange + rangeStep

Do
  ' Use the "member;range=&amp;lt;lowRange&amp;gt;-&amp;lt;highRange&amp;gt;" syntax.
  '
  strCommandText = "member;range=" &amp;amp; lowRange &amp;amp; "-" &amp;amp; highRange
  usersFile.WriteLine(vbCrLf &amp;amp; "Current search command: " &amp;amp; _
  strCommandText &amp;amp; vbCrLf)

  ' Load the specified range of members into the local cache. This 
  ' will throw an error if the range exceeds the properties contained 
  ' in the object. The "On Error GoTo quit" error handler will cause 
  ' the loop to terminate when this happens.
  '
  On Error Resume Next
  oGroup.GetInfoEx Array(strCommandText), 0
  If Err.Number = &amp;amp;H80072020 Then
    Exit Do
  End If
  On Error Goto 0

  ' Enumerate the retrieved members.
  '
  oMembers = oGroup.Get("member")
  If vbArray And VarType(oMembers) Then
    For Each oMember In oMembers
      ' Add the member.
      '            
      Set oUser = GetObject("LDAP://" &amp;amp; oMember)            
      If (oUser.Class = "foreignSecurityPrincipal") Then

        usersFile.WriteLine(GetForeignSAM(oUser))
      Else
        usersFile.WriteLine(oUser.sAMAccountName)
      End If 
      nRetrieved = nRetrieved + 1
    Next
  Else
    ' oGroup.Get returned only one member, so add it to the list.
    '
    Set oUser = GetObject("LDAP://" &amp;amp; oMembers)            
    If (oUser.Class = "foreignSecurityPrincipal") Then

      usersFile.WriteLine(&lt;STRONG&gt;GetForeignSAM&lt;/STRONG&gt;(oUser))
    Else
      usersFile.WriteLine(oUser.sAMAccountName)
    End If 

    nRetrieved = nRetrieved + 1
  End If

  ' Increment the high and low ranges to query for the next block of 
  ' objects.
  '
  lowRange = highRange + 1
  highRange = lowRange + rangeStep
Loop While True

MsgBox "File """ &amp;amp; strFileName &amp;amp;  """ created"


'-----------------------------------------------------------------------
' HELPER FUNCTIONS
'-----------------------------------------------------------------------
&lt;STRONG&gt;function GetForeignSAM&lt;/STRONG&gt; (oUser)
  ' CONSTANTS.
  '
  ADS_SID_RAW = 0
  ADS_SID_HEXSTRING = ADS_SID_RAW + 1
  ADS_SID_SAM = ADS_SID_HEXSTRING + 1
  ADS_SID_UPN = ADS_SID_SAM + 1
  ADS_SID_SDDL = ADS_SID_UPN + 1
  ADS_SID_WINNT_PATH = ADS_SID_SDDL + 1

  ' Get the SID
  '

  ' Now, resolve the SID into its sAMAcountName.
  '
  set oADsSID = CreateObject("&lt;STRONG&gt;ADsSID&lt;/STRONG&gt;")
  oADsSID.&lt;STRONG&gt;SetAs ADS_SID_RAW&lt;/STRONG&gt;, oUser.Get("objectSid")

  ' Requesting the Sam Account Name
  '
  GetForeignSAM = oADsSID.&lt;STRONG&gt;GetAs(ADS_SID_SAM)&lt;/STRONG&gt;	

end function
&lt;/PRE&gt;
&lt;P&gt;Note: &lt;STRONG&gt;ADsSID&lt;/STRONG&gt; object is implemented in &lt;STRONG&gt;ADsSecurity.dll&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8833391" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/VBScript/default.aspx">VBScript</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/ADSI/default.aspx">ADSI</category></item><item><title>System.DirectoryServices.DirectorySynchronization returns access denied with non-admin users</title><link>http://blogs.msdn.com/alejacma/archive/2008/06/20/system-directoryservices-directorysynchronization-returns-access-denied-with-non-admin-users.aspx</link><pubDate>Fri, 20 Jun 2008 10:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8624980</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8624980.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8624980</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;You may get an &lt;STRONG&gt;Access Denied&lt;/STRONG&gt; error (&lt;STRONG&gt;COMException&amp;nbsp;0x80070005&lt;/STRONG&gt;) when using &lt;STRONG&gt;System.DirectoryServices.DirectorySynchronization&lt;/STRONG&gt; in your &lt;STRONG&gt;.NET&lt;/STRONG&gt; application with a &lt;STRONG&gt;non-admin user&lt;/STRONG&gt;, but everything works fine with a domain administrator.&lt;/P&gt;
&lt;P mce_keep="true"&gt;This issue will happen if we use DirectorySynchronization this way:&lt;/P&gt;&lt;PRE&gt;DirectorySearcher directorySearcher = new DirectorySearcher(rootPath);
directorySearcher.DirectorySynchronization = new DirectorySynchronization();
&lt;/PRE&gt;
&lt;P&gt;If we want to run this code as it is, we need to pass administrative credentials. If we are using standard user credentials we need to pass the right Flag saying that this is a normal user who do not have all the rights over Active Directory.&lt;/P&gt;
&lt;P&gt;To understand this in detail please see this article which talks about the flags we can pass to DirectorySynchronization constructor: &lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://msdn.microsoft.com/en-us/library/system.directoryservices.directorysynchronizationoptions.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.directoryservices.directorysynchronizationoptions.aspx"&gt;DirectorySynchronizationOptions Enumeration&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;"&lt;BR&gt;- &lt;STRONG&gt;ObjectSecurity&lt;/STRONG&gt;: If this flag is not present, the caller must have the right to replicate changes. If this flag is present, the caller requires no rights, but is allowed to see only objects and attributes that are accessible to the caller. &lt;BR&gt;"&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;So modify your code to use DirectorySynchronization in&amp;nbsp;this way: &lt;/P&gt;&lt;PRE&gt;directorySearcher.DirectorySynchronization = new DirectorySynchronization(DirectorySynchronization.ObjectSecurity);
&lt;/PRE&gt;
&lt;P&gt;Code should not fail with Access Denied error anymore. Now a standard user will have access to all the objects that she usually has access to.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8624980" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/System.DirectoryServices/default.aspx">System.DirectoryServices</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/ADSI/default.aspx">ADSI</category></item><item><title>ChangePassword method may fail with TargetInvocationException (.NET)</title><link>http://blogs.msdn.com/alejacma/archive/2008/04/29/changepassword-method-may-fail-with-targetinvocationexception-net.aspx</link><pubDate>Tue, 29 Apr 2008 11:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8419329</guid><dc:creator>alejacma</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8419329.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8419329</wfw:commentRss><description>&lt;P&gt;Hi all, welcome back, &lt;/P&gt;
&lt;P&gt;When working with &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/system.directoryservices.directoryentry.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.directoryservices.directoryentry.aspx"&gt;System.DirectoryServices.DirectoryEntry&lt;/A&gt; in &lt;STRONG&gt;.NET&lt;/STRONG&gt;, we may &lt;STRONG&gt;change&lt;/STRONG&gt; the &lt;STRONG&gt;password&lt;/STRONG&gt; of the &lt;STRONG&gt;user&lt;/STRONG&gt; with a code like the following (&lt;STRONG&gt;C#&lt;/STRONG&gt;):&lt;/P&gt;&lt;PRE&gt;user.Invoke("ChangePassword", new object[] { oldPassword, newPassword }&lt;/PRE&gt;
&lt;P&gt;But invoking &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa746341(VS.85).aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa746341(VS.85).aspx"&gt;ChangePassword&lt;/A&gt; may fail with the following &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/system.reflection.targetinvocationexception.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.reflection.targetinvocationexception.aspx"&gt;System.Reflection.TargetInvocationException&lt;/A&gt;:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;"Exception has been thrown by the target of an invocation"&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This error is not very descriptive, I know. I've seen several causes for this error in the past:&lt;/P&gt;
&lt;P&gt;1) Any of the passwords is &lt;STRONG&gt;incorrect&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;2) The new password doesn't meet the domain &lt;STRONG&gt;complexity requirements&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;3) &lt;A class="" href="http://technet2.microsoft.com/windowsserver/en/library/6ac50d53-2713-4aba-8170-574e42fb2bab1033.mspx?mfr=true" mce_href="http://technet2.microsoft.com/windowsserver/en/library/6ac50d53-2713-4aba-8170-574e42fb2bab1033.mspx?mfr=true"&gt;Minimum Password Age&lt;/A&gt; is &amp;gt; 0.&lt;/P&gt;
&lt;P&gt;4) &lt;STRONG&gt;WinNT&lt;/STRONG&gt; provider is used instead of &lt;STRONG&gt;LDAP&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;By using &lt;STRONG&gt;InnerException&lt;/STRONG&gt;.ToString() from the TargetInvocationException we may get a more descriptive error message. We could even see the &lt;STRONG&gt;HResult &lt;/STRONG&gt;value associated to the exception. But this property is protected, so we could try to parse it from the error message string, with a code like this:&lt;/P&gt;&lt;PRE&gt;string errorMessage;
Int32 errorCode = 0;
try
{
    ...
}
catch (TargetInvocationException e)
{
    errorMessage = e.InnerException.ToString();
    try
    {
        string HResult = errorMessage.Substring(errorMessage.IndexOf("0x") + 2, 8);
        errorCode = Int32.Parse(HResult, System.Globalization.NumberStyles.HexNumber);
    }
    catch
    {
        errorCode = -1;
    }
}
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8419329" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/System.DirectoryServices/default.aspx">System.DirectoryServices</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/ADSI/default.aspx">ADSI</category></item><item><title>How to get a list of all users in an OU (VBScript)</title><link>http://blogs.msdn.com/alejacma/archive/2008/04/23/how-to-get-a-list-of-all-users-in-an-ou-vbscript.aspx</link><pubDate>Wed, 23 Apr 2008 18:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8419309</guid><dc:creator>alejacma</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8419309.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8419309</wfw:commentRss><description>&lt;P&gt;Hi all, welcome back,&lt;/P&gt;
&lt;P&gt;Today I'll post a very straight forward sample which gets a list of all &lt;STRONG&gt;users&lt;/STRONG&gt; in an &lt;STRONG&gt;Organizational Unit&lt;/STRONG&gt; (&lt;STRONG&gt;OU&lt;/STRONG&gt;) in &lt;STRONG&gt;Active Directory&lt;/STRONG&gt; (&lt;STRONG&gt;AD&lt;/STRONG&gt;) using &lt;STRONG&gt;VBScript&lt;/STRONG&gt;:&lt;/P&gt;&lt;PRE&gt;' Get OU
'
strOU = "OU=Users,DC=domain,DC=com"

' Create connection to AD
'
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Open "Provider=ADsDSOObject;"

' Create command
'
Set objCommand = CreateObject("ADODB.Command")
objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 1000

' Execute command to get all users in OU
'
objCommand.CommandText = _
  "&amp;lt;LDAP://" &amp;amp; strOU &amp;amp; "&amp;gt;;" &amp;amp; _
  "(&amp;amp;(objectclass=user)(objectcategory=person));" &amp;amp; _
  "adspath,distinguishedname,sAMAccountName;subtree"
Set objRecordSet = objCommand.Execute

' Show info for each user in OU
'
Do Until objRecordSet.EOF

  ' Show required info for a user
  '  
  WScript.Echo objRecordSet.Fields("adspath").Value
  WScript.Echo objRecordSet.Fields("distinguishedname").Value
  WScript.Echo objRecordSet.Fields("sAMAccountName").Value

  ' Move to the next user
  '
  objRecordSet.MoveNext

Loop

' Clean up
'
objRecordSet.Close
Set objRecordSet = Nothing
Set objCommand = Nothing
objConnection.Close
Set objConnection = Nothing
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8419309" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/VBScript/default.aspx">VBScript</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/ADSI/default.aspx">ADSI</category></item><item><title>How to get ADs Providers list (C#)</title><link>http://blogs.msdn.com/alejacma/archive/2008/03/25/how-to-get-ads-providers-list-c.aspx</link><pubDate>Tue, 25 Mar 2008 19:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8336071</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8336071.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8336071</wfw:commentRss><description>&lt;P&gt;Hi, welcome back,&amp;nbsp;&lt;/P&gt;
&lt;P&gt;We may want to get the list of &lt;STRONG&gt;Active Directory Providers &lt;/STRONG&gt;("&lt;STRONG&gt;LDAP:&lt;/STRONG&gt;", "&lt;STRONG&gt;WinNT:&lt;/STRONG&gt;", "&lt;STRONG&gt;IIS:&lt;/STRONG&gt;"...) with &lt;STRONG&gt;.NET &lt;/STRONG&gt;the same way we do it with this &lt;STRONG&gt;VBScript&lt;/STRONG&gt;:&lt;/P&gt;&lt;PRE&gt;Set ads = GetObject("ADs:")
For Each provider In ads
    Wscript.Echo provider.Name
Next
&lt;/PRE&gt;
&lt;P&gt;The information we need is here in the registry: &lt;STRONG&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ADs\Providers&lt;/STRONG&gt;. So the following sample code will get the info we need:&lt;/P&gt;&lt;PRE&gt;using Microsoft.Win32;

...

    // Get the HKLM registry key
    RegistryKey RegKey = Registry.LocalMachine;

    // Open the sub-key which contains all the providers
    RegistryKey ProviderKey = RegKey.OpenSubKey(@"Software\Microsoft\ADs\Providers");

    // Get the list of the sub-keys
    string[] SubKeys = ProviderKey.GetSubKeyNames();

    // Create the string array which will hold the provider list
    string[] ListOfProviders = new string[SubKeys.Length];

    // Now add all providers to the array
    for (int Count = 0; Count &amp;lt; SubKeys.Length; Count++)
    {
        ListOfProviders[Count] = SubKeys[Count] + ":";
    }

    // Show the list of providers
    foreach (string providerName in ListOfProviders)
    {
        MessageBox.Show(providerName);
    }
...

&lt;/PRE&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8336071" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/System.DirectoryServices/default.aspx">System.DirectoryServices</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/ADSI/default.aspx">ADSI</category></item></channel></rss>