Skip to content

New feat: Retry logic & exit with winget Exitcode#895

Closed
FaserF wants to merge 18 commits intoRomanitho:developfrom
FaserF:add-retryLogic-Exitcode
Closed

New feat: Retry logic & exit with winget Exitcode#895
FaserF wants to merge 18 commits intoRomanitho:developfrom
FaserF:add-retryLogic-Exitcode

Conversation

@FaserF
Copy link
Copy Markdown
Contributor

@FaserF FaserF commented Mar 21, 2025

Proposed Changes

Sometimes a installation in our company environment fails due to "another installation is already in progress".
This PR adds a simple retry logic, where an installation will be tried three times per default. This can be disabled with the param -DisableRetry.
Also Winget-Install now exits the script not always with 0 (success), instead the winget installation return code will be used to exit this script. This helps with handling Error Codes through SCCM & Intune.

Related Issues

(Github link to related issues or pull requests)

@github-actions github-actions bot added the invalid-branch Invalid branch label Mar 21, 2025
@FaserF FaserF changed the base branch from main to develop March 21, 2025 10:49
@github-actions github-actions bot removed the invalid-branch Invalid branch label Mar 21, 2025
@FaserF FaserF requested a review from KnifMelti March 25, 2025 16:02
@KnifMelti
Copy link
Copy Markdown
Contributor

Install OK (haven't tested what happens if failed):
19:07:13 - -> Installing Azul.Zulu.11.JRE (Attempt: 0)...
|
|
Successfully installed
19:07:20 - -> Azul.Zulu.11.JRE successfully installed. <-- One line too many...
19:07:21 - -> Azul.Zulu.11.JRE successfully installed. <--
19:07:21 - Azul.Zulu.11.JRE processing finished!

Uninstall with $Appargs OK, but when uninstalling with or without $Appargs this comes in the terminal:

Write-Host : Cannot bind parameter 'ForegroundColor'. Cannot convert value "C:\Program
Files\WindowsApps\Microsoft.DesktopAppInstaller_1.25.340.0_x64__8wekyb3d8bbwe\winget.exe\ uninstall --id
Azul.Zulu.11.JRE -e --accept-source-agreements -h --all-versions" to type "System.ConsoleColor". Error: "Unable to
match the identifier name C:\Program
Files\WindowsApps\Microsoft.DesktopAppInstaller_1.25.340.0_x64__8wekyb3d8bbwe\winget.exe\ uninstall --id
Azul.Zulu.11.JRE -e --accept-source-agreements -h --all-versions to a valid enumerator name. Specify one of the
following enumerator names and try again:
Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red,
Magenta, Yellow, White"
At C:\Program Files\Winget-AutoUpdate\functions\Write-ToLog.ps1:39 char:40
+     $Log | Write-host -ForegroundColor $LogColor
+                                        ~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Write-Host], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WriteHostCommand

19:07:44 - Start Azul.Zulu.11.JRE processing...
19:07:45 - -> Uninstalling Azul.Zulu.11.JRE (Attempt: 0)...
19:07:45 - -> Running:
███████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ 1024 KB / 3.76 MB
███████████████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ 2.00 MB / 3.76 MB
███████████████████████▒▒▒▒▒▒▒ 3.00 MB / 3.76 MB
██████████████████████████████ 3.76 MB / 3.76 MB
Found Azul Zulu JRE 11.78.15 (11.0.26), 64-bit [Azul.Zulu.11.JRE]
Starting package uninstall...
Successfully uninstalled
19:07:49 - -> Azul.Zulu.11.JRE successfully uninstalled.
19:07:49 - Azul.Zulu.11.JRE processing finished!

@FaserF
Copy link
Copy Markdown
Contributor Author

FaserF commented Mar 26, 2025

Test with fail (just open a termin without admin rights, try to install a program that needs admin rights and cancel the admin prompt:

PS C:\Users\fseitz\GitHub\Winget-AutoUpdate\Sources\Winget-AutoUpdate> .\Winget-Install.ps1 -AppIDs "Notepad++.Notepad++"
#################################################################
#    26.03.2025 - NEW INSTALL REQUEST
#################################################################
07:52:38 - Running without admin rights.


07:52:38 - Start Notepad++.Notepad++ processing...
07:52:39 - -> Notepad++.Notepad++ exists on Winget Repository.
07:52:42 - -> Installing Notepad++.Notepad++ (Attempt: 0)...
07:52:42 - -> Running: "C:\Users\fseitz\AppData\Local\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe" install --id Notepad++.Notepad++ -e --accept-package-agreements --accept-source-agreements -s winget -h


Gefunden Notepad++ [Notepad++.Notepad++] Version 8.7.8
Diese Anwendung wird von ihrem Besitzer an Sie lizenziert.
Microsoft ist nicht verantwortlich und erteilt keine Lizenzen für Pakete von Drittanbietern.
Der Installer-Hash wurde erfolgreich überprüft
Paketinstallation wird gestartet...
Das Installationsprogramm fordert die Ausführung als Administrator an. Es wird eine Eingabeaufforderung erwartet.

Unerwarteter Fehler beim Ausführen des Befehls:
0x800704c7 : Der Vorgang wurde durch den Benutzer abgebrochen.
07:52:46 - -> Notepad++.Notepad++ installation failed with Exit Code: -2147023673. Retrying... (Retry 1 of 2)
07:52:51 - -> Installing Notepad++.Notepad++ (Attempt: 1)...
07:52:51 - -> Running: "C:\Users\fseitz\AppData\Local\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe" install --id Notepad++.Notepad++ -e --accept-package-agreements --accept-source-agreements -s winget -h


Gefunden Notepad++ [Notepad++.Notepad++] Version 8.7.8
Diese Anwendung wird von ihrem Besitzer an Sie lizenziert.
Microsoft ist nicht verantwortlich und erteilt keine Lizenzen für Pakete von Drittanbietern.
Der Installer-Hash wurde erfolgreich überprüft
Paketinstallation wird gestartet...
Das Installationsprogramm fordert die Ausführung als Administrator an. Es wird eine Eingabeaufforderung erwartet.

Unerwarteter Fehler beim Ausführen des Befehls:
0x800704c7 : Der Vorgang wurde durch den Benutzer abgebrochen.
07:52:55 - -> Installing Notepad++.Notepad++ (Attempt: 2)...
07:52:55 - -> Running: "C:\Users\fseitz\AppData\Local\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe" install --id Notepad++.Notepad++ -e --accept-package-agreements --accept-source-agreements -s winget -h


Gefunden Notepad++ [Notepad++.Notepad++] Version 8.7.8
Diese Anwendung wird von ihrem Besitzer an Sie lizenziert.
Microsoft ist nicht verantwortlich und erteilt keine Lizenzen für Pakete von Drittanbietern.
Der Installer-Hash wurde erfolgreich überprüft
Paketinstallation wird gestartet...
Das Installationsprogramm fordert die Ausführung als Administrator an. Es wird eine Eingabeaufforderung erwartet.

Unerwarteter Fehler beim Ausführen des Befehls:
0x800704c7 : Der Vorgang wurde durch den Benutzer abgebrochen.
07:53:01 - -> Notepad++.Notepad++ installation failed with Exit Code: -2147023673 after 3 attempts!
07:53:01 - Notepad++.Notepad++ processing finished!

07:53:02 - ###   END REQUEST   ###

With the -DisableRetry Param:

PS C:\Users\fseitz\GitHub\Winget-AutoUpdate\Sources\Winget-AutoUpdate> .\Winget-Install.ps1 -AppIDs "Notepad++.Notepad++" -DisableRetry
#################################################################
#    26.03.2025 - NEW INSTALL REQUEST
#################################################################
07:54:36 - Running without admin rights.


07:54:36 - Start Notepad++.Notepad++ processing...
07:54:37 - -> Notepad++.Notepad++ exists on Winget Repository.
07:54:39 - -> Installing Notepad++.Notepad++ (Attempt: 0)...
07:54:39 - -> Running: "C:\Users\fseitz\AppData\Local\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe" install --id Notepad++.Notepad++ -e --accept-package-agreements --accept-source-agreements -s winget -h


Gefunden Notepad++ [Notepad++.Notepad++] Version 8.7.8
Diese Anwendung wird von ihrem Besitzer an Sie lizenziert.
Microsoft ist nicht verantwortlich und erteilt keine Lizenzen für Pakete von Drittanbietern.
Der Installer-Hash wurde erfolgreich überprüft
Paketinstallation wird gestartet...
Das Installationsprogramm fordert die Ausführung als Administrator an. Es wird eine Eingabeaufforderung erwartet.

Unerwarteter Fehler beim Ausführen des Befehls:
0x800704c7 : Der Vorgang wurde durch den Benutzer abgebrochen.
07:54:44 - -> Notepad++.Notepad++ installation failed with Exit Code: -2147023673 after 1 attempts!
07:54:44 - Notepad++.Notepad++ processing finished!

07:54:45 - ###   END REQUEST   ###

Uninstall:

PS C:\Users\fseitz\GitHub\Winget-AutoUpdate\Sources\Winget-AutoUpdate> .\Winget-Install.ps1 -AppIDs "Adobe.Acrobat.Reader.64-bit" -Uninstall
#################################################################
#    26.03.2025 - NEW UNINSTALL REQUEST
#################################################################
07:58:35 - Running without admin rights.


07:58:35 - Start Adobe.Acrobat.Reader.64-bit processing...
07:58:37 - -> Uninstalling Adobe.Acrobat.Reader.64-bit (Attempt: 0)...
07:58:37 - -> Running: \


Gefunden Adobe Acrobat (64-bit) [Adobe.Acrobat.Reader.64-bit]
Paket-Deinstallation wird gestartet...

Deinstallation fehlgeschlagen mit Exitcode: 1603
07:59:24 - -> Adobe.Acrobat.Reader.64-bit uninstallation failed with Exit Code: -1978335184. Retrying... (Retry 1 of 2)
07:59:29 - -> Uninstalling Adobe.Acrobat.Reader.64-bit (Attempt: 1)...
07:59:29 - -> Running: \


Gefunden Adobe Acrobat (64-bit) [Adobe.Acrobat.Reader.64-bit]
Paket-Deinstallation wird gestartet...

Deinstallation fehlgeschlagen mit Exitcode: 1603
08:00:16 - -> Adobe.Acrobat.Reader.64-bit uninstallation failed with Exit Code: -1978335184. Retrying... (Retry 2 of 2)
08:00:21 - -> Uninstalling Adobe.Acrobat.Reader.64-bit (Attempt: 2)...
08:00:21 - -> Running: \


Gefunden Adobe Acrobat (64-bit) [Adobe.Acrobat.Reader.64-bit]
Paket-Deinstallation wird gestartet...

Deinstallation fehlgeschlagen mit Exitcode: 1603
08:01:06 - -> Adobe.Acrobat.Reader.64-bit uninstallation failed with Exit Code: -1978335184. Retrying... (Retry 3 of 2)
08:01:13 - -> Adobe.Acrobat.Reader.64-bit uninstallation failed after 3 attempts!
08:01:13 - Adobe.Acrobat.Reader.64-bit processing finished!

08:01:14 - ###   END REQUEST   ###

With -DisableRetry Param:

PS C:\Users\fseitz\GitHub\Winget-AutoUpdate\Sources\Winget-AutoUpdate> .\Winget-Install.ps1 -AppIDs "Adobe.Acrobat.Reader.64-bit" -Uninstall -DisableRetry
#################################################################
#    26.03.2025 - NEW UNINSTALL REQUEST
#################################################################
08:01:55 - Running without admin rights.


08:01:55 - Start Adobe.Acrobat.Reader.64-bit processing...
08:01:57 - -> Uninstalling Adobe.Acrobat.Reader.64-bit (Attempt: 0)...
08:01:57 - -> Running: \


Gefunden Adobe Acrobat (64-bit) [Adobe.Acrobat.Reader.64-bit]
Paket-Deinstallation wird gestartet...

Deinstallation fehlgeschlagen mit Exitcode: 1603
08:02:41 - -> Adobe.Acrobat.Reader.64-bit uninstallation failed with Exit Code: -1978335184. Retrying... (Retry 1 of 0)
08:02:47 - -> Adobe.Acrobat.Reader.64-bit uninstallation failed after 1 attempts!
08:02:47 - Adobe.Acrobat.Reader.64-bit processing finished!

08:02:48 - ###   END REQUEST   ###

@FaserF
Copy link
Copy Markdown
Contributor Author

FaserF commented Mar 26, 2025

Uninstall with $Appargs OK, but when uninstalling with or without $Appargs this comes in the terminal:

Write-Host : Cannot bind parameter 'ForegroundColor'. Cannot convert value "C:\Program
Files\WindowsApps\Microsoft.DesktopAppInstaller_1.25.340.0_x64__8wekyb3d8bbwe\winget.exe\ uninstall --id
Azul.Zulu.11.JRE -e --accept-source-agreements -h --all-versions" to type "System.ConsoleColor". Error: "Unable to
match the identifier name C:\Program
Files\WindowsApps\Microsoft.DesktopAppInstaller_1.25.340.0_x64__8wekyb3d8bbwe\winget.exe\ uninstall --id
Azul.Zulu.11.JRE -e --accept-source-agreements -h --all-versions to a valid enumerator name. Specify one of the
following enumerator names and try again:
Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red,
Magenta, Yellow, White"
At C:\Program Files\Winget-AutoUpdate\functions\Write-ToLog.ps1:39 char:40
+     $Log | Write-host -ForegroundColor $LogColor
+                                        ~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Write-Host], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WriteHostCommand

I have now fixed it in the latest commit, I dont get it where it gets called with a wrong color param, but we now always use white as a fallback.

@KnifMelti
Copy link
Copy Markdown
Contributor

KnifMelti commented Mar 29, 2025

Confirmed behavior with another MSI installation ongoing:

Starting package install...
Another installation is already in progress. Try again later.
Installer failed with exit code: 1618
Installer log is available at: C:\Windows\TEMP\WinGet\defaultState\WinGet-Azul.Zulu.11.JRE.11.78.15-2025-03-29-15-53-32.309.log
15:53:35 - -> Azul.Zulu.11.JRE installation failed with Exit Code: -1978334974. Retrying... (Retry 1 of 2)
15:53:40 - -> Running: "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_1.25.340.0_x64__8wekyb3d8bbwe\winget.exe" install --id Azul.Zulu.11.JRE -e --accept-package-agreements --accept-source-agreements -s winget -h 

Uninstall:

Starting package uninstall...
Uninstall failed with exit code: 1618
15:55:46 - -> Azul.Zulu.11.JRE uninstallation failed with Exit Code: -1978335184. Retrying... (Retry 1 of 2)
15:55:51 - -> Running: "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_1.25.340.0_x64__8wekyb3d8bbwe\winget.exe" uninstall --id Azul.Zulu.11.JRE -e --accept-source-agreements -h 

After that Retry 1 was enough (the other installation was completed) to complete the install/uninstall

@KnifMelti
Copy link
Copy Markdown
Contributor

Confirmed behavior

But I notice that the exit codes from the winget run is not the actual exit code from in this case the MSI installation (1618) making your test for 3010, 1641, etc impossible to catch.

@KnifMelti
Copy link
Copy Markdown
Contributor

KnifMelti commented Mar 30, 2025

@KnifMelti
Copy link
Copy Markdown
Contributor

KnifMelti commented Mar 30, 2025

EDIT: only 1 Function now with helper functions inside:
Read-WinGetErrorByDecimal.txt

But, you can translate them

I got an idea. Feel free to incorporate it if you think it's a good one (think I got the most right).
1 new functions:

  • Read-WinGetErrorByDecimal.ps1

Include it as the other ones and call Read-WinGetErrorByDecimal with the actual error code from WinGet like:

$errorResult = Read-WinGetErrorByDecimal -DecimalNumber "-1978334967"
Write-ToLog "$errorResult" "Green"

Or do your translate.
I'm guessing 3010 is -1978334967 in WinGet land: APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_FINISH
And 1641 would be -1978334965 in the same land: APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_INITIATED

Read-WinGetErrorByDecimal runs Get-WinGetReturnCodes if $WAUInstallLocation\config\WinGetReturnCodes.json doesn't exist.

I've included the parsing for General Errors and Install errors from https://raw.githubusercontent.com/microsoft/winget-cli/master/doc/windows/package-manager/winget/returnCodes.md

@KnifMelti
Copy link
Copy Markdown
Contributor

  • Read-WinGetErrorByDecimal.ps1

Last one 😉
In it, better to define the path to the downloaded file as:

# Specify the path to the JSON file
$jsonPath = "$env:TEMP\WinGetReturnCodes.json"

Then it can run for SYSTEM/user without more tinkering.

$Log | Write-host -ForegroundColor $LogColor
if ($LogColor -notin @("Black", "DarkBlue", "DarkGreen", "DarkCyan", "DarkRed", "DarkMagenta", "DarkYellow", "Gray", "DarkGray", "Blue", "Green", "Cyan", "Red", "Magenta", "Yellow", "White")) {
$LogColor = "White"
}
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for me colors don't make sense anymore for logs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have only added this, since some logging commands failed due to missing or wrong color parameters. For this feature here its not specifilcy needed, but I would leave it in there to reduce potential errors

@FaserF
Copy link
Copy Markdown
Contributor Author

FaserF commented Apr 10, 2025

EDIT: only 1 Function now with helper functions inside:
Read-WinGetErrorByDecimal.txt

But, you can translate them

I got an idea. Feel free to incorporate it if you think it's a good one (think I got the most right).
1 new functions:

  • Read-WinGetErrorByDecimal.ps1

Thanks for finding that, really good. I will try to do some more research if we maybe can directly access the installer return code (not the winget return code). If there is no way, your idea looks good.

@KnifMelti
Copy link
Copy Markdown
Contributor

KnifMelti commented Apr 10, 2025

your idea looks good

Nah, don't bother with that extra function!
Everything is already presented in the WinGet output.
You translating WinGet return codes is all that's needed.

@FaserF
Copy link
Copy Markdown
Contributor Author

FaserF commented Apr 11, 2025

What do you @KnifMelti & @Romanitho think about this:
#908

When we add support for that with WAU, it would be easy to retrieve the installer return code: microsoft/winget-cli#5375

@Romanitho
Copy link
Copy Markdown
Owner

From my point of view, we need to make a choice: either we stick with Winget and keep using our PowerShell wrapper, or we move to the official module — but that would require PowerShell 7 as a prerequisite on all devices. Maintaining both approaches could overload the project, which is already somewhat messy and definitely needs a cleanup to reorganize things, streamline the whole process, and so on.
That said, using the Winget PowerShell module does seem like the direction things are heading — it might become the standard eventually.

@ITistheworst
Copy link
Copy Markdown

It may also be worth looking at the approaches taken in the PSADTv4 WinGet Module to see what the solutions are there.

@AndrewDemski-ad-gmail-com
Copy link
Copy Markdown
Contributor

It may also be worth looking at the approaches taken in the PSADTv4 WinGet Module to see what the solutions are there.

Close but no cigar @KnifMelti.

PSAppDeployToolkit.WinGet is not performing any ForEach loops, PDT and its winget derivative are focused on carrying out a single installation after all.
That way any single reboot required flag will not touch/affect/break anything else and decision always belongs to invoking process/tool.

That project includes full return codes table from winget repo:
in-code list of errors:
https://github.com/mjr4077au/PSAppDeployToolkit.WinGet/blob/master/src/PSAppDeployToolkit.WinGet/ImportsFirst.ps1#L127

    enum ADTWinGetExitCode
    {
        INTERNAL_ERROR = -1978335231
# (...) etc.. etc..
    }

Installation can pass the exit code to parent process:
Install-ADTWinGetPackage.ps1

        $wingetResult = $null
        try
        {
            try
            {
                # Perform the required operation.
                $wingetResult = Invoke-ADTWinGetDeploymentOperation -Action Install @PSBoundParameters
            }
            catch
            {
                # Re-writing the ErrorRecord with Write-Error ensures the correct PositionMessage is used.
                Write-Error -ErrorRecord $_
            }

            # Throw if the result has an ErrorRecord.
            if ($wingetResult.ExtendedErrorCode)
            {
                Write-Error -ErrorRecord $wingetResult.ExtendedErrorCode
            }
        }
        catch
        {
            # Process the caught error, log it and throw depending on the specified ErrorAction.
            Invoke-ADTFunctionErrorHandler -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState -ErrorRecord $_ -LogMessage "Failed to install the specified WinGet package."
        }

        # If we have a result and are passing through, return it.
        if ($wingetResult -and $PassThru)
        {
            return $wingetResult
        }

If something goes wrong, then the results are processed using Invoke-ADTFunctionErrorHandler from PDT
https://github.com/PSAppDeployToolkit/PSAppDeployToolkit/blob/main/docs/Invoke-ADTFunctionErrorHandler.mdx

@KnifMelti KnifMelti mentioned this pull request Apr 24, 2025
@FaserF FaserF closed this Aug 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants