Scheduled Task for WOL magic packets

Based on the systems in a collection, this will wakeup all of them using the 1E server.

This depends on the 1E server to be installed – it won[t work without it.

[VBScript]
' NAME: 1EWakeup_Collection
'
' Roger C 5/20/2017
'
' COMMENT: read a collection from SCCM, and fire wakeup commands to the collection members
' intended to be scheduled to run on the server using scheduled task manmager
'the collection can be read form the command line, or hard coded into the script
'==========================================================================
Option Explicit

DIM Version: Version = "1.2.0.1"

Dim strSCCMServer
'strComputer, 
dim oWMI, strSCCM_SiteName, strQuery, objWMIService, strWMIClass
Dim colItems, objItem, strCollectionID, strNameSpace
Dim i, bBatch, s_csv
dim AwakeCount, AsleepCount
Dim locator, services, WakeService
Dim LogFileHandle, LogFilename, objFile

Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20
dim wshShell: Set wshShell = WScript.CreateObject("WScript.Shell")

LogFilename = "WakeupLog.log"

'Edit for your SCCM Server
strSCCMServer = "SCCM02"
strSCCM_SiteName = "site_XXX"

' strCollectionID = "XXX00017" ' All Windows 7 Computers collection
strCollectionID = "XXX0016A" ' small sample collection - just my tablet
if WScript.Arguments.Count >= 1 then 
	if WScript.Arguments.Item(0)  "" then
		strCollectionID = WScript.Arguments.Item(0)
	End if 
end if

'=============================================================================================
' Make sure this is running  from the cscript scripting host, to avoid popups
'=============================================================================================
'If (Not IsCScript()) Then 		'If not CScript, re-run with cscript...
'	dim quote: quote=chr(34)
'    Dim strCmdLine, Argument    
'    strCmdLine = WScript.Path & "\cscript.exe " & quote & WScript.scriptFullName & Quote
'	
'    If Wscript.Arguments.Count > 0 Then
'        For Each Argument in Wscript.Arguments
'            strCmdLine = strCmdLine & space(1) & quote & Argument & quote
'        Next 
'    End If
'
'    'strCmdLine = strCmdLine & space(1) & quote & "//NOLOGO" & quote
'	LogWriteln("Running under wscript.  Relaunching under cscript: " & strCmdLine)
'	
'    wshShell.Run strCmdLine,1,False
'    WScript.Quit            	'...and stop running as WScript    
'End If

'=============================================================================================
' Make sure server is valid/online
'=============================================================================================
'strComputer = strSCCMServer
if WaitForReply(strSCCMServer, 1) then
	LogWriteln("Found server:" & strSCCMServer)
else
	LogWriteln("Unable to ping " & strSCCMServer & ". Aborting.")
	wscript.quit
end if 

'=============================================================================================
' Make sure we can access the SCCM class
'=============================================================================================
strNameSpace = "WINMGMTS:\\" & strSCCMServer & "\ROOT\SMS\" & strSCCM_SiteName
'strNameSpace = "WINMGMTS:\ROOT\SMS\" & strSCCM_SiteName

on error resume next
Set objWMIService = GetObject(strNameSpace)
if Err.number  0 then 				' didn't read it
	LogWriteln("Unable to access Namespace [" & strNameSpace & "]. Aborting.")
	wscript.quit 1
end if
on error goto 0
LogWriteln("Found namespace:" & strNameSpace)

'=============================================================================================
' obtain the list of computers in the collection
'=============================================================================================
strQuery = "SELECT CollectionID, Name FROM SMS_CollectionMember_a WHERE CollectionID='" & _ 
strCollectionID & "'"

on error resume next
Set colItems = objWMIService.ExecQuery(strQuery, "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly)
if Err.number  0 then 				' didn't read it
	LogWriteln("Error running QMI query: [" & strQuery & "]. Aborting.")
	wscript.quit 1
end if
on error goto 0
LogWriteln("Using CollectionID:" & strCollectionID)
	
S_csv = ""

AwakeCount = 0
AsleepCount=0

i = 0
on error resume next
For Each objItem in colItems
	if err.number  0 then
		LogWriteln("No computers were returned from query: " & strQuery)
		WScript.Quit 1
	end if	
	i = i + 1
	
	S_csv = S_csv + """"
	with objItem
		.Name = UCase(.Name)
		'wscript.echo .name
		'if .name = "DT7851" or .name = "DT8543" then	' Debugging = 1 then Exit For   ' DEBUGGING	
Next

LogWriteln("Awake:  " & AwakeCount)
LogWriteln("Asleep: " & AsleepCount)
LogWriteln("Total:  " & i)

wscript.quit

'=============================================================================================
' Send wake packet to a computer
'=============================================================================================
Sub WakeComputer(strComputer)
	strNameSpace = "WbemScripting.SWbemLocator"
	on error resume next
	Set locator = CreateObject(strNameSpace) 
	if Err.number  0 then
		LogWriteln("Unable to access the Scripting Type Library [" & strNameSpace & "]. Aborting.")
		wscript.quit 1
	end if
	on error goto 0
	
	strNameSpace = "root\N1E\WakeUp"
	on error resume next
	Set services = locator.ConnectServer(strSCCMServer, strNameSpace)  
	if Err.number  0 then
		LogWriteln("Unable to access the WakeUp namespace [" & strNameSpace & "]. Aborting.")
		wscript.quit 1
	end if
	on error goto 0
	
	on error resume next
	Set WakeService = services.Get("WakeUp") 
	if Err.number  0 then
		LogWriteln("Unable to access the WakeUp class [" & strNameSpace & ".WakeUp]. Aborting.")
		wscript.quit 1
	end if
	on error goto 0

	'WScript.Echo "Sending wake packet to " & strComputer
	on error resume next
	WakeService.WakeName strComputer
	if Err.number  0 then
		LogWriteln("Unable to access the WakeName method [" & strNameSpace & ".WakeUp]. Aborting.")
		wscript.quit 1
	end if
	on error goto 0
End Sub 

'=============================================================================================
' ping a computer and wait for response for x seconds
'=============================================================================================
Function WaitForReply(strComputer, iPingCount)
	Dim i
	Dim iSleep :iSleep = 1		 'delay in seconds between pings.
	'Convert time between ping to sleep units
	iSleep = iSleep * 1000
	
	WaitForReply = vbFalse
			
	'Connect to local system WMI for ping provider
	on error resume next
	strWMIClass = "winmgmts:\root\CIMV2"
	Set oWMI = GetObject(strWMIClass)
	if Err.number  0 then 				' didn't read it
		LogWriteln("Error accessing local WMI class: [" & strWMIClass & "]. Aborting.")
		wscript.quit 200
	end if
	on error goto 0
	
	For i = 1 To iPingCount
		if Ping(strComputer) Then 
			'WScript.Echo vbTab & strComputer & " online"
			WaitForReply = vbTrue
			Exit For
		End If
		WScript.Sleep iSleep
	Next
End Function

'=============================================================================================
' ping a computer 
'=============================================================================================
Function Ping(strComputer)
	Ping = vbFalse
	Dim strQuery, colItems, objItem
	'wscript.Echo "Pinging " & strComputer
	
	'Note syntax in query to get address and resolved name
	strQuery = "SELECT * FROM Win32_PingStatus where address = '" & strComputer & "'"
	
	on error resume next
	Set colItems = oWMI.ExecQuery(strQuery,,48)
	if Err.number  0 then 				' didn't read it
		LogWriteln("Error running query against local WMI class: [" & strWMIClass & " : " & strQuery & "]. Aborting.")
		wscript.quit 200
	end if
	on error goto 0

	if isobject(colItems) then
		on error resume next
		For Each objItem In colItems
			If objItem.statusCode=0 Then Ping = vbTrue
		Next
		if Err.number  0 then
			LogWriteln("Ping WMI query did not return a collection: [" & strWMIClass & " : " & strQuery & "]. Aborting.")
			wscript.quit 1
		end if
		on error goto 0
	else
		LogWriteln("Error: no results from query against local WMI class: [" & strWMIClass & " : " & strQuery & "]. Aborting.")
		wscript.quit 1
	end if
	
End Function 

'============================================================================================
' Check if this is running under CSCRIPT scripting host
'============================================================================================
'Function IsCScript()
'    If (InStr(UCase(WScript.FullName), "CSCRIPT")  0) Then
'        IsCScript = True
'    Else
'        IsCScript = False
'    End If
'End Function

'============================================================================================
' Logging functions
'============================================================================================
sub LogWriteln(s)        '-------------------------------------------------------------------
	s = "  " & TimeStamp() &  " " & s
	'wscript.echo s														'write message to the console
	if Not isObject(LogFileHandle) Then InitLogFile
	if isObject(LogFileHandle)  0 Then LogFileHandle.write s & vbCRLF	'write message to the log file
End Sub

sub InitLogFile         '--------------------------------------------------------------------
	Dim Failed: Failed = False
	Const Append = 8
	on error resume next
	Set objFile=CreateObject("Scripting.FileSystemObject")
	if Err.number  0 then
		LogWriteln("Unable to create object: [Scripting.FileSystemObject]. Aborting.")
		wscript.quit 1
	end if
	on error goto 0

	On Error Resume Next
	Err.Clear
	Set LogFileHandle = objFile.OpenTextFile(LogFilename,Append,True) ' Append file, OK to create new is not exists
	if err.number  0 then
        wscript.echo ("  Warning: Unable to write to the log file (" & LogFilename & ")")
        Failed = True
    End If	
	On Error goto 0
	If Not Failed then LogFileHandle.write vbCRLF & "===[" & Month(DATE) & "/" & Day(DATE) & "/" & Year(DATE) & _
		"]====================" & vbCrlf	
End Sub

Function TimeStamp()
	Dim intSeconds, intMilliseconds
	intSeconds = (Hour(Now) * 3600) + (Minute(Now) * 60) + Second(Now)
	intMilliseconds = Timer() - intSeconds
	intMilliseconds = Fix(intMilliseconds * 100)
	TimeStamp = Hour(Now) & ":" & Right("0" & Minute(Now),2) & ":" & Right("0" & Second(Now),2) & "." & Right("0" & intMilliseconds,2)
End Function

Leave a comment