Winget-Upgrade.ps1
param( [Parameter(Mandatory = $False)] [ValidateRange(0, 99)] [int32] $MaxLogFiles = 3, [Parameter(Mandatory = $False)] [int64] $MaxLogSize = 1048576, [Parameter(Mandatory = $True)] [Alias('List')] [String] $ListPath, [Parameter(Mandatory = $True)] [Switch] $UseWhiteList = $True, [Parameter(Mandatory=$False)][string[]] $apps=@() ) $UPConfig = @{ WAU_MaxLogFiles = $MaxLogFiles WAU_MaxLogSize = $MaxLogSize DisplayVersion = "0.0.1" WAU_ListPath = $ListPath WAU_UseWhiteList = $UseWhiteList WAU_included_apps = $apps } <# LOAD FUNCTIONS #> #Get the Working Dir $Script:WorkingDir = $PSScriptRoot #Function to configure the prefered scope option as Machine function Add-ScopeMachine($SettingsPath) { if (Test-Path $SettingsPath) { $ConfigFile = Get-Content -Path $SettingsPath | Where-Object { $_ -notmatch '//' } | ConvertFrom-Json } if (!$ConfigFile) { $ConfigFile = @{ } } if ($ConfigFile.installBehavior.preferences.scope) { $ConfigFile.installBehavior.preferences.scope = "Machine" } else { $Scope = New-Object PSObject -Property $( @{ scope = "Machine" } ) $Preference = New-Object PSObject -Property $( @{ preferences = $Scope } ) Add-Member -InputObject $ConfigFile -MemberType NoteProperty -Name 'installBehavior' -Value $Preference -Force } $ConfigFile | ConvertTo-Json | Out-File $SettingsPath -Encoding utf8 -Force } # Initialisation function Start-Init { #Config console output encoding [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 $caller = Get-ChildItem $MyInvocation.PSCommandPath | Select-Object -Expand Name if ($caller -eq "Winget-Upgrade.ps1") { #Log Header $Log = "`n##################################################`n# CHECK FOR APP UPDATES - $( Get-Date -Format (Get-culture).DateTimeFormat.ShortDatePattern )`n##################################################" $Log | Write-host #Logs initialisation $Script:LogFile = "$WorkingDir\logs\updates.log" } if (!(Test-Path $LogFile)) { #Create file if doesn't exist New-Item -ItemType File -Path $LogFile -Force | Out-Null #Set ACL for users on logfile $NewAcl = Get-Acl -Path $LogFile $identity = New-Object System.Security.Principal.SecurityIdentifier S-1-5-11 $fileSystemRights = "Modify" $type = "Allow" $fileSystemAccessRuleArgumentList = $identity, $fileSystemRights, $type $fileSystemAccessRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $fileSystemAccessRuleArgumentList $NewAcl.SetAccessRule($fileSystemAccessRule) Set-Acl -Path $LogFile -AclObject $NewAcl } #Check if Intune Management Extension Logs folder and WAU-updates.log exists, make symlink if ((Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs") -and !(Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log")) { Write-host "`nCreating SymLink for log file in Intune Management Extension log folder" -ForegroundColor Yellow New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -ItemType SymbolicLink -Value $LogFile -Force -ErrorAction SilentlyContinue | Out-Null } if ($caller -eq "Winget-Upgrade.ps1") { #Log file $Log | out-file -filepath $LogFile -Append } } #Function to update an App function Update-App($app) { #Get App Info $ReleaseNoteURL = Get-AppInfo $app.Id if ($ReleaseNoteURL) { $Button1Text = $NotifLocale.local.outputs.output[10].message } #Send available update notification Write-ToLog "Updating $( $app.Name ) from $( $app.Version ) to $( $app.AvailableVersion )..." "Cyan" #Winget upgrade Write-ToLog "########## WINGET UPGRADE PROCESS STARTS FOR APPLICATION ID '$( $App.Id )' ##########" "Gray" #If PreInstall script exist if ($ModsPreInstall) { Write-ToLog "Modifications for $( $app.Id ) before upgrade are being applied..." "Yellow" & "$ModsPreInstall" } #Run Winget Upgrade command if ($ModsOverride) { Write-ToLog "-> Running (overriding default): Winget upgrade --id $( $app.Id ) --accept-package-agreements --accept-source-agreements --override $ModsOverride" & $Winget upgrade --id $( $app.Id ) --accept-package-agreements --accept-source-agreements --override $ModsOverride | Tee-Object -file $LogFile -Append } else { Write-ToLog "-> Running: Winget upgrade --id $( $app.Id ) --accept-package-agreements --accept-source-agreements -h" & $Winget upgrade --id $( $app.Id ) --accept-package-agreements --accept-source-agreements -h | Tee-Object -file $LogFile -Append } if ($ModsUpgrade) { Write-ToLog "Modifications for $( $app.Id ) during upgrade are being applied..." "Yellow" & "$ModsUpgrade" } #Check if application updated properly $CheckOutdated = Get-WingetOutdatedApps $FailedToUpgrade = $false foreach ($CheckApp in $CheckOutdated) { if ($( $CheckApp.Id ) -eq $( $app.Id )) { #Upgrade failed! #Test for a Pending Reboot (Component Based Servicing/WindowsUpdate/CCM_ClientUtilities) $PendingReboot = Test-PendingReboot if ($PendingReboot -eq $true) { Write-ToLog "-> A Pending Reboot lingers and probably prohibited $( $app.Name ) from upgrading...`n-> ...an install for $( $app.Name ) is NOT executed!" "Red" $FailedToUpgrade = $true break } #If app failed to upgrade, run Install command Write-ToLog "-> An upgrade for $( $app.Name ) failed, now trying an install instead..." "Yellow" if (($ModsOverride) -or ($CheckApp.Id -eq "Git.Git")) { Write-ToLog "-> Running (overriding default): Winget install --id $( $app.Id ) --accept-package-agreements --accept-source-agreements --override $ModsOverride" & $Winget install --id $( $app.Id ) --accept-package-agreements --accept-source-agreements --override '/SILENT /COMPONENTS="icons,ext\reg\shellhere,assoc,assoc_sh' | Tee-Object -file $LogFile -Append } else { Write-ToLog "-> Running: Winget install --id $( $app.Id ) --accept-package-agreements --accept-source-agreements -h" & $Winget install --id $( $app.Id ) --accept-package-agreements --accept-source-agreements -h | Tee-Object -file $LogFile -Append } if ($ModsInstall) { Write-ToLog "Modifications for $( $app.Id ) during install are being applied..." "Yellow" & "$ModsInstall" } #Check if application installed properly $CheckOutdated2 = Get-WingetOutdatedApps foreach ($CheckApp2 in $CheckOutdated2) { if ($( $CheckApp2.Id ) -eq $( $app.Id )) { $FailedToUpgrade = $true } } } } if ($FailedToUpgrade -eq $false) { if ($ModsInstalled) { Write-ToLog "Modifications for $( $app.Id ) after upgrade/install are being applied..." "Yellow" & "$ModsInstalled" } } Write-ToLog "########## WINGET UPGRADE PROCESS FINISHED FOR APPLICATION ID '$( $App.Id )' ##########" "Gray" #Notify installation if ($FailedToUpgrade -eq $false) { #Send success updated app notification Write-ToLog "$( $app.Name ) updated to $( $app.AvailableVersion ) !" "Green" $Script:InstallOK += 1 } else { #Send failed updated app notification Write-ToLog "$( $app.Name ) update failed." "Red" } } #Get the winget App Information function Get-AppInfo($AppID) { #Get AppID Info $String = & $winget show $AppID --accept-source-agreements -s winget | Out-String #Search for Release Note info $ReleaseNote = [regex]::match($String, "(?<=Release Notes Url: )(.*)(?=\n)").Groups[0].Value #Return Release Note return $ReleaseNote } |