none
VBScript QFE RRS feed

  • Question

  • Hello everyone,

    I have a vbscript to return the updates installed from multiple computers (we use an application to run tjose scripts remotly in each server).

    Now the goal is to return (wscript.echo) ONLY the last 5 installed updates on each server, and compare the last installed DATE, if it was installed more than 1 month ago, then return the message "The last installed update is KBXXXXX - NOT OK"

    Can you help me?

    PS: unfortunately Powershell is not an option. The OS for the computers to query is from Windows 2003 to Windows 2012R, in 32 and 64 bit (more than 3000). I also suspect that some of them will not have .NET installed.

    Here's what I've got so far:

    Option Explicit
    Dim objWMIService
    Dim colQuickFixes
    Dim objQuickFix
    Dim strComputer
    Dim z : z = 0 : Dim y : y = 0
    Dim arrDate : arrDate = Array()
    
    strComputer = "."
    Set objWMIService = GetObject("winmgmts:" _
        & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    
    Set colQuickFixes = objWMIService.ExecQuery _
        ("Select * from Win32_QuickFixEngineering")
    y = colQuickFixes.Count
    
    If y < 1 Then
    	WScript.Echo "No updates found. Exit."
    	WScript.Quit
    End If
    
    'DISPLAY ONLY THE LAST 5 INSTALLED IF ANY!!
    For Each objQuickFix in colQuickFixes
        Wscript.Echo "Computer: " & objQuickFix.CSName & vbTab, _
        "Hot Fix ID: " & Left(objQuickFix.HotFixID,9) & vbTab, _
        "Installation Date: " & objQuickFix.InstalledOn
    Next
    WScript.Echo
    '---------------------------------------------------------------------------------------
    'NOT SORTING CORRECTLY!!!
    ReDim Preserve arrDate(y - 1)
    For Each objQuickFix In colQuickFixes
    	arrDate(z)= FormatDateTime(objQuickFix.InstalledOn,2)
    	z = z + 1
    Next
    
    Call Sort(arrDate)
    
    WScript.Echo "The last installed updated is: " &  arrDate(0)
    
    
    '---------------------------------------------------------------------------------------
    Sub Sort( ByRef myArray )
    	Dim i, j, strHolder
    	For i = ( UBound( myArray ) - 1 ) To 0 Step -1
    		For j= 0 To i
    			If UCase( myArray( j ) ) > UCase( myArray( j + 1 ) ) Then
    				strHolder        = myArray( j + 1 )
    				myArray( j + 1 ) = myArray( j )
    				myArray( j )     = strHolder
    			End If
    		Next
    	Next 
    End Sub
    '---------------------------------------------------------------------------------------

    Thank you.

    Regards.

    Sunday, November 29, 2015 7:06 PM

Answers

  • I case it isn't clear; using "UCase" on a date type will convert it into a string.  Don't use string methods when comparing dates.

    d1 = Now
    d2 = Now

    if d2 > d1 Then
         WScript.Echo "D2 is newer"
    Else
        WScript.Echo "D1 is newer"
    End If


    \_(ツ)_/

    • Marked as answer by JPKI Sunday, November 29, 2015 11:47 PM
    Sunday, November 29, 2015 10:38 PM

All replies

  • You are asking for someone to redesign a script that you have not written.  I recommend that you contact a professional to help you with this.  Meanwhile you can look at this for some background information: https://social.technet.microsoft.com/Forums/en-US/c47b1bc2-f7fd-4d2e-8ff2-e8a81ce090d4/this-forum-is-for-scripting-questions-rather-than-script-requests?forum=ITCG


    \_(ツ)_/

    Sunday, November 29, 2015 7:31 PM
  • You are asking for someone to redesign a script that you have not written.  I recommend that you contact a professional to help you with this.  Meanwhile you can look at this for some background information: https://social.technet.microsoft.com/Forums/en-US/c47b1bc2-f7fd-4d2e-8ff2-e8a81ce090d4/this-forum-is-for-scripting-questions-rather-than-script-requests?forum=ITCG


    \_(ツ)_/

    I\m not requesting a new script, but rather understand why sorting is not working correctly.

    Regarding to the script, I wrote everything except (Sub Sort) that came from this forum (https://social.technet.microsoft.com/Forums/en-US/fb489b70-28ee-4901-88f2-65a8c48a8da6/vbscript-cant-sort-array).


    • Edited by JPKI Sunday, November 29, 2015 8:06 PM
    Sunday, November 29, 2015 8:05 PM
  • Hello everyone,

    I have a vbscript to return the updates installed from multiple computers (we use an application to run tjose scripts remotly in each server).

    Now the goal is to return (wscript.echo) ONLY the last 5 installed updates on each server, and compare the last installed DATE, if it was installed more than 1 month ago, then return the message "The last installed update is KBXXXXX - NOT OK"

    Can you help me?

    PS: unfortunately Powershell is not an option. The OS for the computers to query is from Windows 2003 to Windows 2012R, in 32 and 64 bit (more than 3000). I also suspect that some of them will not have .NET installed.

    Here's what I've got so far:

    I see nothing here about a sort and I see it is asking for changes to the script.  If that is not what you want then you should reword it to clarify that you want something else.


    \_(ツ)_/

    Sunday, November 29, 2015 8:09 PM
  • You cannot sort dates if you convert them into strings.   Just sort an array of date objects.  Dates will compare correctly for a sort.


    \_(ツ)_/

    Sunday, November 29, 2015 8:11 PM
  • Hello everyone,

    I have a vbscript to return the updates installed from multiple computers (we use an application to run tjose scripts remotly in each server).

    Now the goal is to return (wscript.echo) ONLY the last 5 installed updates on each server, and compare the last installed DATE, if it was installed more than 1 month ago, then return the message "The last installed update is KBXXXXX - NOT OK"

    Can you help me?

    PS: unfortunately Powershell is not an option. The OS for the computers to query is from Windows 2003 to Windows 2012R, in 32 and 64 bit (more than 3000). I also suspect that some of them will not have .NET installed.

    Here's what I've got so far:

    I see nothing here about a sort and I see it is asking for changes to the script.  If that is not what you want then you should reword it to clarify that you want something else.


    \_(ツ)_/

    I was using the sub Sort to be more easy to retrieve the last 5 installed and also the last one, the problem is that is not sorting correctly, I think that must be related with the date format.

    But if you have a different approach, please tell me.


    • Edited by JPKI Sunday, November 29, 2015 8:14 PM
    Sunday, November 29, 2015 8:13 PM
  • You cannot sort dates as strings.  Do not convert the dates to strings.  Just compre and sort the date objects.  "FormatDateTime" converts a date object into a string.

    Why do you think you need to sort the dates?


    \_(ツ)_/

    Sunday, November 29, 2015 8:43 PM
  • You cannot sort dates as strings.  Do not convert the dates to strings.  Just compre and sort the date objects.  "FormatDateTime" converts a date object into a string.

    Why do you think you need to sort the dates?


    \_(ツ)_/

    Yep that s may thought too, the FormatDateTime was just an attempt to get a different result from sort since without FormatDateTime was also not working.

    I think I need to sort dates (in this case strings that are returned by QFE) to get the latest update installed, If I could get that latest ones I could isolate and get the last 5 five installed.

    Do you know other method to achieve this?

    Sunday, November 29, 2015 8:52 PM
  • I think this may be what you are looking for:

    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
    Set colQuickFixes = objWMIService.ExecQuery("Select * from Win32_QuickFixEngineering")
    For Each objQuickFix in colQuickFixes
        WScript.Echo CDate(objQuickFix.InstalledOn)
    Next


    \_(ツ)_/


    • Edited by jrv Sunday, November 29, 2015 9:24 PM
    Sunday, November 29, 2015 9:05 PM
  • Here is the whole thing in PowerShell

    gwmi win32_quickfixengineering | sort installedon -desc | select -First 5


    \_(ツ)_/

    Sunday, November 29, 2015 9:09 PM
  • I think this may be what you are looking for:

    Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
    
    Set colQuickFixes = objWMIService.ExecQuery("Select * from Win32_QuickFixEngineering")
    
    Set sorted = CreateObject("ADODB.Recordset")
    
    For Each objQuickFix in colQuickFixes
        WScript.Echo CDate(objQuickFix.InstalledOn)
    Next


    \_(ツ)_/

    Not following, what is the purpose of the "Set sorted = CreateObject("ADODB.Recordset")" how do your sort .InstalledOn?


    • Edited by JPKI Sunday, November 29, 2015 9:16 PM
    Sunday, November 29, 2015 9:15 PM
  • Here is the whole thing in PowerShell

    gwmi win32_quickfixengineering | sort installedon -desc | select -First 5


    \_(ツ)_/

    eheheh, I wish I could use PS...

    But not in this case.

    Sunday, November 29, 2015 9:15 PM
  • Not following, what is the purpose of the "Set sorted = CreateObject("ADODB.Recordset")" how do your sort .InstalledOn?


    Sorry It was a leftover. Just remove it.

    \_(ツ)_/

    Sunday, November 29, 2015 9:25 PM
  • PowerShell works with WMI from anywhere.

    gwmi win32_quickfixengineering  -computer remotepc |
          sort installedon -desc | select -First 5



    \_(ツ)_/

    Sunday, November 29, 2015 9:27 PM
  • PowerShell works with WMI from anywhere.

    gwmi win32_quickfixengineering  -computer remotepc |
          sort installedon -desc | select -First 5



    \_(ツ)_/

    Yes I know, Inf fact we're using PS now for a very large number of servers...

    But these new servers are a sort of "takeover", and they don't have the same requirements that we have internally, after the "takeover" we can standardize the new systems, until then we're left with VBScript or batch.

    So I did (using a part the initial example) change the sort portion to:

    ReDim Preserve arrDate(y - 1)
    For Each objQuickFix In colQuickFixes
    	arrDate(z)= CDate(objQuickFix.InstalledOn)
    	WScript.Echo IsDate(arrDate(z)), "Date: " & arrDate(z)
    	z = z + 1
    Next
    Call Sort(arrDate)
    WScript.Echo "The last installed updated is: " &  arrDate(0)

    But still doesn't work.

    Sunday, November 29, 2015 9:40 PM
  • PowerShell does not have to be installed on the new servers.  WMI is built in and enabled by default.

    \_(ツ)_/

    Sunday, November 29, 2015 9:41 PM
  • PowerShell works with WMI from anywhere.

    gwmi win32_quickfixengineering  -computer remotepc |
          sort installedon -desc | select -First 5



    \_(ツ)_/

    Yes I know, Inf fact we're using PS now for a very large number of servers...

    But these new servers are a sort of "takeover", and they don't have the same requirements that we have internally, after the "takeover" we can standardize the new systems, until then we're left with VBScript or batch.

    So I did (using a part the initial example) change the sort portion to:

    ReDim Preserve arrDate(y - 1)
    For Each objQuickFix In colQuickFixes
    	arrDate(z)= CDate(objQuickFix.InstalledOn)
    	WScript.Echo IsDate(arrDate(z)), "Date: " & arrDate(z)
    	z = z + 1
    Next
    Call Sort(arrDate)
    WScript.Echo "The last installed updated is: " &  arrDate(0)

    But still doesn't work.

    Convert all dates before you add them to the array.  You can then directly compare them.

    Your sort routine is designed to sort strings.  You cannot sort dates as strings.


    \_(ツ)_/

    Sunday, November 29, 2015 9:44 PM
  • PowerShell does not have to be installed on the new servers.  WMI is built in and enabled by default.

    \_(ツ)_/

    Right, but to connect WMI you need DCOM FW exceptions, we also need User/Password... (That will not gona happen)

    We're stuck with a tool that they have that runs an agent in each server, the tool supports Batch, VB and Powershell, but since the tool runs the cmds on each server locally, we would need Powershell installed for each server.


    • Edited by JPKI Sunday, November 29, 2015 9:47 PM
    Sunday, November 29, 2015 9:47 PM
  • I case it isn't clear; using "UCase" on a date type will convert it into a string.  Don't use string methods when comparing dates.

    d1 = Now
    d2 = Now

    if d2 > d1 Then
         WScript.Echo "D2 is newer"
    Else
        WScript.Echo "D1 is newer"
    End If


    \_(ツ)_/

    • Marked as answer by JPKI Sunday, November 29, 2015 11:47 PM
    Sunday, November 29, 2015 10:38 PM
  • I case it isn't clear; using "UCase" on a date type will convert it into a string.  Don't use string methods when comparing dates.

    d1 = Now
    d2 = Now

    if d2 > d1 Then
         WScript.Echo "D2 is newer"
    Else
        WScript.Echo "D1 is newer"
    End If


    \_(ツ)_/

    You were very clear (as always), I was just testing...

    Here's what I come up with, tell me what you think (I did some testing in some servers and the results look promissing... :)):

    Option Explicit
    Dim objWMIService
    Dim colQuickFixes
    Dim objQuickFix
    Dim strComputer
    Dim z : z = 0 : Dim y : y = 0 : Dim i : i = 0
    Dim arrDate : arrDate = Array()
    
    strComputer = "."
    Set objWMIService = GetObject("winmgmts:" _
        & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    
    Set colQuickFixes = objWMIService.ExecQuery _
        ("Select * from Win32_QuickFixEngineering")
    y = colQuickFixes.Count
    
    If y < 1 Then
    	WScript.Echo "No updates found. Exit."
    	WScript.Quit
    End If
    
    
    Dim date1
    Dim dateMin, dateMax
    
    For Each objQuickFix In colQuickFixes
    	
    	If IsDate(objQuickFix.InstalledOn) then
    	date1 = CDate(objQuickFix.InstalledOn)
    '		If IsDate(date1) Then
    			ReDim Preserve arrDate(z)
    			arrDate(z) = date1
    			'WScript.Echo IsDate(arrDate(z)), arrDate(z)
    			z = z + 1
    '		End If
    	End IF
    Next
    
    dateMin = date1
    dateMax = date1
    
    
    
    If CInt(UBound(arrDate)) > 0 Then
    	
    	For i = 0 to UBound(arrDate)
    		If arrDate(i) < dateMin Then dateMin = arrDate(i)
    		If arrDate(i) > dateMax Then dateMax = arrDate(i)
    	Next
    	
    	WScript.Echo "The date of the most recent update : " & CStr( dateMax )
    	WScript.Echo "The date of the less recent update : " & CStr( dateMin )
    	WScript.Echo
    
    Else
    	WScript.Echo "No MAX nor MIN dates available. Exit"
    	WScript.Echo
    	WScript.Quit
    End If
    
    
    For Each objQuickFix in colQuickFixes
        Wscript.Echo "Computer: " & objQuickFix.CSName & vbTab, _
        "Hot Fix ID: " & Left(objQuickFix.HotFixID,9) & vbTab, _
        "Installation Date: " & objQuickFix.InstalledOn
    Next
    
    WScript.Echo

    Sunday, November 29, 2015 11:22 PM
  • I had to test "If IsDate" in the loop because I found out that some servers don t have date for some updates (maybe due sysprep)
    Sunday, November 29, 2015 11:26 PM
  • There is a registry key that tell you the date of the last applied update.


    \_(ツ)_/

    Sunday, November 29, 2015 11:47 PM
  • There is a registry key that tell you the date of the last applied update.


    \_(ツ)_/

    WHAT!!!! what is that?
    Monday, November 30, 2015 12:07 AM
  • The WndowsUpdate  key,

    Also WMI will not give you all updates.

    https://gallery.technet.microsoft.com/b9ba9b9d-cfc7-4bc9-980b-d914e81b3a84


    \_(ツ)_/

    Monday, November 30, 2015 12:47 AM
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install


    \_(ツ)_/

    Monday, November 30, 2015 12:51 AM
  • The WndowsUpdate  key,

    Also WMI will not give you all updates.

    https://gallery.technet.microsoft.com/b9ba9b9d-cfc7-4bc9-980b-d914e81b3a84


    \_(ツ)_/

    QueryHistory not reliable.

    WUA GetTotalHistoryCount method only returns a list of operations that are not necessarily referent to installed updates (only lists success and fails).

    Further more, if you clean/delete the "SoftwareDistribution" you loose ALL history for operations and will only record new ones...

    WMI gives at least the windows updates (installed either manually or by WUA agent), that's what I'm tracking on this :)

    Monday, November 30, 2015 1:08 AM
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install


    \_(ツ)_/

    I'll give it a test, where did you found that info? MSDN, MSKB?
    Monday, November 30, 2015 1:09 AM
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install


    \_(ツ)_/

    I'll give it a test, where did you found that info? MSDN, MSKB?

    Ok tested, the reg key only updates if using WUA, manual installed updates don`t change the date on that key.

    But is useful information, thanks.

    Monday, November 30, 2015 1:22 AM
  • I found that the Time Value VALUE LastSuccessTime under:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install

    Is NOT refreshed in some servers, in others appears OK (all are using the same WSUS)

    Any one knows anything about this?

    Thank you


    • Edited by JPKI Wednesday, December 2, 2015 12:46 AM
    Wednesday, December 2, 2015 12:46 AM
  • For WSUS the WSUS reports will be the only accurate report.

    If you are using WSUS then post in the WSUS forum for information on how to get customized reports with PowerShell.


    \_(ツ)_/

    Wednesday, December 2, 2015 12:59 AM