|
|
|||||||
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") Code: $strWks="remotesys" $objSession = CreateObject("Microsoft.Update.Session", $strWks) 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 |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
Thanks, I'll give that a try. |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
Let's see your code. |
||||||||
|
|
|||||||
who's code your talking about? |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
I meant Brad. |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
I had two bugs in the addcode line... here is the corrected one. Code: $objsc.addcode('Set Session=CreateObject("Microsoft.Update.Session","' + $strWks + '")') |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
I got results... but I might have changed something else.... hmmm. |
||||||||
|
|
|||||||
Can I see a snipet of your computers.ini |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
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 [edit]NM... just realized this is an INI file. |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
Set Session - CreateObject( what language is that? why there is no = sign? |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
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!!!! |
||||||||
|
|
|||||||
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? |
||||||||
|
|
|||||||
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! |