For auditing and remote access purposes, identifying the computers and users on specified subnets can be useful. This post documents several methods that I've used in the past, including querying computers through AD, DNS, DHCP, SMS, and then finding the logon information through psloggedon, WMIC, or a custom VBScript. DNS - Query DNS to find machines on a specific subnet Non-windows DNS - Just cat/grep/find/findstr the zone files. Query AD for computers in an OU, ping the computers and return only those that respond to a ping (and can be resolved) Step 2 - Find who's logged on to those computers Use WMI: Note that the psloggedon and WMI methods will be slow when processing computers that aren't on the network, wrap around a for /f ping command (see the OU query above). The VBScript is more verbose, providing information including human readable dates, and extra information such as whether a screensaver is running.
Step 1 - Find computers on a subnet
There are several methods of finding this information, some more accurate than others depending upon your infrastructure:
SMS - Query SMS to find computers in a specific subnet or AD site:
Windows DNS
DHCP - Windows DHCP, use netsh:
Use psloggedon:
Use the VBScript in this post:
--- Script follows
Const DELIMITER = ","
Const LINK_PINGCOUNT = 1
const ERROR_SUCCESS = 0
If WScript.Arguments.UnNamed.Count > 0 Then
strComputerSet = WScript.Arguments.UnNamed(0)
Else
WScript.Echo "Please supply one or more computers to process, separated by '" & DELIMITER & "'"
WScript.Quit(2)
End If
For Each strComputer in Split(strComputerSet, DELIMITER) ' For each computer
If VerifyHostPing(strComputer) Then ' Is the computer responding to a ping?
Call FindLoggedOnUserExplorer(strComputer) ' Find the logged on users
End If
Next
Function FindLoggedOnUserExplorer(ByRef strComputer)
Dim objWMI, strQuery, dtmCreationDate, strUser, dtmDifference, strUserInfo
Dim objProcessSet, objProcess, objProcessOwner, intCount
On Error Resume Next
Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
On Error Goto 0
If NOT IsObject(objWMI) Then
wscript.echo strComputer & ", " & "Could not connect to WMI"
Exit Function
End If
strQuery = "select __relpath, CreationDate from win32_process where caption = 'explorer.exe'"
set objProcessSet = objWMI.execQuery(strQuery)
If objProcessSet.Count = 0 then
wscript.echo strComputer & ", " & "No explorer processes found"
Else
strUserInfo = ""
For Each objProcess in objProcessSet
Set objProcessOwner = objProcess.ExecMethod_("GetOwner") ' Execute the method to find the process owner
strUser = objProcessOwner.Domain & "\" & objProcessOwner.User
dtmCreationDate = objProcess.CreationDate ' The creation date of the explorer process
dtmCreationDate = ConvertDMTFToVB(dtmCreationDate, False)
strUserInfo = strUserInfo & vbCRLF & strComputer & ", " & strUser & ", " & dtmCreationDate
Next
If Len(strUserInfo) >= Len(vbCRLF) Then strUserInfo = Right(strUserInfo, Len(strUserInfo) - Len(vbCRLF)) ' Strip the leading CRLF
strQuery = "select __relpath, CreationDate, ExecutablePath from win32_process where ExecutablePath like '%.scr'"
On Error Resume Next
set objProcessSet = objWMI.execQuery(strQuery)
intCount = -1
intCount = objProcessSet.Count
On Error Goto 0
If NOT IsObject(objProcessSet) OR intCount = -1 Then
wscript.echo strComputer & ", " & "Could not check for screensaver"
Else
If intCount > 0 then ' Is there a screensaver running?
For Each objProcess in objProcessSet ' Yes
dtmCreationDate = objProcess.CreationDate ' Get the creation date of the process
dtmCreationDate = ConvertDMTFToVB(dtmCreationDate, False) ' Convert to VB datetime
dtmDifference = DateDiff("h", dtmCreationDate, Now) ' Different between now and then
strUserInfo = strUserInfo & ", " & "Screensaver is running: " & objProcess.ExecutablePath & " and has been for " & dtmDifference & " hours"
Next
Else
strUserInfo = strUserInfo & ", " & "Screensaver is not running"
End If
End If
End If
If strUserInfo <> "" Then wscript.echo struserinfo
End Function
Function VerifyHostPing(ByRef strComputer)
Dim objWMI, strQuery, i, objPings, objStatus
Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\root\cimv2")
VerifyHostPing = False
strQuery = "Select * From Win32_PingStatus where Address = '" & strComputer & "' AND BufferSize = 32 and Timeout = 300"
For i = 1 to LINK_PINGCOUNT
Set objPings = objWMI.ExecQuery(strQuery)
For Each objStatus in objPings
If IsNull(objStatus.StatusCode) OR objStatus.StatusCode <> ERROR_SUCCESS Then
wscript.echo "Warning: " & strComputer & " not contactable."
VerifyHostPing = False
Else
wscript.echo "Successfully pinged " & strComputer
VerifyHostPing = True
End If
Next
Next
Set objPings = Nothing
Set objStatus = Nothing
Set objWMI = Nothing
End Function
Function ConvertDMTFToVB(dtmDate, blnTimeZone)
Dim strTemp, intTemp, strNow, strNowDate
strTemp = Left(dtmDate,4) & "/" & Mid(dtmDate,5,2) & "/" & Mid(dtmDate,7,2) & " " & Mid(dtmDate,9,2) & ":" & Mid(dtmDate,11,2) & ":" & Mid(dtmDate,13,2)
If Left(strTemp, 10) = "****/**/**" Then ' Ugly hack for schedule task times returned by WBEM that only contain time information
strNow = Now
strNowDate = DatePart("yyyy", strNow)
strNowDate = strNowDate & "/" & String(2 - Len(DatePart("m", strNow)),"0") & DatePart("m", strNow)
strNowDate = strNowDate & "/" & String(2 - Len(DatePart("d", strNow)),"0") & DatePart("d", strNow)
strTemp = strNowDate & " " & Right(strTemp, Len(strTemp)- 11)
End If
If IsDate(strTemp) Then
If blnTimeZone Then
strTemp = DateAdd ("h", Right(dtmDate,4)/60, strTemp) 'Add GMT offset
End If
ConvertDMTFToVB = FormatDateTime(strTemp,2) & " " & FormatDateTime(strTemp,4)
Else
ConvertDMTFToVB = FALSE
End If
End Function
Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.
Information regarding Windows Infrastructure, centred mostly around commandline automation and other useful bits of information.
2 comments:
Thanks for this wayne, do you know any easy way to export the results from the command "for /f %i in (wslist.txt) do psloggedon \\%i" to a text file as such?
if you need to pipe these results to a txt file simple use >c:\results.txt
or to append use >>
Post a Comment