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:
- wmic /namespace:\\root\sms\site_%sitecode% /node:"%sms_server%" path SMS_R_System WHERE "IPSubnets='%subnet%' AND Active=1'" get name
- wmic /namespace:\\root\sms\site_%sitecode% /node:"%sms_server%" path SMS_R_System WHERE "ADSiteName='%AD_SITE_CODE%' AND Active=1'" get name
DNS - Query DNS to find machines on a specific subnet
Windows DNS
- dnscmd %dns_Server% /enumrecords %zone% @ /additional /continue find /i "%subnet%"
Non-windows DNS - Just cat/grep/find/findstr the zone files.
DHCP - Windows DHCP, use netsh:
- psexec \\%dhcp_server% cmd /c for %i in (%Subnet1% %Subnet2% %Subnet3%) do netsh dhcp server scope %i show clients 1
- for /f "tokens=1" %i in ('"netsh dhcp server show scope 1 find /i "%description%""') do netsh dhcp server scope %i show clients 1 find /i "255.255" find /i "%prefix%"
Query AD for computers in an OU, ping the computers and return only those that respond to a ping (and can be resolved)
- for /f %i in ('"dsquery computer %OU_DN% -o rdn"') do for /f "tokens=3 delims=: " %m in ('"ping -n 1 %i find /i "reply from""') do echo %i
Step 2 - Find who's logged on to those computers
Use psloggedon:
- for /f %i in (computers.txt) do psloggedon \\%i
Use WMI:
- for /f %i in (computers.txt) do wmic /node:"%computer%" PROCESS where "caption='explorer.exe'" getowner
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).
Use the VBScript in this post:
- cscript LoggedOn.vbs %computer1%,%computer2%,...
The VBScript is more verbose, providing information including human readable dates, and extra information such as whether a screensaver is running.
--- 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.
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