How to Discover if Windows Update is optional, rec

2019-05-16 23:54发布

问题:

I'm currently writing a type of automated program that among other things searches for windows updates. It can search for and retrieve updates just fine, but I am having trouble drilling down for what priority an update is. I would like to have an output similar to:

Total Updates: 25 Important: 12 Optional: 13

The .IsMandatory field is only used when the update is specifically for WUA itself, so important updates are not necessary labeled with .IsMandatory.

Code snippet for searching the WUA is below:

Dim updateSession  ' Object to hold our MS Update Session
Dim updateSearcher ' Object to perform our MS Win Update Search
Dim results        ' Object to hold our MS Win Update Search Results
Dim stopWatch As New Stopwatch()
stopWatch.Start()

outputWriter.WriteLine("----WINDOWS UPDATES-----@ " & Now, False)
outputWriter.WriteLine("  -We are beginning our update search. Please note, this may take a few minutes." & _
                       "  On Windows Server 2003 this may take 800 years.", False)

' We cannot guarantee the update check will succeed, so use a try catch in case of error.
Try
    updateSession = CreateObject("Microsoft.Update.Session")
    updateSearcher = updateSession.CreateUpdateSearcher()
    results = updateSearcher.Search("IsInstalled=0 and Type='Software' and IsHidden=0")
Catch ex As Exception
    outputWriter.WriteLine("  ERROR: Something went wrong in our update search. Details below...", False)
    outputWriter.WriteLine("  Error Msg: " & ex.Message, False)
    Return 1
 End Try

Dim imp_updates = 0
Dim opt_updates = 0
For i = 0 To results.Updates.Count - 1
    Dim update = results.Updates.Item(i)
    If update.IsMandatory = False Then 
        opt_updates = opt_updates + 1
    Else
        imp_updates = imp_updates + 1
    End If
 Next

 outputWriter.WriteLine("Important Updates: " & imp_updates, True)
 outputWriter.WriteLine("Optional Updates:  " & opt_updates, True)

回答1:

It turns out that I did not have a reference to WUApi.DLL in my code. Once I put that reference in, I was successfully able to cast my result as an IUpdate3. IUpdate3 is an interface which contains a property named BrowseOnly. What BrowseOnly does, is specify if an update is optional or not. Using BrowseOnly, I can determine if an update is important or optional.

See below (IUpdate3 used around the middle of the code chunk)...

''' <summary>
''' Performs a windows update check for any updates that are...
''' A: Not installed
''' B: Not hidden
''' C: Software updates (OS and software, no hardware updates)
''' </summary>
''' <returns>0 on success, 1 on failure</returns>
''' <remarks></remarks>
Function checkForUpdates() As Integer

    Dim updateSession  ' Object to hold our MS Update Session
    Dim updateSearcher ' Object to perform our MS Win Update Search
    Dim results        ' Object to hold our MS Win Update Search Results
    Dim stopWatch As New Stopwatch()
    stopWatch.Start()

    outputWriter.WriteLine("----WINDOWS UPDATES-----@ " & Now, False)
    outputWriter.WriteLine("  -We are beginning our update search. Please note, this may take a few minutes." & _
                           "   On Windows Server 2003 this may take 800 years.", False)

    ' We cannot guarantee the update check will succeed, so use a try catch in case of error.
    Try
        updateSession = CreateObject("Microsoft.Update.Session")
        updateSearcher = updateSession.CreateUpdateSearcher()
        results = updateSearcher.Search("IsInstalled=0 and Type='Software' and IsHidden=0")
    Catch ex As Exception
        outputWriter.WriteLine("  ERROR: Something went wrong in our update search. Details below...", False)
        outputWriter.WriteLine("  Error Msg: " & ex.Message, False)
        Return 1
    End Try

    outputWriter.WriteLine("  -Windows update search has successfully completed. Beginning iteration of result set...", False)

    ' Similar to above, we cannot guarantee iterating through our result set will succeed. Use a try catch.
    Try
        Dim totalUpdates = results.Updates.Count
        outputWriter.WriteLine("-----Windows Updates-----@ " & Now, True)
        If results.Updates.Count = 0 Then
            outputWriter.WriteLine("Total Updates: 0", True)
            outputWriter.WriteLine("Important:     0", True)
            outputWriter.WriteLine("Optional:      0", True)
        Else
            Dim imp_updates = 0
            Dim opt_updates = 0
            For i = 0 To totalUpdates - 1
                Dim update = results.Updates.Item(i)
                If CType(update, WUApiLib.IUpdate3).BrowseOnly = True Then ' BrowseOnly is specifically used for whether an update is deemed optional or not (True for optional)
                    opt_updates = opt_updates + 1
                Else
                    imp_updates = imp_updates + 1
                End If
            Next

            outputWriter.WriteLine("Total Updates: " & totalUpdates, True)
            outputWriter.WriteLine("Important:     " & imp_updates, True)
            outputWriter.WriteLine("Optional :     " & opt_updates, True)

        End If
        stopWatch.Stop()
        If stopWatch.ElapsedMilliseconds >= 1000 Then
            outputWriter.WriteLine("--------Total Time: " & Math.Round((CDbl(stopWatch.ElapsedMilliseconds) / 1000), 2) & " Sec----------------" & vbCrLf, True)
        Else
            outputWriter.WriteLine("--------Total Time: " & stopWatch.ElapsedMilliseconds & " MS-------------------" & vbCrLf, True)
        End If

    Catch ex As Exception
        outputWriter.WriteLine("  ERROR: We encountered an issue while iterating through Windows Update Search Results. Details below...", False)
        outputWriter.WriteLine("  Error Msg: " & ex.Message, False)
        Return 1
    End Try

    outputWriter.WriteLine("  -Iteration of Windows Update Search Results has successfully completed.", False)
    outputWriter.WriteLine("-------------------------" & vbCrLf, False)

    ' Clean up our objects.
    updateSession = Nothing
    updateSearcher = Nothing
    results = Nothing

    ' Success!
    Return 0
End Function


回答2:

You should be able to check the MsrcSeverity of the update:

    Select Case update.MsrcSeverity
        Case "Important"
        Case "Critical"
        Case "Moderate"
        Case "Low"
        Case "Unspecified"
    End Select


回答3:

Loop over results.Updates.Count and then check for each Update.Item its Categories item names.

For i As Integer = 0 To results.Updates.Count - 1
    updateCategories = results.Updates.Item(i).Categories
    For j As Integer = 0 To updateCategories.Count - 1
        updateCategorie = updateCategories.Item(j).Name
        Select Case updateCategorie
            Case "Updates"
                'do something
            Case "Critical Updates"
                'do something
            Case "Security Updates"
                'do something
            Case "Service Packs"
                'do something
            Case "Update Rollups"
                'do something
            Case "Feature Packs"
                'do something
            Case Else
                'do something
        End Select
    Next
Next