BradV
(Seasoned Scripter)
2011-11-16 06:39 PM
Microsoft Update Session on remote system

Good Afternoon,

I'm working on a script to check the installed patches on a remote system. I'm trying to create an object of "Microsoft.Update.Session" which points to the remote system. Doing:

 Code:
$objSession = CreateObject("Microsoft.Update.Session")
works fine for creating the object on the local system. However if I try to add:
 Code:
$strWks="remotesys"
$objSession = CreateObject("Microsoft.Update.Session", $strWks)
I get back:
 Code:
ERROR : invalid method/function call: too many parameters!


Anyone have an idea what I am doing wrong? An example is given in:
Scripting Guy Determine Patch Applied

Regards,

Brad


AllenAdministrator
(KiX Supporter)
2011-11-16 06:55 PM
Re: Microsoft Update Session on remote system

I believe this is happening because createobject in kixtart does not support a second parameter. You should be able to pull this off by using the scriptcontrol object.

Something like...

(untested)
 Code:
$sc = CreateObject("ScriptControl")
$sc.language = "VBScript"
$sc.addcode('Session=CreateObject("Microsoft.Update.Session","' + $strWks + '"')
$sc.run
$ObjSession=$sc.codeobject.session


BradV
(Seasoned Scripter)
2011-11-17 11:48 AM
Re: Microsoft Update Session on remote system

Thanks, I'll give that a try. \:\)

BradV
(Seasoned Scripter)
2011-11-17 06:57 PM
Re: Microsoft Update Session on remote system

OK, tried it, but it gives an error when trying to execute the $sc.addcode line. "support for this property or method: 'Session' doesn't" and the rest falls of the window. \:\(

I guess I'll have to distribute the script to each server and then run it remotely there.

Regards,

Brad


LonkeroAdministrator
(KiX Master Guru)
2011-11-17 07:03 PM
Re: Microsoft Update Session on remote system

well, if you just wanna know if the patches are installed, there are other ways to do it.
one is to enumerate the registry uninstall-key.

other one would be to shell out to systeminfo.
bet there is something similar in wmi as well, but these come to head right out of the bat.


AllenAdministrator
(KiX Supporter)
2011-11-17 07:23 PM
Re: Microsoft Update Session on remote system

Let's see your code.

LonkeroAdministrator
(KiX Master Guru)
2011-11-17 07:42 PM
Re: Microsoft Update Session on remote system

who's code your talking about?

LonkeroAdministrator
(KiX Master Guru)
2011-11-17 08:08 PM
Re: Microsoft Update Session on remote system

I couldn't search far enough in to the past to find the complete packages for these scripts but here is a starting point for a code that works without no com-object

 Code:
function GetInstalledsoftware(optional $machine)
	Dim $root, $softwarekey, $index
	dim $temparray[10]

	if not $machine
		$root = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
	else
		$root = "\\" + $machine + "\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
	endif

	$SoftwareKey = enumkey($root,$Index)

	while not @error
		$DisplayName = readvalue($root + $SoftwareKey, "displayname")
		$DisplayVersion = readvalue($root + $SoftwareKey, "DisplayVersion")
		if $DisplayName
			if $count >  ubound($temparray)
				redim preserve $temparray[ubound($temparray)+10]
			endif
			$temparray[$count] = $DisplayName +"  "+ $DisplayVersion
			$count = $count + 1
		endif
		$Index = $Index + 1
		$SoftwareKey = enumkey($root, $Index)
	loop
	if $count > 0
		redim preserve $temparray[$count-1]
	else
		$temparray = ""
	endif
	$getinstalledsoftware = $temparray
endfunction


AllenAdministrator
(KiX Supporter)
2011-11-18 06:32 AM
Re: Microsoft Update Session on remote system

I meant Brad.

BradV
(Seasoned Scripter)
2011-11-18 02:09 PM
Re: Microsoft Update Session on remote system

\:\)

I have 29 Windows 2008 servers that I am responsible to administer, but the patches are applied at the domain level. I don't have access to that. I have to report when a critical vulnerability has been discovered (CVE) whether the systems have been patched. So, I was trying to find a method to search for the applied patches. I'll have to take a look at the registry locations. In the meantime, this is what I was working on so far:

 Code:
;NAME  check_win_patch.kix
;
;DESCRIPTION  This is a script to check for patches on systems.
;
Break On
Dim $SO
;
$SO = SetOpt('Explicit',          'On')
$SO = SetOpt('NoMacrosInStrings', 'On')
;
Dim $strWks, $strComps, $colComps, $objComp
;
$strComps = "u:\Desktop\computers.ini"
;
$colComps = Split(ReadProfileString($strComps,"computers",""),chr(10))
;
For Each $objComp in $colComps
   If $objComp <> ""
      $strWks - ReadProfileString($strComps,"computers",$objComp)
   EndIf
   GetAllPatches($strWks)
   ; more stuff to do here
Next
;
Function GetAllPatches($strWks)
   Dim $objSession, $objSC, $objSearcher, $colUpdates, $intI, $intHistoryCount, $objIdentity, $objUpdate, $objIdentity
   ;
   $objSC = CreateObject("ScriptControl")
   If @ERROR
      ? "There was an error creating the scriptcontrol object " + @SERROR
   EndIf
   $objSC.language = "VBScript"
   $objSC.addcode('Session=CreateObject("Microsoft.Update.Session","' + $strWks + '")')
   If @ERROR
      "There was an error creating the Update Session object"
      ? @SERROR
   EndIf
   $objSC.run
   If @ERROR
      ? "There was an error running the Update Session object " + @SERROR
   EndIf
   $objSession = $objSC.codeobject.session
   If @ERROR
      ? "There was an error creating the Session Object after running the Update Session " @SERROR
   EndIf
   $objSearcher = $objSession.CreateUpdateSearcher
   If @ERROR
      ? " There was an error creating the Update Searcher object " + @SERROR
   EndIf
   $intHistoryCount = $objSearcher.GetTotalHistoryCount
   If @ERROR
      ? "There was an error getting the Update Searcher History count " + @SERROR
   EndIf
   $colUpdates = $objSearcher.QueryHistory(0, $intHistoryCount)
   If @ERROR
      ? "There was an error getting the update collection " + @SERROR
   EndIf
   ;
   ; I haven't really decided what to do with them yet.
   ; So, just printing out the data
   ;
   For Each $objUpdate in $colUpdates
      ? "Title:                   " + $objUpdate.Title
      ? "Description:             " + $objUpdate.Description
      ? "Update application date: " + $objUpdate.Date
      $intI = $objUpdate.Operation
      Select
         Case $intI = 1
            ? "Operation type:         Installation"
         Case $intI = 2
            ? "Operation type:         Uninstallation"
         Case 1
            ? "Operation type:         could not be determined"
      EndSelect
      $intI = $objUpdate.ResultCode
      Select
         Case $intI = 0
            ? "Operation result:       The operation has not started."
         Case $intI = 1
            ? "Operation result:       The operation is in progress."
         Case $intI = 2
            ? "Operation result:       The operation completed successfully."
         Case $intI = 3
            ? "Operation result:       The operation complted, but one or more errors occurred"
            ? "                        during the operation and the results are potentially incomplete."
         Case $intI = 4
            ? "Operation result:       The operation failed to complete."
         Case $intI = 5
            ? "Operation result:       The operation was aborted."
         Case 1
            ? "Operation result:       Could not be determined."
      EndSelect
      $objIdentity = $objUpdate.UpdateIdentity
      ? "Update ID:              " + $objIdentity.UpdateID
      ? "------------------------------------------------------------?
   Next
EndFunction


If there are any typos, I apologize. I have to re-type it all.

Regards,

Brad


AllenAdministrator
(KiX Supporter)
2011-11-18 04:03 PM
Re: Microsoft Update Session on remote system

I had two bugs in the addcode line... here is the corrected one.

 Code:
$objsc.addcode('Set Session=CreateObject("Microsoft.Update.Session","' + $strWks + '")')


BradV
(Seasoned Scripter)
2011-11-18 04:15 PM
Re: Microsoft Update Session on remote system

Hi Allen,

I caught the missing end parenthisis, but missed the "Set " command. I just added that and I'm getting "Invalid number of parameters." Looking further. \:\)


AllenAdministrator
(KiX Supporter)
2011-11-18 04:20 PM
Re: Microsoft Update Session on remote system

I got results... but I might have changed something else.... hmmm.

AllenAdministrator
(KiX Supporter)
2011-11-18 04:23 PM
Re: Microsoft Update Session on remote system

Can I see a snipet of your computers.ini

BradV
(Seasoned Scripter)
2011-11-18 04:27 PM
Re: Microsoft Update Session on remote system

Sure. I have:

 Code:
[computers]
comp1=netbios-name1
comp2=netbios-name2
comp3=netbios-name3


etc. It's pulling the correct computer name. On the first loop, $strWks is set to "netbios-name1"

Regards,

Brad


AllenAdministrator
(KiX Supporter)
2011-11-18 04:50 PM
Re: Microsoft Update Session on remote system

 Quote:

COM exception error "addcode" (Microsoft VBScript runtime error - The remote server machine does not exist or is unavailable: 'CreateObject') [-2147352567/80020009]
Invalid number of parameters.


I don't have a remote machine to test on at the moment. So I just typed in a random computer name and got the error above. So, I'm thinking either the computer you are using is off or doesn't exist... or maybe try using "\\computername" or possibly one with no "-" in it.


Les
(KiX Master)
2011-11-18 04:56 PM
Re: Microsoft Update Session on remote system

 Originally Posted By: BradV
Sure. I have:

 Code:
[computers]
comp1=netbios-name1
comp2=netbios-name2
comp3=netbios-name3


etc. It's pulling the correct computer name. On the first loop, $strWks is set to "netbios-name1"

Regards,

Brad
Ummm... shouldn't you have quotes around the strings? Kix will try to do math on the - operator.
[edit]NM... just realized this is an INI file.


BradV
(Seasoned Scripter)
2011-11-18 05:38 PM
Re: Microsoft Update Session on remote system

I'm pretty sure the ini file and talking to the remote systems works. I had another script that would prompt you for a server name and would then go interrogate that system using WMI to enumerate disk information. I modified it to instead get the computer name from this ini file and ran it. It ran fine and returned all of the correct information from each system. I am looking more closely at the AddCode method.

Regards,

Brad


BradV
(Seasoned Scripter)
2011-11-18 06:03 PM
Re: Microsoft Update Session on remote system

OK, I added:

 Code:
Dim $strCommand
$strCommand = 'Set Session = CreateObject("Microsoft.Update.Session","' + $strWks + '")'
? "The update session command is:"
? $strCommand
$objSC.AddCode($strCommand)


It gets past the AddCode method now and is failing on the run with invalid number of parameters. I think I need to give the code a name and specify that in the run command. Still looking. \:\)


BradV
(Seasoned Scripter)
2011-11-18 06:26 PM
Re: Microsoft Update Session on remote system

OK, slowly making progress. I changed the AddCode section to create a function and then called that function by name in the Run section as follows:

 Code:
$strCommand = 'Function CO
Set Session = CreateObject("Microsoft.Update.Session","' + $strWks + '")
End Function'
$objSC.AddCode($strCommand)
$objSC.Run("CO")


That all passes without any errors. I'm now getting an error on the
 Code:
$objSession = $objSC.CodeObject.Session


I'll have to check that syntax.

\:\)


LonkeroAdministrator
(KiX Master Guru)
2011-11-19 12:10 AM
Re: Microsoft Update Session on remote system

Set Session - CreateObject(

what language is that?
why there is no = sign?


AllenAdministrator
(KiX Supporter)
2011-11-19 02:35 AM
Re: Microsoft Update Session on remote system

I just tried the original script with the modified add code line on a remote pc and while it did produce errors on the screen, it also produced results. You might remove some of you error checking and see what it gets you.

 Code:
The operation completed successfully.
Invalid number of parameters.
Invalid number of parameters.
-2147352562
[317]
-2147352562
There was an error getting the update collection Invalid number of parameters.
Title:                   Update for Windows Server 2003 (KB2641690)
Description:             Install this update to resolve an issue which requires
an update to the certificate revocation list on Windows systems and to keep your
 systems certificate list up to date. After you install this update, you may hav
e to restart your system.
Update application date: 11/17/2011 3:39:47 PM
Operation type:         Installation
Operation result:       The operation completed successfully.
Update ID:              9b1eb814-0ee1-49c1-98cc-6f893ba8ba0f
------------------------------------------------------------?

Title:                   Windows Malicious Software Removal Tool - November 2011
 (KB890830)
Description:             After the download, this tool runs one time to check yo
ur computer for infection by specific, prevalent malicious software (including B
laster, Sasser, and Mydoom) and helps remove any infection that is found. If an
infection is found, the tool will display a status report the next time that you
 start your computer. A new version of the tool will be offered every month. If
you want to manually run the tool on your computer, you can download a copy from
 the Microsoft Download Center, or you can run an online version from microsoft.
com. This tool is not a replacement for an antivirus product. To help protect yo
ur computer, you should use an antivirus product.
Update application date: 11/12/2011 6:56:29 PM
Operation type:         Installation
Operation result:       The operation completed successfully.
Update ID:              846185a2-40da-4909-91d1-064ae329a0ff




BradV
(Seasoned Scripter)
2011-11-21 03:45 PM
Re: Microsoft Update Session on remote system

Allen, you're correct. I was single stepping through, saw the error and quit. I came up with the following function:

 Code:
Function GetAllPatches(optional $strWks)
   ; Function:     GetAllPatches
   ;
   ; Author:       Brad Van Orden
   ;               Tremendous assist from Allen Powell
   ;
   ; Version:      1.1
   ;
   ; Version History: 21 November 2011, finished initial version
   ;                  21 November 2011, Added code to remove carriage returns
   ;                                    and line feeds from the description.
   ;
   ; Action:       Returns an array of all the updates on a given system.
   ;
   ; Syntax:       GetAllPatches([$strWks])
   ;
   ; Parameters:   Optional name of a remote system to query.
   ;               If omitted, will query the current system.
   ;
   ; Returns:      Array listing all updates and their status.
   ;
   ; Dependencies: None
   ;
   ; Kixtart version: tested with 4.61
   ;
   Dim $objSession, $objSearcher, $objUpdate, $colUpdates, $intI, $objSC, $intHistoryCount
   Dim $objIdentity, $objCodeO, $arrPatch[5,1], $intCount
   ;
   If $strWks = ""
      $strWks = "."
   EndIf
   ;
   $objSC                 = CreateObject("ScriptControl")
   $objSC.Language        = "VBScript"
   $objSC.AddCode('Set Session = CreateObject("Microsoft.Update.Session","' + $strWks + '")')
   $objSC.Run
   $objCodeO              = $objSC.CodeObject
   $objSession            = $objCodeO.Session
   $objSearcher           = $objSession.CreateUpdateSearcher
   $intHistoryCount       = $objSearcher.GetTotalHistoryCount
   $colUpdates            = $objSearcher.QueryHistory(0, $intHistoryCount)
   $intCount              = 0
   $arrPatch[0,$intCount] = "Title"
   $arrPatch[1,$intCount] = "Description"
   $arrPatch[2,$intCount] = "Update Application Date"
   $arrPatch[3,$intCount] = "Operation Type"
   $arrPatch[4,$intCount] = "Operation Result"
   $arrPatch[5,$intCount] = "Update ID"
   $intCount              = $intCount + 1
   For Each $objUpdate in $colUpdates
      $arrPatch[0,$intCount] = $objUpdate.Title
      $arrPatch[1,$intCount] = Join(Split(Join(Split($objUpdate.Description,Char(13))),Chr(10)))
      $arrPatch[2,$intCount] = $objUpdate.Date
      $intI                  = $objUpdate.Operation
      Select
         Case $intI = 1
            $arrPatch[3,$intCount] = "Installation"
         Case $intI = 2
            $arrPatch[3,$intCount] = "Uninstallation"
         Case 1
            $arrPatch[3,$intCount] = "Could not be determined"
      EndSelect
      $intI = $objUpdate.ResultCode
      Select
         Case $intI = 0
            $arrPatch[4,$intCount] = "The operation has not started."
         Case $intI = 1
            $arrPatch[4,$intCount] = "The operation is in progress."
         Case $intI = 2
            $arrPatch[4,$intCount] = "The operation completed successfully."
         Case $intI = 3
            $arrPatch[4,$intCount] = "The operation completed, but one or more errors occurred during the operation and the results are potentially incomplete."
         Case $intI = 4
            $arrPatch[4,$intCount] = "The operation failed to complete."
         Case $intI = 5
            $arrPatch[4,$intCount] = "The operation was aborted."
         Case 1
            $arrPatch[4,$intCount] = "Could not be determined."
      EndSelect
      $objIdentity           = $objUpdate.UpdateIdentity
      $arrPatch[5,$intCount] = $objIdentity.UpdateID
      $intCount              = $intCount + 1
      ReDim Preserve $arrPatch[5,$intCount]
   Next
   $intCount = $intCount - 1
   ReDim Preserve $arrPatch[5,$intCount]
   $GetAllPatches = $arrPatch
EndFunction


Jooel, that was a typo. I have to retype everything from the system where I am testing. So, the above may also have a typo. I hope not. \:\)

I called it as:

 Code:
Break On
Dim $SO
;
$SO = SetOpt('Explicit',          'On')
$SO = SetOpt('NoMacrosInStrings', 'On')
;
Dim $strWks, $strComps, $colComps, $objComp, $arrPatches[5,0], $intI
;
$strComps = "u:\Desktop\computers.ini"
;
$colComps = Split(ReadProfileString($strComps,"computers",""),chr(10))
;
For Each $objComp in $colComps
   If $objComp <> ""
      $strWks - ReadProfileString($strComps,"computers",$objComp)
   EndIf
   $arrPatches = GetAllPatches($strWks)
Next
;
For $intI = 1 to Ubound($arrPatches,2)
   ? $arrPatches[0,0] + " : " + $arrPatches[0,$intI]
   ? $arrPatches[0,1] + " : " + $arrPatches[1,$intI]
   ? $arrPatches[0,2] + " : " + $arrPatches[2,$intI]
   ? $arrPatches[0,3] + " : " + $arrPatches[3,$intI]
   ? $arrPatches[0,4] + " : " + $arrPatches[4,$intI]
   ? $arrPatches[0,5] + " : " + $arrPatches[5,$intI]
   ? "----------------------------------------------------------------"
Next


Thanks so much for the help!!!! \:\)


BradV
(Seasoned Scripter)
2011-11-21 04:23 PM
Re: Microsoft Update Session on remote system

Guys, one minor flaw. The description seems to have carriage returns and/or line feeds in it and this does not store well. I tried doing:

 Code:
$arrPatch[1,$intCount] = Join(Split(Join(Split($objUpdate.Description,Char(13))),Chr(10)))


but that doesn't seem to fix it. Am I missing something here?


BradV
(Seasoned Scripter)
2011-11-21 06:15 PM
Re: Microsoft Update Session on remote system

Never mind. I think what I came up with is correct, my command window just wasn't displaying it correctly. I wrote the results to an ini file and it looks fine.

Thanks!