Active Directory Query using ADSI/VBScript

Background

Microsoft’s Active Directory is likely one of the most widely deployed LDAP Server.

Every Application needs User authentication, but unfortunately the code can be written so deep in the Application that the error code and messages gets lost from suppression.

Thankfully, ADSI makes quick work of it.

Here is Microsoft’s definition of ADSI:

ADSI
https://msdn.microsoft.com/en-us/library/aa772170%28v=vs.85%29.aspx

Active Directory Service Interfaces (ADSI) is a set of COM interfaces used to access the features of directory services from different network providers. ADSI is used in a distributed computing environment to present a single set of directory service interfaces for managing network resources. Administrators and developers can use ADSI services to enumerate and manage the resources in a directory service, no matter which network environment contains the resource.

 

Code

Here is a code that I am trying out to quickly get a subset of the logged-on user’s data:


REM ******************************************************************************************************************************
REM *
REM
REM REM AD Query Script
REM http://www.rlmueller.net/ADOSearchTips.htm

REM Rahul Soni's blog
REM Never assume the obvious is true!
REM http://blogs.msdn.com/b/rahulso/archive/2006/12/29/how-to-read-user-and-system-variables-using-vbscript.aspx

REM ******************************************************************************************************************************

Option Explicit

Const USERDOMAIN = "USERDOMAIN"
Const USERNAME = "USERNAME"

Const USERDOMAIN_EXPAND = "%USERDOMAIN%"
Const USERNAME_EXPAND = "%USERNAME%"

Const USER_SYSTEM = "SYSTEM"

Const bDebug = false

Dim adoCommand, adoConnection, strBase, strAttributes
Dim objRootDSE, strDNSDomain, strQuery, adoRecordset, strName, strCN
Dim strLog

Dim objWSH
Dim objUserVariables
Dim objSystemVariables

Dim objWshNetwork 

Dim strFilterSyntax
Dim strFilter

Dim strGivenName
Dim strSurname
Dim strUsername
Dim strUserDomain
Dim strEmailAddress
Dim strTelephoneNumber
Dim strDepartment
Dim strEmployeeID
Dim strDistinguishName

Dim bErrorCheckFailed
Dim strWhenCreated

Dim strFullDN
Dim ou

on error goto 0

strUserName = ""
bErrorCheckFailed = false

if (Wscript.Arguments.Count < 1)  Then

	rem Wscript.Echo "No arguments"

elseif (Wscript.Arguments.Count = 1) Then

	strUserName = Wscript.Arguments.Item(0) 

end if

Set objWSH =  CreateObject("WScript.Shell")

Set objUserVariables = objWSH.Environment("USER")
Set objSystemVariables = objWSH.Environment("SYSTEM")

	Rem http://stackoverflow.com/questions/904739/can-i-pick-up-environment-variables-in-vbscript-wsh-script
	strUserDomain = objSystemVariables(USERDOMAIN)

	if (strUserDomain = "") Then

		Rem http://stackoverflow.com/questions/904739/can-i-pick-up-environment-variables-in-vbscript-wsh-script
		strUserDomain = objWSH.ExpandEnvironmentStrings(UserDomain_EXPAND)

	end	if	

	if (strUserName = "") Then

		strUserName = objSystemVariables(USERNAME)

	end if

	if (strUserName = "") Then

		strUserName = objWSH.ExpandEnvironmentStrings(UserName_EXPAND)

	end	if	

set objWSH =  Nothing

if  ( _
		        (strUserDomain = "") _
		   or ( (strUserName = "") or (strUserName = USER_SYSTEM)) _
	) Then

	' Create a new WshNetwork object to access network properties.
	'http://wsh2.uw.hu/ch11b.html
	Set objWshNetwork = WScript.CreateObject("WScript.Network")

		if (strUserDomain = "") Then

			strUserDomain = objWshNetwork.UserDomain

		end if

		if ( (strUserName = "") or (strUserName = USER_SYSTEM) ) Then

			strUserName = objWshNetwork.UserName

		end if		

	Set objWshNetwork = Nothing

end if

if (strUserDomain = "") Then

	Wscript.Echo "User Domain is empty"
	bErrorCheckFailed = true

end if

if (bErrorCheckFailed) Then

	Wscript.Echo "Validity Check failed!"

	rem http://ss64.com/vb/quit.html
	WScript.Quit -100

end if

strLog = "User Domain: " & strUserDomain
Wscript.Echo strLog

strDNSDomain = strUserDomain

' Setup ADO objects.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
Set adoCommand.ActiveConnection = adoConnection

' Search entire Active Directory domain.
Set objRootDSE = GetObject("LDAP://RootDSE")

strDNSDomain = objRootDSE.Get("defaultNamingContext")
strBase = "<LDAP://" & strDNSDomain & ">"

' Filter on user objects.
strFilterSyntax = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=#USERSAMNAME#))"
strFilter = Replace(strFilterSyntax, "#USERSAMNAME#", strUsername)

rem Wscript.Echo "FILTER SYNTAX: " & strFilterSyntax
rem Wscript.Echo "FILTER:        " & strFilter

' Comma delimited list of attribute values to retrieve.
strAttributes = "distinguishedName,sAMAccountName,cn,givenname,sn,mail,telephoneNumber,department,employeeID,whenCreated,lastLogon,lastLogoff,mailNickname"

' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

' Run the query.
Set adoRecordset = adoCommand.Execute

Dim strLastLogon
Dim strLastLogoff
Dim strMailNickname

' Enumerate the resulting recordset.
on error resume next

strDistinguishName = ""

Do Until adoRecordset.EOF

    ' Retrieve values and display.
    strName = adoRecordset.Fields("sAMAccountName").Value
    strCN = adoRecordset.Fields("cn").value
	strDistinguishName =  adoRecordset.Fields("distinguishedName").value

	strGivenName = adoRecordset.Fields("givenname").value
	strSurname = adoRecordset.Fields("sn").value
	strEmailAddress = adoRecordset.Fields("mail").value
	strTelephoneNumber = adoRecordset.Fields("telephoneNumber").value
	strDepartment = adoRecordset.Fields("department").value
	strEmployeeID = adoRecordset.Fields("employeeID").value
	rem whenCreated
	'strWhenCreated = adoRecordset.Fields("whenCreated").value
	'strLastLogon = adoRecordset.Fields("lastLogon").value
	'strLastLogoff = adoRecordset.Fields("lastLogoff").value
	strMailNickname = adoRecordset.Fields("mailNickname").value

    Wscript.Echo "NT Name: " & strName
	Wscript.Echo "Common Name: " & strCN
	Wscript.Echo "Distinguish Name (dn): " & strDistinguishName
	Wscript.Echo "Given Name: " & strGivenName
	Wscript.Echo "Last Name: " & strSurname
	Wscript.Echo "Email Address: " & strEmailAddress
	Wscript.Echo "Telephone Number: " & strTelephoneNumber
	Wscript.Echo "Department: " & strDepartment
	Wscript.Echo "Employee ID: " & strEmployeeID
	Wscript.Echo "When Created: " & strWhenCreated
	'Wscript.Echo "Last Logoff: " & strLastLogoff
	'Wscript.Echo "Last Logon: " & strLastLogon
	Wscript.Echo "Mail Nickname: " & strMailNickname

    ' Move to the next record in the recordset.
    adoRecordset.MoveNext
Loop

if (Err.Number <> 0) Then

	Wscript.Echo "Err Number " & CSTR(Err.Number)
	Wscript.Echo "Err Description " & CSTR(Err.Description) 

end if

Dim objUser
Dim objLastLogon
Dim objLastLogoff

Dim intLastLogonTime
Dim intLastLogoffTime

if (strDistinguishName <> "") then

	'Set ou = GetObject("LDAP://ou=Accounts,dc=cerrotorre,dc=de")

	'For Each obj In ou
		'WScript.Echo obj.name
	'Next

	strFullDN = "LDAP://" & strDistinguishName

	if (bDebug) Then

		WScript.Echo "Connecting to " & strFullDN & " ..."

	end if

	Set objUser = GetObject(strFullDN)

	if (Err.Number <> 0) Then

		Wscript.Echo "Err connecting to LDAP - Targeted " & strFullDN
		Wscript.Echo "Err Number " & CSTR(Err.Number)
		Wscript.Echo "Err Description " & CSTR(Err.Description) 

	end if

	if ( (objUser is Nothing) = false) Then	

		Set objLastLogon = objUser.Get("lastLogon")
		intLastLogonTime = objLastLogon.HighPart * (2^32) + objLastLogon.LowPart
		intLastLogonTime = intLastLogonTime / (60 * 10000000)
		intLastLogonTime = intLastLogonTime / 1440

		Set objLastLogoff = objUser.Get("lastLogoff")

		intLastLogoffTime = 0
		if ((objLastLogoff is Nothing) = False) Then

			intLastLogoffTime = objLastLogoff.HighPart * (2^32) + objLastLogoff.LowPart
			intLastLogoffTime = intLastLogoffTime / (60 * 10000000)
			intLastLogoffTime = intLastLogoffTime / 1440

		end if

		WScript.Echo "Last Logon is " & intLastLogonTime + #1/1/1601# 

		if (intLastLogoffTime <> 0) Then

			WScript.Echo "Last Logoff is " & intLastLogoffTime + #1/1/1601# 

		end if		

	else

			WScript.Echo "ou is empty for " & strFullDN 	

	end if

	if ( (objUser is Nothing) = false) Then	

		if (bDebug) Then

			WScript.Echo "Releasing User object ..."

		end if

		Set objUser = Nothing

		if (bDebug) Then

			WScript.Echo "Released User object"

		end if

	end if

end if

on error goto 0

' Clean up.
adoRecordset.Close
adoConnection.Close

Output:

ADQueryUser.vbs

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s