none
VBS: How to Install Updates manually from SCCM 2012 Client

    Question

  • Unfortunately, my organization has restricted use of PS. I have around 500 desktops where i need to ensure they are idle (I have certain criteria for this) and manually deploy patches during every patching cycle, i have written logic for verifying the computer status. I have below VBS so far for downloading and installing patches, this is returning either generic error or syntax error ('Invalid Parameter' or 'Type Mismatch') at line 10 in below code. Since i am clueless about what format 'InstallUpdates' method accepts in VBScript (I can try to cast the search result if i know the format):

    I have laready tried to pass 'colItems' by querying only 'UpdateID', 'BulletinID' and 'ArticleID' with no luck. Any help in this regard is highly appreciated.

    My VBScript: Set objWMIService = GetObject("winmgmts:\\.\root\ccm\ClientSDK") Set objInstall = GetObject("winmgmts:\\.\root\ccm\ClientSDK:CCM_SoftwareUpdatesManager") Set colItems = objWMIService.ExecQuery("SELECT * FROM CCM_SoftwareUpdate Where ComplianceState = 0") MsgBox colItems.Count Redim updatesList(colItems.Count) n = 0 For Each objItem In colItems n = n+1 UpdatesList(n-1) = objItem.UpdateID objInstall.InstallUpdates(UpdatesList) Next

    Tuesday, April 10, 2018 10:52 AM

All replies

  • In the script at https://gallery.technet.microsoft.com/scriptcenter/Install-All-Missing-8ffbd525#content, the argument list for InstallUpdates is an array of objects representing each missing update, not an array of ids.


    Jason | https://home.configmgrftw.com | @jasonsandys

    Tuesday, April 10, 2018 2:04 PM
    Moderator
  • Hi,

    Please refer to the following blog on How to install software updates using the client-side SDK:

    https://blogs.technet.microsoft.com/manageabilityguys/2012/08/31/how-to-install-software-updates-using-the-client-side-sdk/

    Best Regards,

    Lorry


    Please remember to mark the replies as answers if they help. If you have feedback for TechNet Subscriber Support, contact tnmff@microsoft.com.

    Wednesday, April 11, 2018 4:15 AM
  • Dear Jason,

    Thank you for the clarification!

    I have tried to pass the query result directly to the InstallUpdates method, it returns me 'Generic Error'. In the below line of PS code, i have noticed that the objects array is casted before passing to InstallUpdates method, any idea how to do that in VBS?

    $MissingUpdatesReformatted = @($MissingUpdates | ForEach-Object {if($_.ComplianceState -eq 0){[WMI]$_.__PATH}})
    Wednesday, April 11, 2018 11:50 AM
  • Dear Lorry,

    I am failing at step 2: Stick the instances in an array (if they aren't already)

    Not sure how to do this in VBS

    Wednesday, April 11, 2018 11:52 AM
  • Hi,

    Sorry for delay replied.

    My appeal is also a PS script . If you want to use VB script to download and install updates, please refer to the following script:

    https://gallery.technet.microsoft.com/scriptcenter/VB-Script-to-Check-and-620579cd#content

    Best Regards,

    Lorry


    Please remember to mark the replies as answers if they help. If you have feedback for TechNet Subscriber Support, contact tnmff@microsoft.com.

    Friday, April 13, 2018 9:22 AM
  • Hi,

    You have not update for a long time. 

    Have you solved this problem? Can you share the solutions to help more people?

    Please remember to mark the replies as answer if they help.

    Best Regards,

    Lorry


    Please remember to mark the replies as answers if they help. If you have feedback for TechNet Subscriber Support, contact tnmff@microsoft.com.

    Monday, April 30, 2018 8:41 AM
  • Dear Lorry,

    My apologies!!

    I was on another assignment for last 2 months and could not spare some time. However, i didn't fin a solution using VBScript bu have managed to create run time PS Script from VBS and kill the same after execution.

    Below is the code that worked for me (Though the sleep timer are kept low for the convenience of testing iterations):

    '================================================================================================================================================================================================================================
    ' Global Declarations
    '================================================================================================================================================================================================================================

    Dim objFSO
    Dim objFolder
    Dim objFile
    Dim strTopFolderName
    Dim WshShell
    Dim exeName
    Dim logPath
    Dim FileLog
    Dim objTopFolder
    Dim totalCount
    Dim objSubFolder
    Dim objLogDir
    Dim Patch_Log
    Dim strText
    Dim objCPAppletMgr
    Dim arrClientActions
    Dim objClientAction
    Dim p
    Dim strCode
    Dim objScript
    Dim strHost
    Dim strPingCommand
    Dim ReturnCode
        Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set WshShell = CreateObject("WScript.Shell")
    strScrPath = "C:\TeamCDS\Install.ps1"
    logPath = "C:\TeamCDS\Logs\"
    FileLog = "C:\TeamCDS\Logs\Patch_Log.log"
    strHost = "xxxxxxxxxxxx"
    strPingCommand = "ping -n 1 -w 5000 " & strHost
    p = 0
    exeName = "powershell -executionpolicy bypass -windowstyle hidden -noninteractive -nologo -file " & strScrPath

    Call Acq_Status()

    '================================================================================================================================================================================================================================
    'Main Program
    '================================================================================================================================================================================================================================
    Sub Acq_Status()
    p = p + 1
    If p = 1 Then
    Call CreateLog()
    Call UpdateLog (2, "_____________________________________________________________________________")
    Call UpdateLog(1, "Starting Security Patch Installer Application....")
    End If

    ReturnCode = WshShell.Run(strPingCommand, 0, True)
    Call Conclude(ReturnCode)
    End Sub

    '================================================================================================================================================================================================================================
    'Run installer if LACE is idle, wait if running
    '================================================================================================================================================================================================================================
    Sub Conclude(ReturnCode)
    If ReturnCode = 0 Then
    Call UpdateLog(1,"LACE is Idle and Connected to Network, Synchronizing SCCM...")
    Call RunInstaller()
    Else
    If p < 11 Then
    If Not ReturnCode = 0 Then
    Call UpdateLog(1,"LACE is not connected to network,  Will Retry after 4 Hours....")
    End If
    SampSetCount = 0
    SingInjCount = 0
    WScript.Sleep 20000
    Call Acq_Status()
    Else
    If Not ReturnCode = 0 Then
    Call UpdateLog(1,"LACE is still not connected to network,  Will Retry after 6 Days....")
    End If
    Call UpdateLog(1,"Closing Security Patch Installer Application....")
    Call UpdateLog (2, "_____________________________________________________________________________")
    End If
    End If
    End Sub

    '================================================================================================================================================================================================================================
    'Run SCCM Client
    '================================================================================================================================================================================================================================
    Sub RunInstaller()
    On Error Resume Next

    Set objCPAppletMgr = CreateObject("CPApplet.CPAppletMgr")
    If Err.Number <> 0 Then
    Call UpdateLog(1,"SCCM Client not found, Quitting Security Patch Installer Application....")
    Call UpdateLog (2, "_____________________________________________________________________________")
    wscript.quit
    End if

    On Error Goto 0

    Set arrClientActions = objCPAppletMgr.GetClientActions()
    For Each objClientAction In arrClientActions
          objClientAction.PerformAction
          strText = strText & vbCrLf & " -- Action: '" & objClientAction.Name & "' has been initiated successfully."
    Next
    Call UpdateLog(1,strText)
    WScript.Sleep 12000

    Call UpdateLog(1,"Creating Runtime Script....")

    Call CreateInstaller()
    Call UpdateLog(1,"Initiating Patch availability check and installation....")
    runApp = WshShell.Run (exeName, 1, True)

    WScript.Sleep 6000
    objFSO.DeleteFile strScrPath, Force
    Call UpdateLog(1, "Deleted Runtime Script....")

    Call UpdateLog(1, "Closing Security Patch Installer Application....")
    Call UpdateLog (2, "_____________________________________________________________________________")
    End Sub

    '================================================================================================================
    ' Create Log file
    '================================================================================================================
    Sub CreateLog ()
    If Not objFSO.FolderExists(logPath) Then
    Set objLogDir = objFSO.CreateFolder(logPath)
    Set Patch_Log = objFSO.CreateTextFile(FileLog, True)
    Set Patch_Log = Nothing
    Else
    If Not objFSO.FileExists(FileLog) Then
    Set Patch_Log = objFSO.CreateTextFile(FileLog, True)
    Set Patch_Log = Nothing
    End If
    End If
    End Sub
    '================================================================================================================
    ' Update Log file
    '================================================================================================================
    Sub UpdateLog(Con, Info)
    Set Patch_Log = objFSO.OpenTextFile(FileLog, 8)
    If Con = 1 Then
    Patch_Log.WriteLine(Date() & ", " & Time() & ": " & Info)
    Else
    Patch_Log.WriteLine(Info)
    End If
    Set Patch_Log = Nothing
    End Sub

    '================================================================================================================
    ' Create Runtime Script
    '================================================================================================================
    Sub CreateInstaller()

    Set objScript = objFSO.CreateTextFile(strScrPath, True)
    Set objScript = Nothing

    strCode = "$system = $env:computername" & vbCrLf &_
    "$log = " & """C:\TeamCDS\Logs\Patch_Log.log""" & vbCrLf &_
    "$date = (Get-Date).ToString()" & vbCrLf &_
    """$date : Checking for available patches...""" & " + " & """`r`n""" & " | Out-File -encoding ascii $log -Append" & vbCrLf &_
    "$wmicheck = $null" & vbCrLf &_
    "$wmicheck = Get-WmiObject -ComputerName $system -namespace root\cimv2 -Class Win32_BIOS -ErrorAction SilentlyContinue" & vbCrLf &_
    "if ($wmicheck)" & vbCrLf &_
    "{" & vbCrLf &_
    "$TargetedUpdates = Get-WmiObject -ComputerName $system -Namespace root\CCM\ClientSDK -Class CCM_SoftwareUpdate -Filter ComplianceState=0" & vbCrLf &_
    "$approvedUpdates = ($TargetedUpdates |Measure-Object).count" & vbCrLf &_
    "$pendingpatches = ($TargetedUpdates |Where-Object {$TargetedUpdates.EvaluationState -ne 8} |Measure-Object).count" & vbCrLf &_
    "$rebootpending = ($TargetedUpdates |Where-Object {$TargetedUpdates.EvaluationState -eq 8} |Measure-Object).count" & vbCrLf &_
    "if ($pendingpatches -gt 0)" & vbCrLf &_
    "{" & vbCrLf &_
    "try {" & vbCrLf &_
    "$MissingUpdatesReformatted = @($TargetedUpdates | ForEach-Object {if($_.ComplianceState -eq 0){[WMI]$_.__PATH}})" & vbCrLf &_
    "$InstallReturn = Invoke-WmiMethod -ComputerName $system -Class CCM_SoftwareUpdatesManager -Name InstallUpdates -ArgumentList (,$MissingUpdatesReformatted) -Namespace root\ccm\clientsdk" & vbCrLf &_
    """Targeted Patches: $approvedUpdates, Pending Patches: $pendingpatches, Reboot Pending Patches: $rebootpending, initiated $pendingpatches Patches for installation""" & " | Out-File -encoding ascii $log -Append" & vbCrLf &_
    "}" & vbCrLf &_
    "catch {" & """$date : Pending patches - $pendingpatches but unable to install, handle manually""" & " | Out-File -encoding ascii $log -Append}" & vbCrLf &_
    "}" & vbCrLf &_
    "else {" & """$date : Targeted Patches: $approvedUpdates, Pending Patches: $pendingpatches, Reboot Pending Patches: $rebootpending""" & " | Out-File -encoding ascii $log -Append}" & vbCrLf &_
    "}" & vbCrLf &_
    "else {" & """$date : Unable to connect to WMI host, Installation failed""" & " | Out-File -encoding ascii $log -Append}" & vbCrLf &_
    """$date : Finished execution of Runtime Script...""" & " | Out-File -encoding ascii $log -Append"

    Set objScript = objFSO.OpenTextFile(strScrPath, 8)
    objScript.WriteLine(strCode)
    Set objScript = Nothing
    Call UpdateLog(1,"Created Runtime Script....")
    End Sub

    Tuesday, July 3, 2018 9:20 AM