[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

mbsacli scripting

Posted on 2010-01-06
2
Medium Priority
?
693 Views
Last Modified: 2012-05-08
This is a two part project. The first part is a batch file that will allow mbsacli to run on a server and verify that all patches from WSUS are installed. The second part is to report a success or fail. I have been wrestling with this for awhile and I am at a loss
0
Comment
Question by:Frog_1337
2 Comments
 
LVL 23

Accepted Solution

by:
Kamaraj Subramanian earned 1000 total points
ID: 26194943
0
 
LVL 47

Assisted Solution

by:Donald Stewart
Donald Stewart earned 1000 total points
ID: 26195633
Save below as "Remote_Update.hta"
 
It will allow you to view and install missing updates. It must be run under an account with permissions on remote machine.

<html>
<!--*******************************************************************
Alan Kaplan for US VA, 11-28-2007. alan dot kaplan at va dot gov
This HTA allows you to check the patches that Windows Update/WSUS
reports are needed on a remote computer, and to patch it remotely.
Also included is test for logged on user and session time.
Note that I use scheduled tasks because other remote execution types failed to work.
Revision History:
v. 1.0 - not released publically
v. 1.1 - First public release, added remote logged on user information
v  1.2 - Fixed error handling issue with selective patching that showed up as a 
type mismatch on deleting patchlist.txt file.  Made some error messages more verbose
v 1.3 - Added waiting for reboot, schedule reboot
v 1.4  12/27/2007 @11:45 - Added check error handling for computer exists on check for pending reboot
Also added resizing and better support of 1024X768, more detailed messaging, default time for reboot
v. 1.5. Force reboot time to military time
v 1.6 fixed Logged on user
v 1.7 changed message display, code cleanup
v 2.0 3-19-2009 Some big changes in appearance.  Added Uptime, fixed mil time for afternoons.
'improved error handling.  I made many layout changes so I bumped major version number.
'****************************************************************************-->
<head><title>Remote Windows Update v 2.0 -- Alan Kaplan</title>

<HTA:APPLICATION
     APPLICATIONNAME="Remote Windows Update HTA"
     SCROLL="yes"
     SINGLEINSTANCE="yes"
     WINDOWSTATE="normal"
     contextmenu="True"
     id ="oRWUHTA"
>
</head>
<script language="VBScript">

Option Explicit
Dim strComputer, strHTML
dim oTable, oAllinputs, iPatchCount
Dim i, strMessage, oPopup
dim strPatch
Dim oPopBody
Dim objSession, updateSearcher, searchResult, update
Dim updatesToInstall, updatesToDownload
Dim downloader 
Dim retval, installer, installationResult
dim wshShell,command
Set wshShell = CreateObject("WScript.Shell")
dim fso
set fso = CreateObject("Scripting.FileSystemObject")
Dim strScript
dim quote
quote=chr(34)
Dim strPatchScript, oTextStream
Dim strUserName, strPassword, strRmtDate, strRmtTime
Dim strPatchFile, strOS
Dim bFatal
bFatal = False

Const HKLM = &H80000002
Dim oReg, strKey, strValue, strVal

' Subs and Functions

Sub Window_OnLoad()
	On Error Resume Next
	'This to get the computer name as an argument
	Dim strCommandLine, strArgs, strProgPath
    strProgPath = replace(document.location.pathname,"%20",space(1))
	strCommandLine = oRWUHTA.commandLine
	strArgs = mid(strCommandline,instr(strCommandline,".hta")+7)
	 
	strUserName  = wshShell.ExpandEnvironmentStrings("%USERDOMAIN%\%USERNAME%")
	UserName.value = strUserName
	strMessage = "<font size=2><i>You are logged on as " & strUserName & ".<br>This account must have administrative rights on the remote computer.</i></font> "

	  If Len(strArgs) > 0 Then 
		ComputerName.Value = strArgs
		strMessage = strMessage &  "<br><br> Choose View Patches or Install Updates to continue."
	 Else
		strMessage = strMessage &  "<br><br> Enter the name of the computer to patch with Windows Update or WSUS"
	 End If 
 	showMessage strMessage
 	patchlist.innerhtml = "<font size = 5><center><bold>Remote Windows Update Tool</center></bold></font>"
 	self.Focus()
    self.MoveTo 200,100
    'Width by length
    self.ResizeTo 900,650
    ComputerName.Focus( )
End Sub 

Sub GetPatches()
	On Error Resume Next
	strComputer = ucase(computername.value)
	
	If Not PingReply() Then 
			MsgBox "Ping Failed!",vbCritical + vbOKOnly,strComputer
			showMessage "Failed to ping " & strComputer & " . Reset Form to continue."
			Exit Sub
	Else
			showMessage strComputer & " replied to ping."
	End If 
	
	strMessage = "Starting Windows Update on " & strComputer & VbCrLf & _
	"(If this message persists, this action has failed.)"
	showMessage strMessage
	Set objSession = CreateObject("Microsoft.Update.Session", strComputer)
	If Err <> 0 or isnull(objSession) Then 
		MsgBox "Failed!" & Err.Description,strComputer,vbCritical + vbOKOnly
		Exit Sub
	End If 

	showMessage "Connecting to " & strComputer
	Set updateSearcher = objSession.CreateupdateSearcher
	If Err <> 0 Then
		MsgBox "Failed to create update searcher. " & Err.Description, vbcritical + vbokonly,strComputer 
		Exit Sub
	End If 
	
	showMessage strComputer & " is getting the list of applicable updates, please wait ...." 
	
	Set searchResult = updateSearcher.Search("IsInstalled=0 and Type='Software'")
	If Err <> 0 Then
		MsgBox "Failed to start search with update searcher. " & Err.Description, vbcritical + vbokonly,strComputer 
		showMessage "Fatal error, unable to update " & strComputer
		Exit Sub
	End If 
	
	Dim d, PatchNames, Descriptions
    Set d = CreateObject("Scripting.Dictionary")
    
	For I = 0 To searchResult.Updates.Count-1
	    Set update = searchResult.Updates.Item(I)
		Dim objCategories, strCatName, strMore
		Set objCategories = update.Categories
	    strCatName = objCategories.Item(0).Name
	
		If strCatName = "Security Updates" Then 
			strMore =  VbCrLf & ", severity: " & update.MsrcSeverity
		Else
			strMore = "."
		End If 
	
	    d.add update.Title, update.Description & VbCrLf & "Category: " & strCatName & strMore
	Next
	
	If searchResult.Updates.Count = 0 Then
		showMessage "There are no applicable updates."
		Exit Sub
	End If
 	
    showMessage "Creating collection of updates available to download"
		
 	strHTML = ""

	'This all ends up in a single cell, but I don't care
	
	strHTML = "<tr><td><tbody><font+3><b>Patch List for " & strComputer & ":</b></font><br><br>"
	
	PatchNames = d.Keys
    Descriptions = d.items
    	
	 For i = 0 To d.Count -1
        strHTML =  strHTML & "<input type='checkbox' name='CheckBox" & i & _
        "' value=" & i & ">" & PatchNames(i) & ". Description: " & Descriptions(i) & "<br><br>"
       
  	Next
  
	strHTML =  strHTML &"</tbody></tr></td>"
  
    PatchList.InnerHTML = strHTML
    showMessage "Choose patches to install"
    runbutton.disabled = False
    selectbutton.disabled = False
End Sub

Sub SecOnly
	strUserName = username.value
	strPassword = PasswordBox.value
	If strUserName = "" Or strPassword="" Then
		MsgBox "Username and Password required", vbCritical + vbOKOnly,"Input Error"
		Exit Sub
	End If 
	
    strMessage = "All Security Patches"
    strComputer = ucase(cstr(computername.value))
    
	 If Not PingReply() Then 
			MsgBox "Ping Failed!",vbCritical + vbOKOnly,strComputer
			showMessage "Failed to ping " & strComputer & " Reset Form to continue"
			Exit Sub
	Else
			showMessage strComputer & " replied to ping."
	End If 
	
	Dim strPatchFile
	strPatchFile = "\\"& strComputer & "\c$\patchlist.txt"
	
	'12/20/2007
	Err.Clear()
	On Error Resume Next
	
	If fso.FileExists(strPatchFile) Then fso.DeleteFile strPatchFile, true
	
	if err <> 0 then 
		MsgBox "Failed to delete old patchlist.txt from remote drive. " & Err.Description, vbcritical + vbokonly,strComputer
		showMessage "Fatal error, unable to update " & strComputer
		Exit Sub
	End If 	
   	
   	Set oTextStream = fso.CreateTextFile(strPatchFile)
   	
   	If err <> 0 Then 
		MsgBox "Failed to write patchlist.txt to remote drive. " & Err.Description, vbcritical + vbokonly,strComputer
		showMessage "Fatal Error"
		Exit Sub
	End If 
	
   	oTextStream.Write(strMessage) 
	oTextStream.Close
	
    showMessage "Wrote " & strPatchFile
    MakeScript()
End Sub

Sub InstSelected
	strUserName = username.value
	strPassword = PasswordBox.value
	
	If strUserName = "" Or strPassword="" Then
		MsgBox "Username and Password required", vbCritical + vbOKOnly,"Input Error"
		Exit Sub
	End If 
	
	 If Not PingReply() Then 
			MsgBox "Ping Failed!",vbCritical + vbOKOnly,strComputer
			showMessage "Failed to ping " & strComputer & " Reset Form to continue"
			Exit Sub
	Else
			showMessage strComputer & " replied to ping."
	End If 
	
    strMessage =""
	set otable = document.getElementById("PatchTable")
	set oAllInputs = otable.getElementsByTagName("input")
	
	Set updatesToDownload = CreateObject("Microsoft.Update.UpdateColl")	
	
	for i = 0 To oallinputs.length -1
		if oallInputs(i).checked = true then 
			Set update = searchResult.Updates.Item(I)
		    strMessage = strMessage &  update.Title & vbcrlf 'write to control list on remote computer
		End If 
	Next
	
	'12/20/2007
	Err.Clear()
	On Error Resume Next 	
	strPatchFile = "\\"& strComputer & "\c$\patchlist.txt"
	If fso.FileExists(strPatchFile) Then fso.DeleteFile strPatchFile, true
	
	if err <> 0 then 
		MsgBox "Failed to delete old patchlist.txt from remote drive. " & Err.Description, vbcritical + vbokonly,strComputer
		showMessage "Fatal error, unable to update " & strComputer
		Exit Sub
	End If 	
	
	
   	Set oTextStream = fso.CreateTextFile(strPatchFile)
   	oTextStream.Write(strMessage) 

   	
   	If err <> 0 Then 
		MsgBox "Failed to write patchlist.txt to remote drive. " & Err.Description, vbcritical + vbokonly,strComputer
		showMessage "Fatal error, unable to update " & strComputer
		Exit Sub
	End If 

    showMessage "Wrote " & strPatchFile

	On Error Goto 0    
   MakeScript()
 End Sub

Sub UpTime ()
	Err.Clear
	If computername.value = "" Then 
		MsgBox "Enter computer name first!",vbCritical + vbOKOnly, "User Error"
		Exit Sub
	Else
		strComputer = ucase(computername.value)
	End If 
	
	Dim oWMI, colItems, objItem
	Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
	Set colItems = oWMI.ExecQuery("Select LastBootUpTime from Win32_OperatingSystem",,48)
	If Err <> 0 Then
		MsgBox "Failed to connect to WMI for "&  strComputer,vbokonly+vbcritical,"Oops"
	End If 
	
	For Each objItem In colItems
	    strMessage  = strComputer & " uptime: " & DiffADate (WMIDateStringToDate(objItem.LastBootUpTime)) & " days."
	Next
	
	MsgBox strMessage,vbokonly+vbInformation,"Computer Uptime"
End Sub 

Function WMIDateStringToDate(dtmDate)
	WMIDateStringToDate = CDate(Mid(dtmDate, 5, 2) & "/" & _
	Mid(dtmDate, 7, 2) & "/" & Left(dtmDate, 4) _
	& " " & Mid (dtmDate, 9, 2) & ":" & Mid(dtmDate, 11, 2) & ":" & Mid(dtmDate,13, 2))
End Function


Function DiffADate(theDate)
  DiffADate = DateDiff("d", thedate, now)
End Function



 Sub SelectDeselect
      
	    Set otable = document.getElementById("PatchTable")
    	Set oAllInputs = otable.getElementsByTagName("input")
    		
        If selectButton.Value = "Select All" Then
            SelectButton.Value = "Deselect All"
            for i = 0 to oallinputs.length -1
       			oallInputs(i).checked = true
            next
        Else
            SelectButton.Value = "Select All"
            for i = 0 to oallinputs.length -1
       			oallInputs(i).checked = false
            next
        End If
End Sub


Sub doPopup(strText, iXlocation, iYLocation)  ' just for show...
	Dim iWidth, iHeight

	set oPopup = window.createPopup
    set oPopBody = oPopup.document.body
    oPopBody.style.backgroundColor = "lightyellow"
    oPopBody.style.border = "solid black 1px"
    oPopBody.innerHTML =  "<font face = 'arial' size = 2>" & strText & "</font>"
    iWidth = (Len(strText)*10) / 2
    iHeight = 25 *2
    oPopup.show iXLocation, iYLocation ,iWidth, iHeight, document.body
End Sub

Sub closePopup
    oPopup.hide
end Sub

Sub showMessage(lsMsg)  
	Message.innerHTML= " " & lsMsg & " "  
	Message.style.display=""  
	command = "%COMSPEC% /c"  
	wshShell.Run command,0,1  
End Sub  

  
Sub hideMessage()
	Message.innerHTML=""  
	Message.style.display="none"  
end Sub

Sub MakeScript()
	'Create script on remote computer
	strScript = "'=== This is a temp file.  It is okay to delete it. ===" & vbcrlf & _ 
	"'======= Alan Kaplan, created by WindowsUpdate.hta ==========" & vbcrlf & _ 
	"dim fso,logfile, bReboot, bMSReboot, appendout" & vbcrlf & _ 
	"Const ForAppend = 8" & vbcrlf & _ 
	"Set fso = CreateObject(" & quote & "Scripting.FileSystemObject" & quote & ")" & vbcrlf & _ 
	"Dim strPatchFile, strPatchList" & vbcrlf & VbCrLf & _ 
	"bReboot = True" & VbCrLf & _
	"If wscript.arguments.count > 0 then bReboot = False" & VbCrLf  & _
	"On Error Resume Next" & vbcrlf & _ 
	"logfile = " & quote & "c:\RemoteWSUSLog.txt" & quote & "	'Name of log file.  Can open in Excel." & vbcrlf & _ 
	"strPatchfile = " & quote & "c:\PatchList.txt" & quote & "" & vbcrlf & _ 
	"Set appendout = fso.OpenTextFile(logfile, ForAppend, True)" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"If not fso.FileExists(strPatchFile) Then" & vbcrlf & _ 
	"	WriteLog strPatchFile & " & quote & " not found, quitting" & quote & "" & vbcrlf & _ 
	"	WScript.Quit" & vbcrlf & _ 
	"End If " & vbcrlf & _ 
	"" & vbcrlf & _ 
	"Set f=fso.OpenTextFile(strPatchFile,1,False)" & vbcrlf & _ 
	"strPatchList = f.readall" & VbCrLf & _ 
	"Dim bSecurity"& VbCrLf & _ 
	"If strPatchList = " & quote & "All Security Patches" & quote & " Then bSecurity = True"& VbCrLf & _ 
	"" & VbCrLf & _ 
	"if bReboot = False then" & VbCrLf & _ 
	"WriteLog " & quote & "Launched with no reboot set" & quote &  VbCrLf & _ 
	"   Else" & VbCrLf & _ 
	"WriteLog " & quote & "Launched permitting reboot if not user is logged on "& quote & VbCrLf & _ 
	"End If " & VbCrLf & _ 
	"" & VbCrLf & _ 
	"Set oSession = CreateObject(" & quote & "Microsoft.Update.Session" & quote & ")" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"Set updateSearcher = oSession.CreateupdateSearcher" & vbcrlf & _ 
	"If Err <> 0 Then" & VbCrLf & _ 
	"	WriteLog " &  quote & "Update Searcher not created" & quote & " & Err.Description" & VbCrLf & _ 
	"	WScript.Quit" & VbCrLf & _ 
	"End If " & vbcrlf & _ 
	"" & vbcrlf & _ 
	"Set searchResult = updateSearcher.Search(" & quote & "IsInstalled=0 and Type='Software'" & quote & ")" & vbcrlf & _ 
	"If Err <> 0 Then" & VbCrLf & _ 
	"	WriteLog " & quote & "Update Search function failed." & quote & "&  Err.Description" & vbcrlf & _ 
	"	WScript.Quit" & VbCrLf & _ 
	"End If " & vbcrlf & _ 
	"" & vbcrlf & _ 
	"If searchResult.Updates.Count = 0 Then" & vbcrlf & _ 
	"	WriteLog " & quote & "There are no applicable updates." & quote & "" & vbcrlf & _ 
	"	WScript.Quit" & VbCrLf & _ 
	"End If" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"'Creating collection of updates to download" & vbcrlf & _ 
	"Set updatesToDownload = CreateObject(" & quote & "Microsoft.Update.UpdateColl" & quote & ")" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"For I = 0 to searchResult.Updates.Count-1" & vbcrlf & _ 
	"    Set update = searchResult.Updates.Item(I)" & VbCrLf & _
	"	Set objCategories = update.Categories" & VbCrLf & _
	"	strCatName = objCategories.Item(0).Name" & VbCrLf & VbCrLf & _
	"	If bSecurity Then " & VbCrLf & _
	"		If strCatName = " & quote & "Security Updates" & quote & " Then " & VbCrLf & _
	"	    WriteLog " & quote & "adding " & quote & " & update.Title & " & quote & " to download list." & quote  & vbcrlf & _ 
	"			updatesToDownload.Add(update) " & VbCrLf & _
	"		End If" & VbCrLf & _
	"	Else" & VbCrLf & _
	"    If InStr(strPatchList, update.Title) Then " & vbcrlf & _ 
	"	    WriteLog " & quote & "adding " & quote & " & update.Title & " & quote & " to download list." & quote  & vbcrlf & _ 
	"	    updatesToDownload.Add(update)" & vbcrlf & _ 
	"    End If " & VbCrLf & _ 
	"  End If " & VbCrLf & _ 
	"Next" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"'Downloading updates..." & VbCrLf & _
	"If updatestoDownload.count = 0 Then" & VbCrLf & _
	"	WriteLog " & quote & "No patches meeting criteria found to download, quitting." & quote & VbCrLf & _
	"	WScript.Quit" & VbCrLf & _
	"End If" & VbCrLf & _
	"Set downloader = oSession.CreateUpdateDownloader() " & vbcrlf & _ 
	"" & VbCrLf & _ 	
	"downloader.Updates = updatesToDownload" & vbcrlf & _ 
	"downloader.Download()" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"Set updatesToInstall = CreateObject(" & quote & "Microsoft.Update.UpdateColl" & quote & ")" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"'Creating collection of downloaded updates to install" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"For I = 0 To searchResult.Updates.Count-1" & vbcrlf & _ 
	"    set update = searchResult.Updates.Item(I)" & vbcrlf & _ 
	"    If update.IsDownloaded  Then" & vbcrlf & _ 
	"	    WriteLog " & quote & "adding " & quote & " & update.Title & " & quote & " to install list." & quote & vbcrlf & _ 
	"	    updatesToInstall.Add(update)	" & vbcrlf & _ 
	"    End If" & vbcrlf & _ 
	"Next" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"WriteLog " & quote & "Installing updates..." & quote & "" & vbcrlf & _ 
	"Set installer = oSession.CreateUpdateInstaller()" & vbcrlf & _ 
	"installer.Updates = updatesToInstall" & vbcrlf & _ 
	"Set installationResult = installer.Install()" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"'Output results of install" & vbcrlf & _ 
	"WriteLog " & quote & "Installation Result: " & quote & " &	Code2Text(installationResult.ResultCode)" & vbcrlf & _ 
	"WriteLog  " & quote & "Reboot Required: " & quote & " & installationResult.RebootRequired " & vbcrlf & _ 
	"bMSReboot = installationResult.RebootRequired" & VbCrLf & _
	"strMessage = " & quote & "Listing of updates installed " & quote & " & _" & VbCrLf & _ 
	" " & quote & "and individual installation results:" & quote & "  & VbCrLf " & vbcrlf & _ 
	"" & vbcrlf & _ 
	"For I = 0 to updatesToInstall.Count - 1" & vbcrlf & _ 
	"	strMessage =  VbCrLf & strMessage & vbtab & updatesToInstall.Item(i).Title & _" & vbcrlf & _ 
	"	" & quote & ": " & quote & " & code2text(installationResult.GetUpdateResult(i).ResultCode)" & vbcrlf & _ 
	"Next" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"WriteLog strMessage" & VbCrLf & _ 
	"" & VbCrLf & _ 
	"If Not(UserLoggedOn) and bReboot and bMSReboot then" & vbcrlf & _ 
	"		WriteLog " & quote & "Done.  Rebooting computer" & quote & "" & vbcrlf & _ 
	"		strComputer = " & quote & "." & quote & "" & vbcrlf & _ 
	"		Set objWMIService = GetObject(" & quote & "winmgmts:" & quote & " _" & vbcrlf & _ 
	"		& " & quote & "{impersonationLevel=impersonate,(Shutdown)}!\\" & quote & " & strComputer & " & quote & "\root\cimv2" & quote & ")" & vbcrlf & _ 
	"		" & vbcrlf & _ 
	"		Set colOperatingSystems = objWMIService.ExecQuery (" & quote & "Select * from Win32_OperatingSystem" & quote & ")" & vbcrlf & _ 
	"		" & vbcrlf & _ 
	"		For Each objOperatingSystem in colOperatingSystems" & vbcrlf & _ 
	"			objOperatingSystem.Reboot()" & vbcrlf & _ 
	"		Next" & vbcrlf & _ 
	"	Else" & VbCrLf & _
	"		If bMSReboot = False then "& VbCrLf & _
	"			strmessage =" & quote & "Done.  No reboot required" & quote  & VbCrLf & _
	"		else" & VbCrLf & _
	"			strmessage = " & quote & "Done.  Logged on user, not rebooting computer" & quote & VbCrLf & _
	"		End If " & VbCrLf & _
	"		WriteLog strmessage" & vbcrlf & _ 
	"End If" & vbcrlf & _ 
	"" & VbCrLf & _ 	
	"Sub WriteLog (message)" & vbcrlf & _ 
	"	message = now & vbTab &  message" & vbcrlf & _ 
	"	AppendOut.WriteLine message" & vbcrlf & _ 
	"End Sub  " & vbcrlf & _ 
	"" & vbcrlf & _ 
	"Function UserLoggedOn()" & vbcrlf & _ 
	"	UserLoggedOn = False" & vbcrlf & _ 
	"	Dim wshshell" & VbCrLf & _ 
	"	Set wshShell = WScript.CreateObject(" & quote & "WScript.Shell" & quote & ")" & vbcrlf & _ 
	"	Dim objLocator, objWMIService, objUserInfoList, objUserInfo" & vbcrlf & _ 
	"	strComputer = wshShell.ExpandEnvironmentStrings(" & quote & "%COMPUTERNAME%" & quote & ")" & vbcrlf & _ 
	"	set objLocator = CreateObject(" & quote & "WbemScripting.SWbemLocator" & quote & ")" & vbcrlf & _ 
	"	set objWMIService = objLocator.ConnectServer(strComputer) " & vbcrlf & _ 
	"	Set objUserInfoList = objWMIService.InstancesOf(" & quote & "Win32_ComputerSystem" & quote & ")" & vbcrlf & _ 
	"	For Each objUserInfo in objUserInfoList" & vbcrlf & _ 
	"   		If not isnull(objUserInfo.Username) Then  " & vbcrlf & _ 
	"    		UserLoggedOn = True" & vbcrlf & _ 
	"    		Exit Function " & vbcrlf & _ 
	"   		End If  " & VbCrLf & _ 
	"	Next" & vbcrlf & _ 
	"End Function" & vbcrlf & _ 
	"" & vbcrlf & _ 
	"Function Code2Text(iCode)" & vbcrlf & _ 
	"	If iCode = 2 Then " & vbcrlf & _ 
	"		Code2Text = " & quote & "Okay" & quote & "" & vbcrlf & _ 
	"	Else" & VbCrLf & _ 
	"		Code2Text = " & quote & "Failed" & quote & "" & VbCrLf & _ 
	"	End If " & VbCrLf & _ 
	"End Function "

    'Whew!
	
	strPatchScript = "\\"& strComputer & "\c$\patchscript.vbs"
	If fso.FileExists(strPatchScript) Then fso.DeleteFile strPatchScript, true
	
   	Set oTextStream = fso.CreateTextFile(strPatchScript)
   	oTextStream.Write(strScript) 
	oTextStream.Close
	
    showMessage "Wrote " & strPatchScript

    MakeJob()
End Sub


Sub BtnUpdate
   button1.disabled = False
   If Radio1(0).Checked Then
   		'self.ResizeTo 900,650
		button1.value = "Get Patch List"        
   Else
   		'self.ResizeTo 1000,650
		button1.value = "Launch Security Update Install"
   End if 
End Sub

Sub SelectedOption		
   button1.disabled = True
   If Radio1(0).Checked Then
        GetPatches
   End If
    
   If Radio1(1).Checked Then
        SecOnly
   End If
    
End Sub


Function PingReply()
	strComputer = ucase(computername.value)
	PingReply = False
 	Dim objWMIService, colPings, objPing
    Set objWMIService = GetObject("winmgmts:" _
      & "{impersonationLevel=impersonate}!\\.\root\cimv2")
    Set colPings = objWMIService.ExecQuery _
      ("SELECT * FROM Win32_PingStatus WHERE Address = '" & strComputer & "'")
      
    For Each objPing in colPings
        if objPing.StatusCode = 0 Then 
        PingReply = True
       	Exit Function
       	End If 
    Next

End Function


Sub MakeJob()
	On Error Resume Next
	Dim strCommand , retval
	Dim iTime, strNewTime
	strComputer = ucase(computername.value)	
	Dim strJobFile
	strJobfile = "\\"& strComputer & "\admin$\tasks\RunOnce.job"
	If fso.FileExists(strJobFile) Then		fso.DeleteFile strJobFile, True
	
	if err <> 0 Then 
		MsgBox "Failed to delete old job " & err.Description, vbcritical + vbokonly,strComputer
		Exit Sub
	End If 
	
	RemoteDateTime()
	
	showMessage "Creating scheduled task for patching"
	
	iTime = minutes.value
	If iTime = 0 Then iTime = 1	'minimum delay 1 minute
	
	'Add minutes
	strNewTime = DateAdd("n", minutes.value, time)
	'format as military Time String
	strCommand = "\\" & strComputer & "\admin$\System32\cscript.exe c:\patchscript.vbs "
	If document.getElementbyID("C1").checked = false  Then strCommand = strCommand & " noReboot"
	
	strNewTime= cstr(FormatDateTime(strNewTime, vbShortTime))& ":00"
	strCommand = "SCHTASKS /s " & strComputer & " /Create /SC once /TN RunOnce /TR " & quote & strCommand & quote &_
      " /ST "& strNewTime & " /RU " & quote & strUserName & quote & " /RP " & quote & strpassword & quote

	retval = WshShell.Run(strCommand, 0, True) 
	If retval = 0 Then
	   showMessage "The patch task was successfully created to start at " & strNewTime & ". Press Reset Form button to reset"
	Else
	   strMessage ="There were problems creating the patch task. " & Err.Description & ". Press Reset Form button to reset"
	   showMessage strMessage
	   MsgBox strMessage, vbCritical + vbOKOnly, "Fatal Error"
	End If
	
 End Sub


Sub RemoteDateTime()
	showMessage "Getting time on " & strComputer
	On Error Resume Next
	Dim oWMI, colItems, objItem
	Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
		if err <> 0 then 
		MsgBox "WMI Failure " & err.Description, vbcritical + vbokonly,strComputer
		Exit Sub
	End if 
	Set colItems = oWMI.ExecQuery("SELECT * FROM Win32_Localtime",,48)
	For Each objItem In colItems
		strRmtDate = objItem.Year & "-" & padNum(objItem.Month) & "-" & padnum(objItem.Day)
		strRmtTime = objItem.Hour & ":" & padNum(objItem.Minute) & ":" & padnum(objItem.Second)
	Next
	showMessage "Time on " & strComputer & " is " & strRmtTime
End Sub 

Function PadNum(strNum)
	If Len(strnum) = 1 Then 
		padnum = "0" & strnum
	Else 
		PadNum = strNum
	End If 
End Function


Sub CheckUser()
	If computername.value = "" Then 
		MsgBox "Enter computer name first!",vbCritical + vbOKOnly, "User Error"
		Exit Sub
	End If 

	strComputer = ucase(computername.value)
	strMessage = "Current user: " & RemoteComputerUsers(strComputer)

	If bFatal = True Then 
		showMessage "Fatal Error - Use Reset Form button to reset"
		bFatal = False
		Exit Sub
	End If 
	
	If InStr(strMessage,"(None)") = 0 Then
		strMessage = strMessage & VbCrLf &  "Session Time: " & Sessiontime & VbCrLf & VbCrLf  & _
	    "Continue forced logoff of this user? Logoff is immediate and without notice!"
	    retval = MsgBox(strMessage, vbYesNo + vbQuestion + vbDefaultButton2,"Logoff user?")
		If retval = vbYes Then Logoff strComputer
	Else
		retval = MsgBox(strMessage,vbOKOnly + vbInformation, strComputer)
	End If 

End Sub 


Sub Logoff(strComputer)
	Dim objOSItem, colOSItems
	On Error Resume Next		' continue On Error
	
	Set colOSItems=GetObject("winmgmts:{(Debug,RemoteShutdown)}//" _
	            	& strComputer & "/root/cimv2").ExecQuery( _
	              	"Select * from Win32_OperatingSystem where Primary=true")
	If Err > 0 Then
		MsgBox "Force logoff to "& strComputer & " failed. "  & Err.Description, vbCritical  + vbOKOnly,"Success"
		Exit Sub 
	End If  
	
	For each objOSItem In colOSItems
		objOSItem.Win32Shutdown(4) 'Force Logoff
		MsgBox "Sent force logoff to "& strComputer, vbInformation + vbOKOnly,"Success"
	Next 
	On Error Goto 0
End Sub  

Function Sessiontime()
	On Error Resume Next 
	'I have not seen any other vbscript that does this well
	Dim oWMI, ColSessions, objSession, strLogonTime
	Dim iElapsedTime, iHours, iMinutes
	Set oWMI = GetObject("winmgmts:" _
			& "{impersonationLevel=impersonate,(Shutdown)}!\\" & strComputer & "\root\cimv2")
	Set ColSessions = oWMI.ExecQuery("Select * from Win32_LogonSession where LogonType=2",,48)
	strLogonTime  = 0
	If Err > 0 Then
		MsgBox "Getting session information from "& strComputer & " failed. "  & Err.Description, vbCritical  + vbOKOnly,"Success"
		bFatal = True
		Exit Function  
	End If  


	
	For Each objSession In ColSessions
	   If WMIDateStringToDate(objSession.StartTime) > strLogonTime Then 
	   	  strLogonTime = WMIDateStringToDate(objSession.StartTime)
	   End If 
	Next
		
	iElapsedTime = MinutesDiff(strLogonTime)
	iHours = int(iElapsedTime /60)
	iMinutes = iElapsedTime Mod 60
	Sessiontime = iHours & " Hours " & iMinutes & " minutes."
End Function


Sub SchedReboot    
	If Not PingReply() Then 
		MsgBox "Ping Failed! Press Reset form to continue.",vbCritical + vbOKOnly,strComputer
		showMessage "Failed to ping " & strComputer & ". Press Reset form to continue."
		Exit Sub
	Else
		showMessage strComputer & " replied to ping."
	End If 
	
	strUserName = username.value
	strPassword = PasswordBox.value
	If strUserName = "" Or strPassword="" Then
		MsgBox "Username and Password required", vbCritical + vbOKOnly,"Input Error"
		Exit Sub
	End If 
	
	On Error Resume Next
	strComputer = ucase(computername.value)	
	Dim strJobFile, strNewTime, strCommand
	
	strJobfile = "\\"& strComputer & "\admin$\tasks\Reboot.job"
	If fso.FileExists(strJobFile) Then		fso.DeleteFile strJobFile, True
	
	if err <> 0 Then 
		MsgBox "Failed to delete old job " & err.Description, vbcritical + vbokonly,strComputer
		Exit Sub
	End If 
	
	Dim strDay
	Do Until Len(strDay) = 10
		strDay = PadNum(Month(now))& "/" & padNum(Day(now)) & "/" & Year(now)
		strDay  = InputBox("Enter day to reboot in military time, ex: 01/01/2009","Day",StrDay)
		If strDay = "" Then Exit Sub 
	Loop
	
	Do Until InStr(strNewTime,":") = 3
		strNewTime = InputBox("Enter reboot time in military format. Ex: 01:00:00 for 1:00 AM","Reboot Time",MilPlusFive())
		If strNewTime = "" Then Exit Sub 
	Loop
	
	showMessage "Creating scheduled task to reboot"

	strCommand = "shutdown.exe -r"
	strCommand = "SCHTASKS /s " & strComputer & " /Create /SC once /TN Reboot /TR " & quote & strCommand & quote &_
      " /ST "& strNewTime & " /SD " & strDay & " /RU " & quote & strUserName & quote & " /RP " & quote & strpassword & quote

	
		retval = WshShell.Run(strCommand, 0, True) 
	If retval = 0 Then
	   strMessage = "The reboot was successfully created to start at " & strNewTime
	   showMessage strMessage
	Else
	   strMessage ="There were problems creating the reboot task." & "<br> Press Reset Form button to reset"
	   showMessage strMessage
	   MsgBox strMessage, vbCritical + vbOKOnly, "Fatal Error"
	End If
	
 End Sub

Sub RebootCheck
	If computername.value = "" Then
		MsgBox "Enter a computer name first!",vbCritical + vbOKOnly,"Name"
		Exit Sub
	End If 
	
	strComputer = ucase(cstr(computername.value))
	On Error Resume Next
	Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" &_ 
	   strComputer & "\root\default:StdRegProv")
	
	If Err <> 0 Then 
		MsgBox "Failed to check reboot computer.",vbCritical + vbOKOnly,strComputer
		ShowMessage strcomputer & space(1) & err.description & VbCrLf & "Reset Form to continue."
		Exit Sub
	End If 
	
	
	strKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired"
	strValue = "(Default)"
	
	retval = oReg.getStringValue(HKLM, strKey, strValue,strVal)
	
	
	If retval = 1 Then 
		strmessage = strComputer & " is waiting for a reboot to apply Windows updates."
	Else
		strmessage = strComputer & " is not waiting for a reboot to apply Windows updates"
		CheckOther
	End If 
	
	
	msgbox strMessage,vbinformation + vbokonly,"Reboot Info"
	
End Sub 

Sub CheckOther()
	Dim arrValues
	strKey = "computer\CurrentControlSet\Control\Session Manager"
	strValue = "PendingFileRenameOperations"
	oReg.GetMultiStringValue HKLM,strKey,strValue,arrValues

	If IsNull(arrValues) Then 
		strmessage = strComputer & " not waiting for reboot"	
		Exit Sub 
	End If
	
	For Each strValue In arrValues
		If InStr(strValue,"\??\") > 0 Then
			strmessage = strmessage &  ", but appears to be waiting for reboot from another program."
			Exit For
		End If 
	Next

End Sub 

Function RemoteComputerUsers (strComputer)
	strMessage =""
	Dim otrans, strDom
	strDom = wshShell.ExpandEnvironmentStrings("%USERDNSDOMAIN%")

	On Error Resume Next
	'Cut and pasted from another script and a bit lazy - I could have connected 1x to WMI.. 
	Set otrans = CreateObject("NameTranslate")
	oTrans.Init 1, strDom	' initialize NameTranslate with NT style Domain name

	Dim objLocator, objWMIService, objUserInfoList, objUserInfo
	set objLocator = CreateObject("WbemScripting.SWbemLocator")
	set objWMIService = objLocator.ConnectServer(strComputer) 

	If Err.Number <> 0 Then
		MsgBox "Error reaching or connecting to WMI on " & strComputer,vbcritical & vbokonly, "Failed"
		bFatal = True
		Exit Function
	End If

	Set objUserInfoList = objWMIService.InstancesOf("Win32_ComputerSystem")
	If (Err.Number = 0)  Then
		For Each objUserInfo in objUserInfoList
    		If not isnull(objUserInfo.Username) Then  
	    		strMessage = strMessage &  objUserInfo.UserName & vbTab
		        oTrans.Set 8,objUserInfo.UserName 				'name here is in domain\samname format
	   			strMessage = strMessage & "(" & oTrans.Get(4) & ")" 	'Get DisplayName
	   		End If  
		Next
	Else
		strMessage = Err.Description
	End If

	If  strMessage = ""  Then 
 		strMessage = "(None)"
 	End If
	RemoteComputerUsers = strMessage
End Function

Function MinutesDiff(theTime)
  MinutesDiff = DateDiff("n", theTime, now)
End Function

Function WMIDateStringToDate(utcDate)
	WMIDateStringToDate = CDate(Mid(utcDate, 5, 2) & "/" & _
	Mid(utcDate, 7, 2) & "/" & _
	Left(utcDate, 4) & " " & _
	Mid(utcDate, 9, 2) & ":" & _
	Mid(utcDate, 11, 2) & ":" & _
	Mid(utcDate, 13, 2))
End Function


Sub Clear()
    'Location.Reload(True)	'This reloads, clearing all
    bFatal = False
    'c1.checked = True		'Instead, I am keeping username and password
    computername.value = ""
    PatchList.innerhtml = ""
    button1.disabled = False 
    button1.value = "^ Choose ^"    
    Radio1(0).Checked = False
    Radio1(1).Checked = False
    
    runbutton.disabled = True
    selectbutton.disabled = True    
    ComputerName.Focus( )
  	patchlist.innerhtml = "<font size = 5><center>Remote Windows Update Tool</center></font>"
    showMessage "Enter Another Computer Name"
End Sub 

Function MilPlusFive()
	Dim aTemp,i, strTime,bPM
	If instr(cstr(Time),"PM") Then bPM = True 
	strTime= DateAdd("n", 5, time)
	aTemp = Split(strTime,":")
	If bPM Then aTemp(i) = aTemp(i) + 12
	For i = 0 To 2
		MilPlusFive = MilPlusFive & padNum(left(atemp(i),2))
		If i < 2 Then MilPlusFive = MilPlusFive & ":"
	Next
End Function 

</script>

<BODY STYLE="font:12 pt arial; color:white; filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#0000FF', EndColorStr='#000000')">
     
  <div align="center">
<table border="0" width="87%" id="PatchTable" >
	<tr><td><span id='PatchList'></span></td></tr>
</table>
  </div>
<form method="POST">
</form>
  <div align="center">
  <table border="0" cellspacing="0" cellpadding="0" height="188" width="843">
  <tr>
    <td height="57" width="458" valign="bottom">

<font size="3">Enter Computer Name:</font>
<INPUT TYPE="text" NAME="ComputerName" SIZE="28" 
onmouseover="doPopup 'Enter name of computer', 140,85"  onmouseout="closePopup" >&nbsp;&nbsp;
</td>
    <td height="57" width="40" valign="bottom">

&nbsp;</td>
    <td height="57" width="347" valign="bottom" align="left">
<p>

<input id=Uptime type="button" value="Get uptime" name="UptimeBtn"  onClick="Uptime" onmouseover="doPopup 'Check to see computer uptime.',620,75"  
 onmouseout="closePopup"  style="float: left"></td>
  </tr>
  <tr>
    <td height="58" width="458">

<input type="radio" name="Radio1" value="1" onclick ="BtnUpdate" title="Will create a list of the available updates and patches to review and select.">View Available Patches&nbsp;
<input type="radio" name="Radio1" value="V1" onclick ="BtnUpdate" title = "Select to install all security patches without first reviewing list." >Install All Security Updates<br>
<input type="button" name="button1" disabled = True value="^ Choose ^" onclick="SelectedOption" style="float: Center; "></td>
    <td height="58" width="40">
&nbsp;</td>
    <td height="58" width="347" align="left">
<p>
  <input type="button" name="RBSchedbtn" value="Schedule a reboot"  onclick="SchedReboot" 
 onmouseover="doPopup 'Schedule the computer to reboot.', 680,115"  
 onmouseout="closePopup" style="float: left"></td>
  </tr>
  <tr>
    <td height="73" width="458" rowspan="2" valign="top">

<input type="checkbox" id="C1" name="C1" 
  onmouseover="doPopup 'This program will reboot the remote computer (if required) after an update completes unless there is a logged on user. Uncheck if this is a server that you want to manually reboot.', 40,220"  
  onmouseout="closePopup">Permit reboot after update if no user logged on.<p>&nbsp;</td>
    <td height="73" width="40" rowspan="2" valign="top">

&nbsp;</td>
    <td height="41" width="347" align="left" valign="top">
  <p>
<input type="button" name="LoggedonBtn" value="Check logged on user"  onclick="CheckUser" 
 onmouseover="doPopup 'Get remote user and session time, with choice to force logoff.', 210,160
 "  
 onmouseout="closePopup"></td>
  </tr>
  <tr>
    <td height="32" width="347" align="left">

<p align="center">

<input type="button" name="LUBtn" value="Check whether reboot is pending"  onclick="RebootCheck" 
 onmouseover="doPopup 'Check to see whether computer is waiting to reboot from software or patch install.',120,220"  
 onmouseout="closePopup" style="float: left"></td>
  </tr>
</table>

  <p align="center">&nbsp;</div>

  <div align="center">
    <p>

</div>
  </p>
<p>
<input id=SelectButton  type="button"  disabled= True value="Select All" onClick="SelectDeselect"> 
<input id=runbutton  type="button" disabled= true  value="Install Selected Patches" onClick="InstSelected"></p>
<p>Please enter a username
<input type="text" name="UserName" size="30">


and a password&nbsp;  
<input type=password Name = "PasswordBox" size="20">&nbsp; to be used as the credentials 
for the task that runs the patch script on the remote computer.&nbsp; Delay in minutes 
before patching begins:&nbsp; 
<input type ="text" name = "minutes" size = 3 value="3"></p>

&nbsp;
<div align="center">
  <table border="1" width="92%" id="table1">
    <tr>
      <td align="center"><span id="Message"</span></td>
    </tr>
  </table>
</div>
  <p>

<input id=Clearbutton type="button" value="Reset Form" name="ClearBtn"  onClick="Clear" style="float: right"></p>
</body>
</html>

Open in new window

0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

How to remove superseded packages in windows w60 or w61 installation media (.wim) or online system to prevent unnecessary space. w60 means Windows Vista or Windows Server 2008. w61 means Windows 7 or Windows Server 2008 R2. There are various …
While rebooting windows server 2003 server , it's showing "active directory rebuilding indices please wait" at startup. It took a little while for this process to complete and once we logged on not all the services were started so another reboot is …
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question