Recently, at my job, I had a task to write script/program to count how many users had logged to workstation in the last month. While my colleague tried to complete this task with C#, I’ve decided to use old good Batch. In fact, I was thinking about using PowerShell at first, but since all computers this script will be run in are running Windows XP and do not have PowerShell installed.
To accomplish what I want I’ve found out about VBS script called EVENTQUERY which exists in Windows XP. After reading documentation I’ve decided that it would allow me to do exactly what I need. Though the script that relies on EVENTQUERY.VBS file, it wouldn’t work on newer Windows OS (Vista, Windows XP), but it wouldn’t cause any problems since, as I’ve mentioned before, all computers this script will be deployed to runs on Windows XP. If I would need it to work on Windows 7 later, I’m probably gonna use PsLogList from SysInternals.
So, about the final script itself. I’ve decided to make it as much customizable as possible so we can easily change some settings at the beginning of the script. It would allow to make this script to count something else (let’s say logs off or specific errors) easily. Since the script will be running once a month, I needed to get previous month and count events only from this date. It took me a while to write those lines related to date modification since I haven’t known that Batch doesn’t updates variables in the condition statements. It took some time to find it out.
All the magic happens in the 40th line. I call EVENTQUERY.VBS with all the filters I’ve defined. Since I need to count only real users I’ve skipped those event’s that are caused by either NT AUTHORITYNETWORK SERVICE or NT AUTHORITYLOCAL SERVICE “user”. Also, after some first tests, I’ve seen that the number of logons my scripts counts is twice as big as the real one. It was because that on my local testing machine’s event log I really needed to take logon events that have “user32” as “Logon process“. After adding this filter (findstr /i %logonProcess%’) everything’s looks good. I’ve tried it on some other machines and it worked for me. After running the script, number of logons is saved to specified network location or simply displayed in the console (if script was ran with /p key).Организация караоке-бара
So, there’s the script:
<br /> REM Login to workstation counter<br /> REM By Tomas Dabasinskas<br /> REM 2010-09-08</p> <p>REM Log name (application|system|security)<br /> SET log=security<br /> REM Log event ID:<br /> SET id=528<br /> REM Log type (ERROR|INFORMATION|WARNING|SUCCESSAUDIT|FAILUREAUDIT):<br /> SET type=SUCCESSAUDIT<br /> REM Logon process:<br /> SET logonProcess=user32<br /> REM Save path for results. If empty, results are displayed on the screen<br /> SET savePath="\\ComputerShare"<br /> REM Filename of results file (ignored if savePath is empty):<br /> SET saveFile=%COMPUTERNAME%-%date:~0,4%.%date:~5,2%.%date:~8,2%</p> <p>REM Stop editing here<br /> @ECHO Off<br /> SETLOCAL DISABLEDELAYEDEXPANSION<br /> CLS<br /> SET counter=0</p> <p>REM Set Windows Script Host to CScript:<br /> @CSCRIPT //h:cscript //s //nologo>NUL</p> <p>REM Get last month:<br /> SET y=%date:~0,4%<br /> SET m=%date:~5,2%<br /> SET d=%date:~8,2%<br /> IF %m% LSS 10 SET m=%m:~1,2%<br /> IF %m% EQU 1 (<br /> SET /A y-=1<br /> SET m=12<br /> ) ELSE SET /A m-=1<br /> IF %m% LSS 10 SET m=0%m%<br /> SET dateFilter=%m%/%d%/%y%</p> <p>REM Counter loop:<br /> FOR /F "tokens=* delims=" %%A in ('EVENTQUERY /v /nh /l %log% /fo CSV /fi "ID eq %id%" /fi "User ne NT AUTHORITYNETWORK SERVICE" /fi "User ne NT AUTHORITYLOCAL SERVICE" /fi "Type eq %type%" %dateFilter% ^| findstr /i %logonProcess%') DO SET /A counter+=1</p> <p>REM Results:<br /> IF NOT %savePath%.==. IF NOT "%1"=="/p" (<br /> REM To file:<br /> ECHO %counter% > %savePath%%saveFile%.txt<br /> ) ELSE (<br /> REM To console:<br /> ECHO Number of logons: %counter%<br /> PAUSE>NUL<br /> )<br />