'########################################################################### ' Script to print out all the new objects (user,group/DL, computer that have ' been created in the forest in the last N days. ' Defaults to looking two days back unless a valid # of days is specified on ' the command line. Ex: cscript NewObjects.vbs 6 '########################################################################### ' Copyright (c) 2007 Carlos R. Tronco ' Web site - http://cars.lostroncos.org ' Version 1.0 - June 30,2007 ' ' You have a royalty-free right to use, modify, reproduce, and ' distribute this script file in any way you find useful, provided that ' you agree that the copyright owner above has no warranty, obligations, ' or liability for such use. Option Explicit 'On error Resume Next 'Following Constants pulled from Iads.h from MS Platform SDK August 2002 Const ADS_SCOPE_BASE = 0 Const ADS_SCOPE_ONELEVEL = 1 Const ADS_SCOPE_SUBTREE = 2 'Do we want to print out marginally useful debugging info Const bDebug = False 'object for RootDSE- used to kind of help get our AD bearings Dim objRootDSE 'Root Domain object - Dim objRootDomain 'RootDN path. Dim RootDN 'Today's Date/Time. Used for comparing WhenCreated attribute to now Dim MyDate '# Date Range tells us how far back (in days) we want to look for new objects '# (ex: if DateRange= 2 we want all new objects within the last 2 days Dim DateRange 'Script works by performing ADO search based on object types so we don't have 'to traverse OUs. 'Schema object for groups Dim grpObjCat 'Schema Object for users Dim userObjCat 'Schema object for computers Dim computerObjCat ' Command line args object Dim objArgs 'Output Separator String.... Dim Separator Separator = vbCrLF & "##############################################" & vbCRLF 'DateRange Defaults to 2 if not specified on command line. DateRange = 2 'Set MyDate to Now.... MyDate = Date 'Let's see if another value was specified for DateRange on the command line. '**NOTE: We don't validate the command line arg** Set objArgs = WScript.Arguments 'We got at least one argument. If objArgs.Count > 0 Then If bDebug Then WScript.Echo "[Debug] " & objArgs(0) DateRange = Cint(objArgs(0)) End If WScript.Echo " Looking for objects less than " & DateRange & " Days old" 'Get RootDSE info so we can figure out the Configuration/object category stuff.. set objRootDSE = GetObject("LDAP://RootDSE") If bDebug Then WScript.Echo "[DEBUG] RootDomainNamingcontext=" & objRootDSE.Get("rootDomainNamingContext") 'Get an obj for root domain so we can get the DN Set objRootDomain = GetObject("LDAP://" & objRootDSE.Get("rootDomainNamingContext")) RootDN = objRootDomain.DistinguishedName If bDebug Then Wscript.Echo "[Debug] " &"objRootDomain.DN=" & RootDN grpObjCat = "CN=Group,CN=Schema,CN=Configuration," & RootDN userObjCat = "CN=Person,CN=Schema,CN=Configuration," & RootDN computerObjCat = "CN=Computer,CN=Schema,CN=Configuration," &RootDN GetDomainList RootDN WScript.Quit '###################################################### Sub FindNewObjects( strDCName,strDomainDN, strObjectCategory) '###################################################### '# Find new Objects in the Domain specified by strDomainDN of '# type strobjectcategory '###################################################### Dim description Dim WhenCreated Dim CN Dim DN Dim DDiff 'Our Local Connection Object Dim Connection 'Our Local Command Object Dim Command 'RecordSet Object Dim RS 'String to hold the parts of our RS Dim Entry 'index into array of RS Dim Index if bDebug Then Wscript.Echo "[DEBUG] In FindNewObjects([" & strDCName & "],[" & strDomainDN &_ "],[" &strObjectCategory &"]" End If Err.Clear 'Set up our Connection Object... Set Connection = CreateObject("ADODB.Connection") Connection.Provider = "ADsDSOObject" Connection.Open "ADSI" if bDebug Then WScript.Echo " [DEBUG] RC=" & Err.Number &" " & Err.Description 'Set up our Command Object Set Command = CreateObject("ADODB.Command") 'Tie this command object back to our Connection Object Set Command.ActiveConnection = Connection 'Tell AD we want to do a subtree search.... Command.Properties("searchscope")= ADS_SCOPE_SUBTREE 'Select specifies a DC explicitly rather than doing serverless binding because the 'otherwise we seem to get inconsistent results.... Command.CommandText = "SELECT distinguishedName,cn,whenCreated,description" & _ " FROM 'LDAP://" & strDCName& "/" & strDomainDN & "'" & _ " WHERE objectCategory='" & strObjectCategory & "'" '------------------------------------------- Command.CommandText = "SELECT distinguishedName,cn,whenCreated,description" & _ " FROM 'LDAP://" & strDCName& "/" & strDomainDN & "'" & _ " WHERE objectCategory='" & strObjectCategory & "'" &_ " ORDER By whenCreated Desc" '------------------------------------------- ' " FROM 'LDAP://standarddc1/" & strDomainDN & "'" & _ if BDebug Then WScript.Echo "[DEBUG] Command.CommandText = " & Command.CommandText 'Execute our Search command Set RS = Command.Execute Err.Clear While Not RS.EOF Err.Clear ' description = RS.Fields(0) ' WScript.Echo "Description Get RC = " & Err.Number & ":" & err.Desciption If Err.Number <> 0 Then Description = "" ' WScript.echo “Err.#=” & Err.Number whencreated = RS.Fields(1) cn = RS.Fields(2) dn = RS.Fields(3) DDiff = DateDiff("d", whencreated,MyDate) if bDebug Then WScript.Echo "[DEBUG] DDIFF is =" & DDiff if DDiff <=dateRange Then WScript.Echo Whencreated & vbTab & dn & vbTab & description else Exit Sub end If RS.MoveNext Wend End Sub '###################################################################### Function GetDC(strDomainDN) '###################################################################### '#Finds an applicable DC to bind to for the domain represented by '# strDomainDN. Uses FSMORoleOwner attribute from domain object. '# Doesn't take AD site or network location into consideration '###################################################################### ' Object representing the domain we want to find a DC for Dim objDomain 'obj represented by FSMORoleOwner Attr of objDomain Dim objFSMOOwner 'obj representing parent of FSMORoleOwner (i.e. the DC) Dim objDC 'Print out Debug info telling us where we are when Func is called if bDebug Then WScript.Echo "[DEBUG] In GetDC(" & strdomainDN & ")" 'Get Domain Object represented by strDomainDN Set objDomain = GetObject("LDAP://" & strDomainDN) If bDebug Then Wscript.echo "[Debug]" & objDomain.Get("fsmoRoleOwner") 'Get FSMORoleOwner Attribute and bind the object. This will look ' something like: CN=NTDS Settings,DC=DC01,DC=Company,DC=Com Set objFSMOOwner = GetObject("LDAP://" & objDomain.Get("fsmoRoleOwner")) If bDebug Then WScript.Echo "[DEBUG] Parent=" & objFSMOOwner.Parent 'Get the "Parent" of the FSMORoleOwner object. This will be the DC. Set objDC= GetObject(objFSMOOwner.Parent) If bDebug Then WScript.Echo "[DEBUG] DC=" & objDC.DnshostName 'Return the HostName of the DC. GetDC= objDC.DnshostName End Function ' '###################################################### Sub GetDomainList(strDomainDN) '###################################################### ' ' ' '###################################################### 'Our Connection Object Dim Connection 'Our Command Object Dim Command 'RecordSet Object Dim RS Dim strDomainName Dim strDN Dim strDCName 'Set up our Connection Object... Set Connection = CreateObject("ADODB.Connection") Connection.Provider = "ADsDSOObject" Connection.Open "ADSI" if bDebug Then WScript.Echo "[DEBUG] RC=" & Err.Number &" " & Err.Description 'Set up our Command Object Set Command = CreateObject("ADODB.Command") 'Tie this command object back to our Connection Object Set Command.ActiveConnection = Connection 'Tell AD we want to do a subtree search.... Command.Properties("searchscope")= ADS_SCOPE_SUBTREE 'Set up our query to get a list of domains from a GC Command.CommandText = "SELECT Name,distinguishedName FROM 'GC://" & strDomainDN & "'" & _ " WHERE objectCategory='domain'" if bDebug Then WScript.Echo "[DEBUG] Command.CommandText=" & Command.CommandText 'Execute our Search command Err.Clear Set RS = Command.Execute RS.MoveFirst While Not RS.EOF strDomainName = RS.Fields(1) strDN = RS.Fields(0) 'Find a DC for this domain..... strDCName = GetDC(strDN) if bDebug Then WScript.Echo "[DEBUG] name=" & strDomainName & "; DN=" & strDN ' Get List of User objects WScript.Echo Separator & " New User Objects in " & strDN FindNewObjects strDCName, strdn, userObjCat 'Get list of group/DL objects WScript.Echo Separator & " New group Objects in " & strDN FindNewObjects strDCName, strdn, grpObjCat 'Get list of Computer objects.... WScript.Echo Separator & " New computer Objects in " & strDN FindNewObjects strDCName, strdn, computerObjCat RS.MoveNext Wend End Sub