5

We have some Win7 Machines that don't use the shutdown Button but a custom Tool that checks for online PCs and shuts down the NAS if it is the last one online. Everything works fine but I use the command Process.Start("shutdown", "/s /t 0"); to shutdown the pc and it seems that this ignores pending updates. This results in the PC automatically shutting down some day while doing important stuff without saving.

Question how can the command be modified to do updates and shutdown instead of just shutting down. The cmd command would be enough, I can translate that into C# with no problem.

Sorry if this was asked multiple times but I need to be absolutely sure that my changes work...

8
wuauclt /detectnow /updatenow && shutdown /s /t 0

Shuts down only when update is over.

  • I just did this, and updates weren't installed (I had 14 waiting, Windows 7) – Canadian Luke Mar 25 '15 at 17:00
  • Worked for me with Windows 7. Doesn't work with Process.Start() under Win8 but I just start a *.bat cmd file. – CodingYourLife Jun 25 '15 at 21:29
  • Tested against Windows 7, Windows 8.1, and Windows 10. wuauclt.exe triggers updates to start installing, but the command immediately returns and then shutdown is executed. Unfortunately Microsoft doesn't "hang" the return of wuauclt until the update process is done. – Aaron C. de Bruyn Apr 16 '20 at 3:24
  • Likewise - doesn't wait when I do this. Perhaps if updates are already detected and being installed, it returns immediately? – almcnicoll May 2 '20 at 22:57
0

I ran into a similar issue, and did some research. I found a script from MSDN, and modified it on my blog to automatically install updates.

You could run it with the cscript command, available in every version of Windows since at least Windows XP, and put that command in your C# code to call this script. Posted below, save as a .VBS script:

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
            strInput = "Y"
            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
strInput = "Y"
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

Not the answer you're looking for? Browse other questions tagged or ask your own question.