Translate Active Directory VBScript into PowerShell—Not Me!

Translate Active Directory VBScript into PowerShell—Not Me!

  • Comments 3
  • Likes

Summary: Don’t translate old VBScript scripts that search Active Directory—instead use the Active Directory cmdlets from the RSAT.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have this script that I use for auditing Active Directory. Basically, it queries to see what new user accounts have been created in the last month. I started translating it to Windows PowerShell (because I know that Windows PowerShell has the ability to create COM objects), but I fail to see the Windows PowerShell advantage. I mean, the script is as long as the original VBScript script. What gives?

—BB

Hey, Scripting Guy! Answer Hello BB,

Microsoft Scripting Guy, Ed Wilson, is here. This morning I had to jump right into work, with little time even for a nice cup of tea. With the Atlanta TechStravaganza and TechEd Europe coming up back-to-back, there have been literally dozens of emails flying across the pond. The Scripting Guys will have a booth at TechEd Europe, and I will be conducting a couple of instructor-led labs about the cool new Windows PowerShell 4.0 Desired State Configuration feature. This lab, which was completely full the last day of TechEd North America, is absolutely awesome. Anyway, with temperatures in the mid-90s (Fahrenheit, 34 degrees Celsius), it is advisable to not get too terribly excited.

Good old COM-based ADO

In the VBScript days, it was not uncommon to use COM-based ADO to query Active Directory to find various pieces of information about users. In fact, this is a technique that I used all the way back in the Windows 2000 days (and the infamous millennium bug). Following is a 4.5 star script from the Script Center Repository: Search for All Users by the Date Their Account was Created.

On Error Resume Next

Const ADS_SCOPE_SUBTREE = 2

 

dtmCreationDate = "20071001000000.0Z"

 

Set objConnection = CreateObject("ADODB.Connection")

Set objCommand =   CreateObject("ADODB.Command")

objConnection.Provider = "ADsDSOObject"

objConnection.Open "Active Directory Provider"

Set objCommand.ActiveConnection = objConnection

 

objCommand.Properties("Page Size") = 1000

objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE

 

objCommand.CommandText = _

    "SELECT Name FROM 'LDAP://dc=fabrikam,dc=com' WHERE objectClass='user' "  & _

        "AND whenCreated>='" & dtmCreationDate & "'"

Set objRecordSet = objCommand.Execute

 

objRecordSet.MoveFirst

Do Until objRecordSet.EOF

    Wscript.Echo objRecordSet.Fields("Name").Value

    objRecordSet.MoveNext

Loop

Hey, you know what, it is not too bad—only 26 lines long. It especially was not too bad if you had a great VBScript template with which to begin your work (you can find templates at Script Resources for IT Professionals). If one were to translate this script into Windows PowerShell, using the same COM-based ADO, the script would be essentially the same, and it would be just as long. Luckily, we do not have to do that.

The Windows PowerShell way

In Windows PowerShell 1.0, about the best one could do was to use the .NET Framework classes. This translated into using two classes. The resultant code is shown here:

$strFilter = "(&(objectCategory=User)(whenChanged=20071001000000.0Z))"

 

$objDomain = New-Object System.DirectoryServices.DirectoryEntry

 

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher

$objSearcher.SearchRoot = $objDomain

$objSearcher.PageSize = 1000

$objSearcher.Filter = $strFilter

 

$colProplist = "name"

foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}

 

$colResults = $objSearcher.FindAll()

 

foreach ($objResult in $colResults)

    {$objItem = $objResult.Properties; $objItem.name}

Groovy. This is only 17 lines of code, and we have the added bonus of avoiding the use of COM-based classes.

In Windows PowerShell 2.0, the [adsisearcher] type accelerator is added, and that shortens the code by a few lines. But the greatest addition comes with the installation of the Remote Server Administration Tools (RSAT) because these introduce the Active Directory module. (For more information, see Hey, Scripting Guy! What's Up with Active Directory Domain Services Cmdlets?)

The Active Directory module and a one-liner

Upon installing the RSAT tools (for your specific version of client and server), you gain access to the Get-ADUser cmdlet. This makes finding information about newly created users the one-liner shown here:

Get-ADUser -Filter * -Properties whencreated | where whencreated -ge ((get-date).adddays(-30))

BB, that is all there is to converting an Active Directory script to Windows PowerShell. Join me tomorrow when we are joined by Honorary Scripting Guy and Windows PowerShell MVP, Sean Kearney, for Part 1 of his series, Create a New Virtual Machine with PowerShell.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • The only time you REALLY need to touch on the old stuff (between the Quest/Dell Cmdlets and Active Directory Modules) is if you are going to (Stop laughing) pull data from an NT 4.0 domain.

    ....and yes PowerShell CAN do that :)

    It can do ANYTHING !

  • akhem...

    $searcher = [adsisearcher]'(&(objectCategory=User)(whenChanged=20071001000000.0Z))'

    $searcher.SearchRoot = ... # you can ommit that line if the domain you're searching is the one your computer is joined to

    $searcher.FindAll() | % {$_.Properties.name}

    what I wanted to say is "use the [adsisearcher] type accelerator"

  • @Sean Kearney yep, the really old stuff is basically for compatibility sake.

    @Siodmy Thank you for providing an example of using the [adsisearcher]. I mentioned it in my article, as having been introduced in PowerShell 2, and was going to add an example, then at the last minute decided not to do so. I am glad you stepped in with your example.