leighlandwhitehead

scriptcontrol for windows update

8 posts in this topic

#1 ·  Posted (edited)

Hi Guys i was wondering if anyone could help me with the following code . i am having a problem with getting the error message "variable must be of type object " , im have tried to create a new script control for each of the objects(don't know if this is correct) . the error message is displayed after the line "_updatedebug($window,@CRLF & "Downloading updates...")".

any help would be much appreciated

thanks 

;
#include <File.au3>
#include <GuiEdit.au3>
#include <GuiStatusBar.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ScrollBarsConstants.au3>
#include <MsgBoxConstants.au3>
#include <Date.au3>
#include <GuiEdit.au3>
#include <Inet.au3>
#include <AD.au3>

;###############################

;create the debug window
Func _createdebug()
    Global $window
$time =  _NowTime(5)
    $splittime = StringSplit($time,":",1)
    $currenttime= $splittime[1] & $splittime[2] & $splittime[3]
    global $Debuglog = Envget("temp") & "\laptoplog" & $currenttime & ".log"

_FileCreate($Debuglog)

    GUICreate("Debug", 600, 700)
    $window = GUICtrlCreateEdit("", 2, 2,597, 697, BitOR($ES_WANTRETURN, $WS_VSCROLL,$ES_READONLY,$ES_AUTOVSCROLL))
    GUISetState(@SW_SHOW)

    return $window
EndFunc


;update the debug window
func _updatedebug($window,$textdebug)
    local $filehandle

    $filehandle = fileopen($Debuglog,1)
    FileWriteLine($filehandle,$textdebug)
    FileClose($filehandle)
    $debug = $debug  & $textdebug & @CRLF
    _GUICtrlEdit_SetText($window,$debug)
    _GUICtrlEdit_LineScroll($window, 0, _GUICtrlEdit_GetLineCount($window))
return $debug
EndFunc

global $debug
;###################################
_createdebug()
$remote = "jamesh-8"
$obj = ObjCreate("MSScriptControl.ScriptControl")
$obj.language = "VBScript"
$code = 'Set Session = CreateObject("Microsoft.Update.Session","' & $remote & '")'
$obj.AddCode($code)
$obj.Run

$updateSession =  $obj.codeobject.session
$updateSearcher = $updateSession.CreateupdateSearcher

 _updatedebug($window,"Searching for updates..." & @CRLF)
 $searchResult = $updateSearcher.Search("IsInstalled=0 and Type='Software'")

  _updatedebug($window,"List of applicable items on the machine:")
For $I = 0 To $searchResult.Updates.Count - 1
    $update = $searchResult.Updates.Item($I)
     _updatedebug($window,$I + 1 & "> " & $update.Title & @CR)
Next

If $searchResult.Updates.Count = 0 Then
     _updatedebug($window,"There are no applicable updates.")
EndIf

_updatedebug($window,@CRLF & "Creating collection of updates to download:")

$obj1 = ObjCreate("MSScriptControl.ScriptControl")

$obj1.language = "VBScript"

$code1 = 'Set Session = CreateObject("Microsoft.update.UpdateColl","' & $remote & '")'

$obj1.AddCode($code1)

$obj1.Run

$updatesToDownload = $obj1.codeobject.session

For $I = 0 To $searchResult.Updates.Count - 1
    $update = $searchResult.Updates.Item($I)
     _updatedebug($window,$I + 1 & "> adding: " & $update.Title & @CR)
    $updatesToDownload.Add($update)
Next

 _updatedebug($window,@CRLF & "Downloading updates...")
 $downloader = $updateSession.CreateUpdateDownloader
$downloader.Updates = $updatesToDownload
$downloader.Download

 _updatedebug($window,@CRLF & "List of downloaded updates:")
For $I = 0 To $searchResult.Updates.Count - 1
    $update = $searchResult.Updates.Item($I)
    If $update.IsDownloaded Then
         _updatedebug($window,$I + 1 & "> " & $update.Title & @CR)
    EndIf
Next



$obj2 = ObjCreate("MSScriptControl.ScriptControl")

$obj2.language = "VBScript"

$code2 = 'Set Session = CreateObject("Microsoft.update.UpdateColl","' & $remote & '")'

$obj2.AddCode($code2)

$obj2.Run

$updatesToInstall = $obj2.codeobject.session

 _updatedebug($window,@CRLF & "Creating collection of downloaded updates to install:")
For $I = 0 To $searchResult.Updates.Count - 1
    $update = $searchResult.Updates.Item($I)
    If $update.IsDownloaded = True Then
         _updatedebug($window,$I + 1 & "> adding: " & $update.Title & @CR)
        $updatesToInstall.Add($update)
    EndIf
Next


 _updatedebug($window,@CRLF & "Installing updates...")
$installer = $updateSession.CreateUpdateInstaller()
$installer.Updates = $updatesToInstall
If $updatesToInstall.Count > 0 Then
    $installationResult = $installer.Install()
   ;Output results of install
     _updatedebug($window,"Installation Result: " & $installationResult.ResultCode)
     _updatedebug($window,"Listing of updates installed " & "and individual installation results:")
    For $I = 0 To $updatesToInstall.Count - 1
         _updatedebug($window,$I + 1 & "> " & $updatesToInstall.Item($I).Title & ": " & $installationResult.GetUpdateResult($I).ResultCode & @CR)
    Next
     _updatedebug($window,"PC will reboot in 30 seconds")
     sleep(30000)
    ;Shutdown(2)
Else
     _updatedebug($window,@CRLF & "Nothing to install" & @CRLF)
EndIf






  While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop

        EndSwitch
    WEnd
    GUIDelete()
Edited by leighlandwhitehead

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Can you post here only the VBScript code ?

edit: unless something not yet understand.

Edited by mLipok

Signature beginning:   Wondering who uses AutoIT and what it can be used for ?
* GHAPI UDF - modest begining - comunication with GitHub REST API *
ADO.au3 UDF     POP3.au3 UDF     XML.au3 UDF    How to use IE.au3  UDF with  AutoIt v3.3.14.x  for other useful stuff click the following button

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST API *

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 - BETA * ADO.au3 UDF SMTP Mailer UDF *

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Best coding practices * 

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * 

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2017-06-04

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Can you post here only the VBScript code ?

edit: unless something not yet understand.

 

Hi mLipok , please see the below the vb script that i have used to create the autoit one but changed as needed , thanks  :

Set updateSession = CreateObject("Microsoft.Update.Session")
updateSession.ClientApplicationID = "MSDN Sample Script"

Set updateSearcher = updateSession.CreateUpdateSearcher()

WScript.Echo "Searching for updates..." & vbCRLF

Set searchResult = _
updateSearcher.Search("IsInstalled=0 and Type='Software' and IsHidden=0")

WScript.Echo "List of applicable items on the machine:"

For I = 0 To searchResult.Updates.Count-1
    Set update = searchResult.Updates.Item(I)
    WScript.Echo I + 1 & "> " & update.Title
Next

If searchResult.Updates.Count = 0 Then
    WScript.Echo "There are no applicable updates."
    WScript.Quit
End If

WScript.Echo vbCRLF & "Creating collection of updates to download:"

Set updatesToDownload = CreateObject("Microsoft.Update.UpdateColl")

For I = 0 to searchResult.Updates.Count-1
    Set update = searchResult.Updates.Item(I)
    addThisUpdate = false
    If update.InstallationBehavior.CanRequestUserInput = true Then
        WScript.Echo I + 1 & "> skipping: " & update.Title & _
        " because it requires user input"
    Else
        If update.EulaAccepted = false Then
            WScript.Echo I + 1 & "> note: " & update.Title & _
            " has a license agreement that must be accepted:"
            WScript.Echo update.EulaText
            WScript.Echo "Do you accept this license agreement? (Y/N)"
            strInput = WScript.StdIn.Readline
            WScript.Echo 
            If (strInput = "Y" or strInput = "y") Then
                update.AcceptEula()
                addThisUpdate = true
            Else
                WScript.Echo I + 1 & "> skipping: " & update.Title & _
                " because the license agreement was declined"
            End If
        Else
            addThisUpdate = true
        End If
    End If
    If addThisUpdate = true Then
        WScript.Echo I + 1 & "> adding: " & update.Title 
        updatesToDownload.Add(update)
    End If
Next

If updatesToDownload.Count = 0 Then
    WScript.Echo "All applicable updates were skipped."
    WScript.Quit
End If
    
WScript.Echo vbCRLF & "Downloading updates..."

Set downloader = updateSession.CreateUpdateDownloader() 
downloader.Updates = updatesToDownload
downloader.Download()

Set updatesToInstall = CreateObject("Microsoft.Update.UpdateColl")

rebootMayBeRequired = false

WScript.Echo vbCRLF & "Successfully downloaded updates:"

For I = 0 To searchResult.Updates.Count-1
    set update = searchResult.Updates.Item(I)
    If update.IsDownloaded = true Then
        WScript.Echo I + 1 & "> " & update.Title 
        updatesToInstall.Add(update) 
        If update.InstallationBehavior.RebootBehavior > 0 Then
            rebootMayBeRequired = true
        End If
    End If
Next

If updatesToInstall.Count = 0 Then
    WScript.Echo "No updates were successfully downloaded."
    WScript.Quit
End If

If rebootMayBeRequired = true Then
    WScript.Echo vbCRLF & "These updates may require a reboot."
End If

WScript.Echo  vbCRLF & "Would you like to install updates now? (Y/N)"
strInput = WScript.StdIn.Readline
WScript.Echo 

If (strInput = "Y" or strInput = "y") Then
    WScript.Echo "Installing updates..."
    Set installer = updateSession.CreateUpdateInstaller()
    installer.Updates = updatesToInstall
    Set installationResult = installer.Install()
 
    'Output results of install
    WScript.Echo "Installation Result: " & _
    installationResult.ResultCode 
    WScript.Echo "Reboot Required: " & _ 
    installationResult.RebootRequired & vbCRLF 
    WScript.Echo "Listing of updates installed " & _
    "and individual installation results:" 
 
    For I = 0 to updatesToInstall.Count - 1
        WScript.Echo I + 1 & "> " & _
        updatesToInstall.Item(i).Title & _
        ": " & installationResult.GetUpdateResult(i).ResultCode   
    Next
End If
Edited by leighlandwhitehead

Share this post


Link to post
Share on other sites

hello

I have been playing with existing script to try and get windows updates to reliable install on Windows 7, 8 and 8.1. I am also getting object errors. It seems to work on some and not on others. I was just wondering if you were able to get your script working properly.

 

Thanks

Brad

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

This is slightly off topic, and you'll probably end up figuring it out!

However, I ended up giving up on this approach and going with an Offline Update Server either over a Network Share or Flashdrive.

http://download.wsusoffline.net/

This basically gives you an Offline Windows Update Client that you can select the OS to create offline updates for... Once the offline Updates have been compiled, I simply update the database every Wednesday, since official updates are pushed on Tuesday. This app also has a sub-program that detects the installed OS, checks to see if updates exist in the database for the installed OS, and then, depending on the options selected, will install all updates that the machine doesn't have, rebooting as needed during the process.

I truly don't mean to discourage you and I'm sorry if my posts comes off as distracting or side-stepping the answer. I've just invested a lot of time into perfecting a mechanism to bring a Windows machine completely up-to-date, as fast as possible. And have found this solution, to be the best, in my humble opinion. ^_^

As a side-note, I am not affiliated with that project in any possible way, other than arguing with the developer over using a randomly generated password for the creation of the "WSUSUpdate" account that is created to install updates and then removed when completed.

As an awesome side-note, that I almost forgot, that Offline Update Server/Client is built with AutoIt, so it's possible you might learn something from taking apart the source, which is provided!

Good luck!

P.S. Here is a direct link to the app. http://download.wsusoffline.net/wsusoffline96.zip
 

Edited by BinaryBrother
My posts keep getting "corrupted" with the strike-through style...

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Thank you for the reply. We have been using the offline updater at our shop for probably 6 years. It does work way better than chewing up all of your internet bandwidth. But I find that you need to run it many times to get all of the updates installed properly and it doesn't like to reboot and reconnect properly when run from a network share. I did actually get a similar script running to the above one (as far as I can tell). It was something so stupid that I was struggling with, it needs #RequireAdmin.

We have decided to go down the road of a WSUS server that we redirect to on every machine from our computer cleaning / setup software. Then the updater script just hammers away at the updates until done. Once complete it changes back to the Windows update server and completes again. We just started testing, so we will see how it goes. Might end up going back to the offline updater.

 

thanks

Brad

Edited by byarotsky
1 person likes this

Share this post


Link to post
Share on other sites

Glad to see you got it resolved!

More information involving that Offline Update Server, if needed.

I'm not sure why you need to run it multiple times, unless you're not using the "Update and Recall" feature, which keeps pushing the update client through the updates until it has installed all of the ones stored in the offline database. It works, beautifully, through multiple reboots, but I did need to do a couple things to the Windows Share to get everything working smoothly!

You must disable "Password Protected Sharing" in your Vista+ OS. Which is a bit of a lie, considering that password protected shares still work fine!

2015-05-29_1715.png

Then, you'll want to go to the share that needs "Guest" read-only access, like the "Client" folder of the Offline Update Server and use "Advanced Sharing" to share the folder as something like "Windows 7 X64 - WSUS". You'll need to add "Guests"  to the share with Read rights and then go to the "Security" tab and add "Guests" with read rights to the folder, as well. That last part is required to make the Guest Shares on Vista+ work properly with the Offline Update Server, without a password.

I have learned from personal experience, that it's a horrible idea to give Write Privs to the Offline Update server from a client that is updating. Corruption was a regular issue, as well as virus propagation from infected machines. And yes, a virus did actually infect my Offline Update server from a customer's machine, once, and didn't notice it until I had infected another machine. It was one of those viruses that replicates an infected EXE with the same name as directories, hides extensions, and gives the EXEs folder icons! So I thought I had ran into a folder that would not open, then noticed the duplicate, and then noticed it was an EXE... lol

Anywho, the point is, if you set the Share permissions properly, it will successfully update from a fresh & untouched OS Install, to completely up-to-date, without having to mess with it more than once, outside having to click "Ok" and unchecking "Always ask for this file." during the next reboot.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now