Need help automating Windows Update

Started by tjthorson, July 16, 2021, 08:14:26 PM

Previous topic - Next topic

tjthorson

Faithful user of WinBatch since 1996 here.  And to be honest I have never gotten the hang of the Control Manager Extender.  And Ive tried - really....  I just dont get it....  Not even sure I can use it here.   I have usually gotten away with send keys and mouse clicks over the years.  Im trying to help someone that has 4000 Win10 machines so old their SUS server wont update them.  And their environment is so locked down I am very limited in what i can do - i cant even elevate privilege, run powershell, etc.  What I have had limited success is sending keystrokes to the Windows update screen - note - they cant just click the button to check for updates - they have to choose the option link below it to "Check online for updates from Microsoft Update".  So, my code snippet is below.  The problem is it is not reliable.  If for some reason the machine was already updating, the keystrokes will "pause" the updates, or restart the machine.  What Im asking - is it possible to 1) control this dialog to "click" the link to check Microsoft update?  2) Is it possible to wait/look for a "restart" button if it exists in that window and then click it?  Im hoping someone already has some code that can do this they are willing to share.  Thanks in advance!

Run("cmd.exe", "/c control.exe /name Microsoft.WindowsUpdate")     ; 4 tabs to do the update from microsoft option.....
   WinWaitExist("Settings", 30)
   delay(5)
   SendKeysTo("Settings", "{tab}")
   Delay(.1)
   SendKeysTo("Settings", "{tab}")
   Delay(.1)
   SendKeysTo("Settings", "{tab}")
   Delay(.1)
   SendKeysTo("Settings", "{tab}")
   Delay(.1)
   SendKeysTo("Settings", "~")
   Delay(.1)
   WinClose("Settings")

stanl

Not sure about Sendkeys, and it's a bummer you have such Powershell limits. Might not be much help, but there is a COM object Microsoft.Update.Session that might be usable.  The link below has vbscript code but that is easily converted to WB:


https://docs.microsoft.com/en-us/previous-versions/windows/desktop/aa387102(v=vs.85)

tjthorson

Thanks for replying - unfortunately the link doesnt work.  :( 

stanl

Sorry about the link. Forgot that I had already posted a script with that COM Object in 2019:  I placed it below, but can be tweaked as needed:
Code (WINBATCH) Select


;Winbatch 2019B - Windows Update Helper - no error handler
;code not complete, just a starting point for COM Objects
;Stan Littlefield, December 28,2019
;========================================================================================
updateSession = CreateObject("Microsoft.Update.Session")
updateSearcher = updateSession.CreateUpdateSearcher()
updatestoInstall = CreateObject("Microsoft.Update.UpdateColl")
BoxOpen("Update Session Objects","Initiating")
upds = updateSearcher.Search("IsInstalled=1").Updates
;upds = updateSearcher.Search("IsInstalled=1 and Type='Software'").Updates


For i = 0 To upds.Count-1
    upd= upds.Item(i)
    BoxTitle("Enumerating Installed Updates")
    Boxtext("Update ":i+1:" ":upd.Title) ; or save to file or shown in grid
    TimeDelay(1)
Next
Boxtext("")
BoxTitle("Enumerating Updates Not Installed")
;====== this section to be tested ======================================
;create a similar collection for not installed
;upds = updateSearcher.Search("IsInstalled=0 and Type='Software'").Updates
upds = updateSearcher.Search("IsInstalled=0").Updates
If upds.Count==0
   BoxText("No Updates pending install"0
Else
   BoxText("Preparing Downloads")
   For i = 0 To upds.Count-1
      upd= upds.Item(i)
      Boxtext("Update ":i+1:" ":upd.Title)
      Timedelay(1)
      ;uncomment next line and next 3 commented lines to test.
      ;updatestoInstall.Add(upd)
   Next
;  downloader= updateSession.CreateUpdateDownloader()
;  downloader.Updates = updatestoInstall
;  downloader.Download()
Endif


updateSession=0
updateSearcher=0
updatestoInstall=0
Exit

tjthorson

OK thanks.  I had found that code and tried it.  I have been searching for weeks before posting as a last resort....  I don't like to be "that" guy...  :)   So - on those machines in question, it runs without error, but they show zero updates, presumably because its doing a "regular" check for updates - meaning their broken WSUS server is serving up nothing.....

I need to somehow click on the "check with Microsoft" link in that dialog (or the corresponding behind the scenes call) and then wait for the restart button to appear and click that.  I their security is blocking most anything behind the scenes (set up by people that no longer work there, so no one knows anything about it).

I appreciate the effort.


ChuckC

Given the limitations running a program elevated in that environment, I'm not certain that this will work, but it would be worth attempting, perhaps with a one-off installation of Windows where you can do so.

Specifically, I'm referring to using the Microsoft SysInternals suite of utilities, which has a program in it called ProcMon.exe [Process Monitor].  With ProcMon, you can spy on every single API function call that is generated by any process that matches a given set of selection criteria.  What you would expect to find out is some additional details about either the API function(s) calls that are made to initiate the update when you click on that link, or what process is created, along with the program's full path and the command line parameters that are passed to it.  Once you have that information, you can then formulate a strategy for duplicating the initiation of the update process with a WinBatch script.


stanl

Quote from: tjthorson on July 17, 2021, 12:47:27 PM
So - on those machines in question, it runs without error, but they show zero updates,


As was mentioned, that code had the lines to perform the update(s) commented, so no updates would be expected. Also, should have mentioned [based on the article I adapted it from]


The sample can download updates only by using WUA. It cannot download updates from a Software Update Services (SUS) 1.0 server.


[Edit]:
And not to get too far off-topic. I did read you could execute the COM object to download/install updates on a remote machine with Powershell by either calling via Psexec or creating a Powershell Local Virtual Account which gives unrestricted access.

td

Quote from: tjthorson on July 17, 2021, 12:47:27 PM
OK thanks.  I had found that code and tried it.  I have been searching for weeks before posting as a last resort....  I don't like to be "that" guy...  :)   So - on those machines in question, it runs without error, but they show zero updates, presumably because its doing a "regular" check for updates - meaning their broken WSUS server is serving up nothing.....

I need to somehow click on the "check with Microsoft" link in that dialog (or the corresponding behind the scenes call) and then wait for the restart button to appear and click that.  I their security is blocking most anything behind the scenes (set up by people that no longer work there, so no one knows anything about it).

I appreciate the effort.

Automating the UI is the most unreliable way to automate anything on newer versions of Windows so you need to get off that horse to improve your chances of success. Also, note Stan's comment about the script he posted and give that solution more consideration.

Strickly personal opinion, but based on your description of your computer environment, you may want to consider either figure out how your user accounts and computers are set up or hire some who can. Working in the dark can lead to all manner of unintended and undesirable outcomes.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

Quote from: td on July 18, 2021, 09:27:24 AM
Also, note Stan's comment about the script he posted and give that solution more consideration.


Below is modified script, the initial part of iterating installed, unless for historical reasons, pretty useless. However uncomment the second part and added lines to perform install.  Tested on my laptop and had another friend test on his... and it appears to work. His only comment was having some kind of message that install was in process, since the script ran for over an hour. So, this would run with WUA on an individual machine... but how to port to the 4k workstations you mentioned.... 4k EXE's??? or perhaps note that


updateSession = CreateObject("Microsoft.Update.Session",[remote PC])  can accept an additional parameter, but I think that is were the denied access error will occur so need a workaround.
Code (WINBATCH) Select


;Winbatch 2019B - Windows Update Helper - no error handler
;code not complete, just a starting point for COM Objects
;Stan Littlefield, December 28,2019
;========================================================================================
updateSession = CreateObject("Microsoft.Update.Session")
updateSearcher = updateSession.CreateUpdateSearcher()
updatestoInstall = CreateObject("Microsoft.Update.UpdateColl")
BoxOpen("Update Session Objects","Initiating")
upds = updateSearcher.Search("IsInstalled=1").Updates
;upds = updateSearcher.Search("IsInstalled=1 and Type='Software'").Updates


;isinstalled = ""
For i = 0 To upds.Count-1
    upd= upds.Item(i)
    BoxTitle("Enumerating Installed Updates")
    Boxtext("Update ":i+1:" ":upd.Title) ; or save to file or shown in grid
    ;TimeDelay(1)
Next
Boxtext("")
BoxTitle("Enumerating Updates Not Installed")
;====== this section to be tested ======================================
;create a similar collection for not installed
;upds = updateSearcher.Search("IsInstalled=0 and Type='Software'").Updates
upds = updateSearcher.Search("IsInstalled=0").Updates
If upds.Count==0
   BoxText("No Updates pending install"0
Else
   BoxText("Preparing Downloads")
   For i = 0 To upds.Count-1
      upd= upds.Item(i)
      Boxtext("Update ":i+1:" ":upd.Title)
      Timedelay(1)
      ;uncomment next line and next 3 commented lines to test.
      updatestoInstall.Add(upd)
   Next
  downloader= updateSession.CreateUpdateDownloader()
  downloader.Updates = updatestoInstall
  downloader.Download()
  installer = updateSession.CreateUpdateInstaller()
  installer.Updates = updatestoInstall
  installer.Install()
Endif


updateSession=0
updateSearcher=0
updatestoInstall=0
Exit

tjthorson

Thanks all.  I understand the challenges here.  Understand - I could easily figure out how to "fix" the environment so I could do this the "right" way.  Im not allowed to at this point, and the there is a whole host of legal reasons I cannot get those groups to make any of the required changes, and truthfully they aren't "allowed" to make any changes right now.  I have to work in the box Im put into, at least for now on this one.

td

My point was not so much a question of changing anything as it was a question of understanding how your systems are configured. That understanding makes it easier for you to solve problems and ask for better advice when you can't solve them yourself.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

and I have to throw in a hiccup.... the friend who tested my script [I compiled as EXE] said that although his 2016 Office updates installed, he had a Win10 update that required a re-boot so some other updates were paused. Also, he questioned a script when he had his auto-update registry key set....   :o :o ....  but, it was a slow weekend and I had fun searching about updates...

td

I am of the opinion that MSFT doesn't do a particularly good job of implementing updates because of the "reboot needed update paused" strangeness and several other issues. It's just another one of the many Windows 10 quirks and bugs.  One solution ?might? be to script a reboot before relaunching a script to install updates.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

Quote from: td on July 19, 2021, 10:24:22 AM
I am of the opinion that MSFT doesn't do a particularly good job of implementing updates because of the "reboot needed update paused" strangeness and several other issues. It's just another one of the many Windows 10 quirks and bugs.  One solution ?might? be to script a reboot before relaunching a script to install updates.


That is really interesting... in my script [modified] you can determine reboot
Code (WINBATCH) Select


For i = 0 To upds.Count-1
      upd= upds.Item(i)
      If upd.InstallationBehavior.RebootBehavior > 0
         Boxtext("Update ":i+1:" ":upd.Title:@LF:"Reboot May Be Required")
         Timedelay(5)
      Else
         Boxtext("Update ":i+1:" ":upd.Title)
      Endif
      updatestoInstall.Add(upd)
   Next



so, reboot after initial install if this is triggered?

td

Quote from: stanl on July 19, 2021, 01:25:42 PM
so, reboot after initial install if this is triggered?

Don't see why not. The trick would be to restart the script if more updates are available after the reboot. There are several ways to do that but it may require admin permissions of one kind or another. 
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade