Per the subject line
... hope it proves as useful to some of you as it has been to me this
week. As always, please verify its successful execution in a lab before
use in a production environment.
Thanks to Laura
Hunter for guinea-pigging it for me!
Kindest
regards.
Dean
--
Dean Wells
MSEtechnology
* Email: [EMAIL PROTECTED]
http://msetechnology.com
:: Active Directory Object Counter - Dean Wells / MSEtechnology / Sept. 2005
:: Provides count and breakdown of objects and their class type within the
supplied partition
:: - additional LDIFDE command line arguments [such as providing credentials]
can be supplied by
:: pre-populating the environment variable "LDIFargs" with the desired syntax.
:: See script help for further details
@echo off
:: Define initial environment
set STDOUT=nul
set STDERR=nul
set TITLESTRING=Active Directory Object Counter
set TOGGLE=0
set FQDN=
set LOGDIR=%TEMP%\
set PARTCLASS=?
set PARTTYPE=?
if "%1"=="" goto :HELP
if "%1"=="/?" goto :HELP
setlocal ENABLEDELAYEDEXPANSION
:: Locate critical executables
for %%e in (ldifde.exe find.exe) do (
set where="%%~$PATH:e"
if "!where!"=="""" (
echo ERROR - Required executable, "%%e", not located within the
path
goto :END
)
)
:: Prepare display and window title
echo/
echo STATUS - Working ...
echo/
title %TITLESTRING%
:: Determine verbosity requirements and if a DN or FQDN was supplied
set DNSorDN=%*
set VERBOSE=%*
set DNSorDN=%DNSorDN: -V=%
set DNSorDN=%DNSorDN: /v=%
set DNSorDN=%DNSorDN: -V=%
set DNSorDN=%DNSorDN: -v=%
if not "%VERBOSE%"=="%DNSorDN%" set VERBOSE=1
set ROOT=%DNSorDN:,=%
if not "%ROOT%"=="%DNSorDN%" (
set ROOT=%DNSorDN%
call :STRIPDN %DNSorDN%
if "!TOGGLE!"=="-1" (
echo ERROR - Unknown syntax supplied
goto :HELP
)
) else (
set ROOT=dc=%DNSorDN:.=,dc=%
set FQDN=%DNSorDN%
set LOGDIR=%LOGDIR%!FQDN!
)
:: Define or modify remaining environment
set CNT=0
set ICTMP=
set LOGFILE="%LOGDIR%\objcount.log"
set TMPFILE="%LOGDIR%\objcount.$$$"
set SERVER=
set TMPSYNTAX=
:: Create %LOGDIR% directory
if not exist "%LOGDIR%" (
md "%LOGDIR%" 2>%STDERR%
if errorlevel 1 (
echo ERROR - Log directory could NOT be created
echo/
echo "%LOGDIR%"
goto :END
)
)
:: Construct human-readable time
set DTIME=%TIME% & set DTIME=!DTIME:~0,8!
:: Display operational data
echo * Running on computer : %COMPUTERNAME%
:: Determine if -s [server to query against] was supplied by LDIFargs, if so,
don't use %FQDN%
if not "%LDIFargs%"=="" (
set TMPSYNTAX=%LDIFargs:-s=%
set TMPSYNTAX=!TMPSYNTAX:-S=!
)
if "%TMPSYNTAX%"=="%LDIFargs%" (
echo * DSAs resolved using : %FQDN%
set SERVER=-s %FQDN%
) else (
echo * DSAs resolved using : see optional LDIF args. below
)
:: Continue displaying operational data
echo * Base DN of query is : %ROOT%
echo * Command submitted at : %DTIME% on %DATE%
if not "%LDIFargs%"=="" (
echo * Optional LDIF args. : %LDIFargs%
)
echo/
:: Construct LDAP query for all objects
echo - submitting LDAP query
set LDIFSYNTAX=ldifde -j "%LOGDIR%" %SERVER% -d %ROOT% -r objectclass=* -l
objectclass -f %LOGFILE% %LDIFargs%
:: Submit LDAP query for all objects
%LDIFSYNTAX% >%STDOUT%
:: If LDFIDE returned an error, delete %LOGFILE% such that the following error
check is triggered
if errorlevel 1 (
del %LOGFILE% 2>%STDERR%
)
if not exist %LOGFILE% (
echo/
echo ERROR - LDAP query failed enumerating objects
echo/
echo %LDIFSYNTAX%
goto :HELP
)
:: Construct and submit LDAP query to determine partition type
set /p = - partition type: <nul
ldifde -j "%LOGDIR%" %SERVER% -d %ROOT% -r objectclass=* -l
objectclass,instanceType,fSMORoleOwner -p base -f %TMPFILE% %LDIFargs% >%STDOUT%
:: Parse query result
for /f "tokens=1,2 usebackq" %%t in (%TMPFILE%) do (
if /i "%%t"=="objectclass:" (
set PARTCLASS=%%u
) else (
if /i "%%t"=="instanceType:" (
set PARTTYPE=%%u
)
)
)
:: Display partition detail
if "%PARTTYPE%"=="13" (
if /i "%PARTCLASS%"=="dmd" (
echo Schema
) else (
if /i "%PARTCLASS%"=="configuration" (
echo Configuration
) else (
if /i "%PARTCLASS%"=="domainDNS" (
echo Application [NDNC]
) else (
echo UNKNOWN
[class=%PARTCLASS%/instanceType=%PARTTYPE%]
)
)
)
) else (
if "%PARTTYPE%"=="5" (
if /i "%PARTCLASS%"=="domainDNS" (
echo Domain or ADAM NDNC
) else (
echo UNKNOWN [class=%PARTCLASS%/instanceType=%PARTTYPE%]
)
) else (
echo UNKNOWN [class=%PARTCLASS%/instanceType=%PARTTYPE%]
)
)
:: Count total objects
for /f %%c in ('type %LOGFILE% ^| find /i /c "dn:"') do (
set /p = - total number of objects: <nul
set OBJTOT=%%c
)
:: Determine if LDIFDE failed to locate the supplied partition
echo %OBJTOT%
if "%OBJTOT%"=="0" (
echo/
echo ERROR - LDAP query incomplete; object count too low
goto :END
)
:: If high verbosity was not requested [/v], skip to summary
if not "%VERBOSE%"=="1" goto :SKIPINSTCNT
:: Append footer to %LOGFILE% in order to ensure instance count function below
includes the last object
echo dn:
This_line_was_appended_to_ensure_last_object_found_is_included_by_the_instance_count_function>>%LOGFILE%
:: Count the number of instances of each class [filter LDIF changetype: entries
from log file]
echo - calculating number of instances per class [-V]
for /f "tokens=1,2 usebackq" %%n in (%LOGFILE%) do (
if /i not "%%n"=="changetype:" (
if /i not "%%n"=="dn:" (
set ICTMP=%%o
) else (
if not "!ICTMP!"=="" (
set /a CNT+=1
title %TITLESTRING% - !CNT! of %OBJTOT% ...
call set /a [$IC$]!ICTMP!+=1 2>%STDERR%
if errorlevel 1 (
set ICFIX=!ICTMP!
set ICFIX=!ICFIX:-=#$#!
call set /a [$IC$]!!ICFIX!!+=1
)
)
)
)
)
:: Ensure temporary file used below is empty
del %TMPFILE% 2>%STDERR%
:: Construct instance count temporary file
for /f "tokens=1,2 delims==" %%e in ('set [$IC$] 2^>%STDOUT%') do (
if "!INSTSTR!"=="" (
echo/
echo STATUS - The following classes were found -
echo/
)
set INSTSTR=%%e
set INSTSTR=!INSTSTR:#$#=-!
set INSTSTR=!INSTSTR:[$IC$]=!
set INSTCNT= %%f
set INSTCNT=!INSTCNT:~-10!
echo !INSTCNT! !INSTSTR!>>%TMPFILE%
)
:: Display sorted instance count
for /f "tokens=1,2" %%s in ('sort /r %TMPFILE%') do (
set INSTSTR=%%t
set INSTSTR=!INSTSTR! ....................................
set INSTSTR=!INSTSTR:~0,37! %%s
echo !INSTSTR!
)
:: Display total object count
echo/
echo TOTAL ................................. %CNT% objects
:SKIPINSTCNT
echo/
:: Construct human-readable time
set DTIME=%TIME% & set DTIME=!DTIME:~0,8!
:: Script body ends
echo Completed successfully at %DTIME% on %DATE%
goto :END
:: Define functions/subroutines
:: Convert DN to FQDN
:STRIPDN
if not "%1"=="" (
if "!TOGGLE!"=="0" (
set TYPE=%1
set TOGGLE=1
) else (
if /i "!type!"=="cn" (
set LOGDIR=!LOGDIR!%1.
set TOGGLE=0
) else (
if /i "!type!"=="dc" (
set LOGDIR=!LOGDIR!%1.
set FQDN=!FQDN!%1.
set TOGGLE=0
) else (
set TOGGLE=-1
goto :EOF
)
)
)
shift
goto :STRIPDN
)
set FQDN=%FQDN:~0,-1%
set LOGDIR=%LOGDIR:~0,-1%
goto :EOF
:HELP
echo/
echo SYNTAX - %0 ^<Partition FQDN or DN^> [-V]
echo/
echo [-V] optional, displays per-class object count
echo/
echo Additional LDIFDE command line arguments [such as providing
echo alternate credentials] can be supplied by pre-populating the
echo environment variable "LDIFargs" with the desired syntax.
echo/
echo e.g. set LDIFargs=-b Administrator MSET MyPassw0rd
echo set LDIFargs=-s cubelet.msetechnology.com
goto :END
:END
title Command Prompt
if not "%FQDN%"=="" if exist "%LOGDIR%" (
del "%TMPFILE%" "%LOGFILE%" "%LOGDIR%\ldif.err" "%LOGDIR%\ldif.log" /f
/q 2>%STDERR%
rd "%LOGDIR%" 2>%STDERR%
)
