diff --git a/Winget-AutoUpdate-Install.ps1 b/Winget-AutoUpdate-Install.ps1 index cbdfd8e..3dc9661 100644 --- a/Winget-AutoUpdate-Install.ps1 +++ b/Winget-AutoUpdate-Install.ps1 @@ -11,7 +11,7 @@ https://github.com/Romanitho/Winget-AutoUpdate Install Winget-AutoUpdate and prerequisites silently .PARAMETER WingetUpdatePath -Specify Winget-AutoUpdate installation localtion. Default: C:\ProgramData\winget-update\ +Specify Winget-AutoUpdate installation localtion. Default: C:\ProgramData\Winget-AutoUpdate\ .PARAMETER DoNotUpdate Do not run Winget-autoupdate after installation. By default, Winget-AutoUpdate is run just after installation. @@ -23,7 +23,7 @@ Do not run Winget-autoupdate after installation. By default, Winget-AutoUpdate i [CmdletBinding()] param( [Parameter(Mandatory=$False)] [Alias('S')] [Switch] $Silent = $false, - [Parameter(Mandatory=$False)] [Alias('Path')] [String] $WingetUpdatePath = "$env:ProgramData\winget-update", + [Parameter(Mandatory=$False)] [Alias('Path')] [String] $WingetUpdatePath = "$env:ProgramData\Winget-AutoUpdate", [Parameter(Mandatory=$False)] [Switch] $DoNotUpdate = $false ) @@ -78,11 +78,19 @@ function Check-Prerequisites{ function Install-WingetAutoUpdate{ try{ + #Check if previous version location exists and delete + $OldWingetUpdatePath = $WingetUpdatePath.Replace("\Winget-AutoUpdate","\winget-update") + if (Test-Path ($OldWingetUpdatePath)){ + Remove-Item $OldWingetUpdatePath -Force -Recurse + } + Get-ScheduledTask -TaskName "Winget Update" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False + Get-ScheduledTask -TaskName "Winget Update Notify" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False + #Copy files to location if (!(Test-Path $WingetUpdatePath)){ New-Item -ItemType Directory -Force -Path $WingetUpdatePath } - Copy-Item -Path "$PSScriptRoot\winget-update\*" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue + Copy-Item -Path "$PSScriptRoot\Winget-AutoUpdate\*" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue Copy-Item -Path "$PSScriptRoot\excluded_apps.txt" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue # Set dummy regkeys for notification name and icon @@ -98,7 +106,7 @@ function Install-WingetAutoUpdate{ # Set up the task, and register it $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings -Trigger $taskTrigger2,$taskTrigger1 - Register-ScheduledTask -TaskName 'Winget Update' -InputObject $task -Force + Register-ScheduledTask -TaskName 'Winget-AutoUpdate' -InputObject $task -Force # Settings for the scheduled task for Notifications $taskAction = New-ScheduledTaskAction –Execute "wscript.exe" -Argument "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\winget-notify.ps1`"`"" @@ -107,7 +115,7 @@ function Install-WingetAutoUpdate{ # Set up the task, and register it $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings - Register-ScheduledTask -TaskName 'Winget Update Notify' -InputObject $task -Force + Register-ScheduledTask -TaskName 'Winget-AutoUpdate-Notify' -InputObject $task -Force Write-host "`nInstallation succeeded!" -ForegroundColor Green Start-sleep 1 @@ -138,7 +146,7 @@ function Start-WingetAutoUpdate{ if ($RunWinget -eq "y"){ try{ Write-host "Running Winget-AutoUpdate..." -ForegroundColor Yellow - Get-ScheduledTask -TaskName "Winget Update" -ErrorAction SilentlyContinue | Start-ScheduledTask -ErrorAction SilentlyContinue + Get-ScheduledTask -TaskName "Winget-AutoUpdate" -ErrorAction SilentlyContinue | Start-ScheduledTask -ErrorAction SilentlyContinue } catch{ Write-host "Failed to run Winget-AutoUpdate..." -ForegroundColor Red @@ -165,4 +173,4 @@ Check-Prerequisites Install-WingetAutoUpdate Write-host "End of process." -Start-Sleep 3 +Start-Sleep 3 \ No newline at end of file diff --git a/winget-update/Invisible.vbs b/Winget-AutoUpdate/Invisible.vbs similarity index 100% rename from winget-update/Invisible.vbs rename to Winget-AutoUpdate/Invisible.vbs diff --git a/winget-update/icons/error.png b/Winget-AutoUpdate/icons/error.png similarity index 100% rename from winget-update/icons/error.png rename to Winget-AutoUpdate/icons/error.png diff --git a/winget-update/icons/info.png b/Winget-AutoUpdate/icons/info.png similarity index 100% rename from winget-update/icons/info.png rename to Winget-AutoUpdate/icons/info.png diff --git a/winget-update/icons/success.png b/Winget-AutoUpdate/icons/success.png similarity index 100% rename from winget-update/icons/success.png rename to Winget-AutoUpdate/icons/success.png diff --git a/winget-update/icons/warning.png b/Winget-AutoUpdate/icons/warning.png similarity index 100% rename from winget-update/icons/warning.png rename to Winget-AutoUpdate/icons/warning.png diff --git a/winget-update/locale/en-US.xml b/Winget-AutoUpdate/locale/en-US.xml similarity index 100% rename from winget-update/locale/en-US.xml rename to Winget-AutoUpdate/locale/en-US.xml diff --git a/winget-update/locale/fr-FR.xml b/Winget-AutoUpdate/locale/fr-FR.xml similarity index 96% rename from winget-update/locale/fr-FR.xml rename to Winget-AutoUpdate/locale/fr-FR.xml index 3f7c1a1..783c3f6 100644 --- a/winget-update/locale/fr-FR.xml +++ b/Winget-AutoUpdate/locale/fr-FR.xml @@ -1,34 +1,34 @@ - - - - - Vérifiez votre connexion réseau - - Impossible de vérifier les mises à jours logicielles pour le moment ! - - - - Aucune connexion réseau - - Les mises à jour logicielles n'ont pas pu être vérifiées ! - - - - {0} va être mis à jour ! - - {0} vers {1} - - - - {0} a été mis à jour. - - Version installée : {0} - - - - {0} n'a pas pu être mis à jour ! - - Contacter le support. - - - + + + + + Vérifiez votre connexion réseau + + Impossible de vérifier les mises à jours logicielles pour le moment ! + + + + Aucune connexion réseau + + Les mises à jour logicielles n'ont pas pu être vérifiées ! + + + + {0} va être mis à jour ! + + {0} vers {1} + + + + {0} a été mis à jour. + + Version installée : {0} + + + + {0} n'a pas pu être mis à jour ! + + Contacter le support. + + + diff --git a/winget-update/winget-notify.ps1 b/Winget-AutoUpdate/winget-notify.ps1 similarity index 80% rename from winget-update/winget-notify.ps1 rename to Winget-AutoUpdate/winget-notify.ps1 index 331c561..7e6c517 100644 --- a/winget-update/winget-notify.ps1 +++ b/Winget-AutoUpdate/winget-notify.ps1 @@ -1,21 +1,21 @@ -#Send Notif Script - -#get xml notif config -[xml]$NotifConf = Get-Content "$env:ProgramData\winget-update\notif.xml" -Encoding UTF8 -ErrorAction SilentlyContinue -if (!($NotifConf)) {break} - -#Load Assemblies -[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null -[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null - -#Prepare XML -$ToastXml = [Windows.Data.Xml.Dom.XmlDocument]::New() -$ToastXml.LoadXml($NotifConf.OuterXml) - -#Specify Launcher App ID -$LauncherID = "Windows.SystemToast.Winget.Notification" - -#Prepare and Create Toast -$ToastMessage = [Windows.UI.Notifications.ToastNotification]::New($ToastXML) -$ToastMessage.Tag = $NotifConf.toast.tag +#Send Notif Script + +#get xml notif config +[xml]$NotifConf = Get-Content "$env:ProgramData\Winget-AutoUpdate\notif.xml" -Encoding UTF8 -ErrorAction SilentlyContinue +if (!($NotifConf)) {break} + +#Load Assemblies +[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null +[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null + +#Prepare XML +$ToastXml = [Windows.Data.Xml.Dom.XmlDocument]::New() +$ToastXml.LoadXml($NotifConf.OuterXml) + +#Specify Launcher App ID +$LauncherID = "Windows.SystemToast.Winget.Notification" + +#Prepare and Create Toast +$ToastMessage = [Windows.UI.Notifications.ToastNotification]::New($ToastXML) +$ToastMessage.Tag = $NotifConf.toast.tag [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($LauncherID).Show($ToastMessage) \ No newline at end of file diff --git a/winget-update/winget-upgrade.ps1 b/Winget-AutoUpdate/winget-upgrade.ps1 similarity index 96% rename from winget-update/winget-upgrade.ps1 rename to Winget-AutoUpdate/winget-upgrade.ps1 index 7378e37..5cd8205 100644 --- a/winget-update/winget-upgrade.ps1 +++ b/Winget-AutoUpdate/winget-upgrade.ps1 @@ -1,304 +1,304 @@ -<# FUNCTIONS #> - -function Init { - #Var - $Script:WorkingDir = $PSScriptRoot - - #Logs initialisation - $LogPath = "$WorkingDir\logs" - if (!(Test-Path $LogPath)){ - New-Item -ItemType Directory -Force -Path $LogPath - } - - #Log file - $Script:LogFile = "$LogPath\updates.log" - - #Log Header - $Log = "##################################################`n# CHECK FOR APP UPDATES - $(Get-Date -Format 'dd/MM/yyyy')`n##################################################" - $Log | Write-host - $Log | out-file -filepath $LogFile -Append - - #Get locale file for Notification - #Default en-US - $DefaultLocale = "$WorkingDir\locale\en-US.xml" - #Get OS locale - $Locale = Get-WinSystemLocale - #Test if OS locale config file exists - $LocaleFile = "$WorkingDir\locale\$($locale.Name).xml" - if(Test-Path $LocaleFile){ - [xml]$Script:NotifLocale = Get-Content $LocaleFile -Encoding UTF8 -ErrorAction SilentlyContinue - $LocaleNotif = "Notification Langugage : $($locale.Name)" - } - else{ - [xml]$Script:NotifLocale = Get-Content $DefaultLocale -Encoding UTF8 -ErrorAction SilentlyContinue - $LocaleNotif = "Notification Langugage : en-US" - } - Write-Log $LocaleNotif "Cyan" -} - -function Write-Log ($LogMsg,$LogColor = "White") { - #Get log - $Log = "$(Get-Date -UFormat "%T") - $LogMsg" - #Echo log - $Log | Write-host -ForegroundColor $LogColor - #Write log to file - $Log | out-file -filepath $LogFile -Append -} - -function Start-NotifTask ($Title,$Message,$MessageType,$Balise) { - - #Add XML variables -[xml]$ToastTemplate = @" - - - - $Title - $Message - - - - $Balise - -"@ - - #Save XML File - $ToastTemplateLocation = "$env:ProgramData\winget-update\" - if (!(Test-Path $ToastTemplateLocation)){ - New-Item -ItemType Directory -Force -Path $ToastTemplateLocation - } - $ToastTemplate.Save("$ToastTemplateLocation\notif.xml") - - #Send Notification to user. First, check if script is run as admin (or system) - $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) - if ($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)){ - #Run Notify scheduled task to notify conneted users - Get-ScheduledTask -TaskName "Winget Update Notify" -ErrorAction SilentlyContinue | Start-ScheduledTask -ErrorAction SilentlyContinue - } - #else, run as user - else{ - Start-Process powershell.exe -ArgumentList "-ExecutionPolicy Bypass -File `"$WorkingDir\winget-notify.ps1`"" -NoNewWindow -Wait - } - - #Wait for notification to display - Start-Sleep 3 -} - -function Test-Network { - #init - $timeout = 0 - $ping = $false - - #test connectivity during 30 min then timeout - Write-Log "Checking internet connection..." "Yellow" - while (!$ping -and $timeout -lt 1800){ - try{ - Invoke-RestMethod -Uri "https://api.github.com/zen" - Write-Log "Connected !" "Green" - $ping = $true - return $ping - } - catch{ - Start-Sleep 10 - $timeout += 10 - Write-Log "Checking internet connection. $($timeout)s." "Yellow" - #Send Notif if no connection for 5 min - if ($timeout -eq 300){ - Write-Log "Notify 'No connection'" "Yellow" - $Title = $NotifLocale.local.outputs.output[0].title - $Message = $NotifLocale.local.outputs.output[0].message - $MessageType = "warning" - $Balise = "connection" - Start-NotifTask $Title $Message $MessageType $Balise - } - } - } - Write-Log "Timeout. No internet connection !" "Red" - #Send Notif if no connection for 30 min - $Title = $NotifLocale.local.outputs.output[1].title - $Message = $NotifLocale.local.outputs.output[1].message - $MessageType = "error" - $Balise = "connection" - Start-NotifTask $Title $Message $MessageType $Balise - return $ping -} - -function Get-WingetOutdated { - class Software { - [string]$Name - [string]$Id - [string]$Version - [string]$AvailableVersion - } - - #Get WinGet Location - $WingetCmd = Get-Command winget.exe -ErrorAction SilentlyContinue - if ($WingetCmd){ - $script:upgradecmd = $WingetCmd.Source - } - elseif (Test-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\AppInstallerCLI.exe"){ - #WinGet < 1.17 - $script:upgradecmd = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\AppInstallerCLI.exe" | Select-Object -ExpandProperty Path - } - elseif (Test-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe"){ - #WinGet > 1.17 - $script:upgradecmd = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe" | Select-Object -ExpandProperty Path - } - else{ - Write-Log "Winget not installed !" - return - } - - #Run winget to list apps and accept source agrements (necessary on first run) - & $upgradecmd list --accept-source-agreements | Out-Null - - #Get list of available upgrades on winget format - $upgradeResult = & $upgradecmd upgrade | Out-String - - #Start Convertion of winget format to an array. Check if "-----" exists - if (!($upgradeResult -match "-----")){ - return - } - - #Split winget output to lines - $lines = $upgradeResult.Split([Environment]::NewLine).Replace("¦ ","") - - # Find the line that starts with "------" - $fl = 0 - while (-not $lines[$fl].StartsWith("-----")){ - $fl++ - } - - #Get header line - $fl = $fl - 2 - - #Get header titles - $index = $lines[$fl] -split '\s+' - - # Line $i has the header, we can find char where we find ID and Version - $idStart = $lines[$fl].IndexOf($index[1]) - $versionStart = $lines[$fl].IndexOf($index[2]) - $availableStart = $lines[$fl].IndexOf($index[3]) - $sourceStart = $lines[$fl].IndexOf($index[4]) - - # Now cycle in real package and split accordingly - $upgradeList = @() - For ($i = $fl + 2; $i -le $lines.Length; $i++){ - $line = $lines[$i] - if ($line.Length -gt ($sourceStart+5) -and -not $line.StartsWith('-')){ - $software = [Software]::new() - $software.Name = $line.Substring(0, $idStart).TrimEnd() - $software.Id = $line.Substring($idStart, $versionStart - $idStart).TrimEnd() - $software.Version = $line.Substring($versionStart, $availableStart - $versionStart).TrimEnd() - $software.AvailableVersion = $line.Substring($availableStart, $sourceStart - $availableStart).TrimEnd() - #check if Avalaible Version is > than Current Version (block "unknow" versions loop) - if ([version]$software.AvailableVersion -gt [version]$software.Version){ - $upgradeList += $software - } - } - } - - return $upgradeList -} - -function Get-ExcludedApps{ - if (Test-Path "$WorkingDir\excluded_apps.txt"){ - return Get-Content -Path "$WorkingDir\excluded_apps.txt" - } -} - - -<# MAIN #> - -#Run initialisation -Init - -#Check network connectivity -if (Test-Network){ - - #Get exclude apps list - $toSkip = Get-ExcludedApps - - #Get outdated Winget packages - Write-Log "Checking available updates..." "yellow" - $outdated = Get-WingetOutdated - - #Log list of app to update - foreach ($app in $outdated){ - #List available updates - $Log = "Available update : $($app.Name). Current version : $($app.Version). Available version : $($app.AvailableVersion)." - $Log | Write-host - $Log | out-file -filepath $LogFile -Append - } - - #Count good update installs - $InstallOK = 0 - - #For each app, notify and update - foreach ($app in $outdated){ - - if (-not ($toSkip -contains $app.Id)){ - - #Send available update notification - Write-Log "Updating $($app.Name) from $($app.Version) to $($app.AvailableVersion)..." "Cyan" - $Title = $NotifLocale.local.outputs.output[2].title -f $($app.Name) - $Message = $NotifLocale.local.outputs.output[2].message -f $($app.Version), $($app.AvailableVersion) - $MessageType = "info" - $Balise = $($app.Name) - Start-NotifTask $Title $Message $MessageType $Balise - - #Winget upgrade - Write-Log "------ Winget - $($app.Name) Upgrade Starts ------" "Gray" - & $upgradecmd upgrade --id $($app.Id) --all --accept-package-agreements --accept-source-agreements -h - Write-Log "----- Winget - $($app.Name) Upgrade Finished -----" "Gray" - - #Check installed version - $checkoutdated = Get-WingetOutdated - $FailedToUpgrade = $false - foreach ($checkapp in $checkoutdated){ - if ($($checkapp.Id) -eq $($app.Id)) { - $FailedToUpgrade = $true - } - } - - #Notify installation - if ($FailedToUpgrade -eq $false){ - #Send success updated app notification - Write-Log "$($app.Name) updated to $($app.AvailableVersion) !" "Green" - - #Send Notif - $Title = $NotifLocale.local.outputs.output[3].title -f $($app.Name) - $Message = $NotifLocale.local.outputs.output[3].message -f $($app.AvailableVersion) - $MessageType = "success" - $Balise = $($app.Name) - Start-NotifTask $Title $Message $MessageType $Balise - - $InstallOK += 1 - } - else { - #Send failed updated app notification - Write-Log "$($app.Name) update failed." "Red" - - #Send Notif - $Title = $NotifLocale.local.outputs.output[4].title -f $($app.Name) - $Message = $NotifLocale.local.outputs.output[4].message - $MessageType = "error" - $Balise = $($app.Name) - Start-NotifTask $Title $Message $MessageType $Balise - } - } - else{ - Write-Log "$($app.Name) : Skipped upgrade because it is in the excluded app list" "Gray" - } - } - - if ($InstallOK -gt 0){ - Write-Log "$InstallOK apps updated ! No more update." "Green" - } - if ($InstallOK -eq 0){ - Write-Log "No new update." "Green" - } -} - -#End -Write-Log "End of process!" "Cyan" -Sleep 3 +<# FUNCTIONS #> + +function Init { + #Var + $Script:WorkingDir = $PSScriptRoot + + #Logs initialisation + $LogPath = "$WorkingDir\logs" + if (!(Test-Path $LogPath)){ + New-Item -ItemType Directory -Force -Path $LogPath + } + + #Log file + $Script:LogFile = "$LogPath\updates.log" + + #Log Header + $Log = "##################################################`n# CHECK FOR APP UPDATES - $(Get-Date -Format 'dd/MM/yyyy')`n##################################################" + $Log | Write-host + $Log | out-file -filepath $LogFile -Append + + #Get locale file for Notification + #Default en-US + $DefaultLocale = "$WorkingDir\locale\en-US.xml" + #Get OS locale + $Locale = Get-WinSystemLocale + #Test if OS locale config file exists + $LocaleFile = "$WorkingDir\locale\$($locale.Name).xml" + if(Test-Path $LocaleFile){ + [xml]$Script:NotifLocale = Get-Content $LocaleFile -Encoding UTF8 -ErrorAction SilentlyContinue + $LocaleNotif = "Notification Langugage : $($locale.Name)" + } + else{ + [xml]$Script:NotifLocale = Get-Content $DefaultLocale -Encoding UTF8 -ErrorAction SilentlyContinue + $LocaleNotif = "Notification Langugage : en-US" + } + Write-Log $LocaleNotif "Cyan" +} + +function Write-Log ($LogMsg,$LogColor = "White") { + #Get log + $Log = "$(Get-Date -UFormat "%T") - $LogMsg" + #Echo log + $Log | Write-host -ForegroundColor $LogColor + #Write log to file + $Log | out-file -filepath $LogFile -Append +} + +function Start-NotifTask ($Title,$Message,$MessageType,$Balise) { + + #Add XML variables +[xml]$ToastTemplate = @" + + + + $Title + $Message + + + + $Balise + +"@ + + #Save XML File + $ToastTemplateLocation = "$env:ProgramData\Winget-AutoUpdate\" + if (!(Test-Path $ToastTemplateLocation)){ + New-Item -ItemType Directory -Force -Path $ToastTemplateLocation + } + $ToastTemplate.Save("$ToastTemplateLocation\notif.xml") + + #Send Notification to user. First, check if script is run as admin (or system) + $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) + if ($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)){ + #Run Notify scheduled task to notify conneted users + Get-ScheduledTask -TaskName "Winget Update Notify" -ErrorAction SilentlyContinue | Start-ScheduledTask -ErrorAction SilentlyContinue + } + #else, run as user + else{ + Start-Process powershell.exe -ArgumentList "-ExecutionPolicy Bypass -File `"$WorkingDir\winget-notify.ps1`"" -NoNewWindow -Wait + } + + #Wait for notification to display + Start-Sleep 3 +} + +function Test-Network { + #init + $timeout = 0 + $ping = $false + + #test connectivity during 30 min then timeout + Write-Log "Checking internet connection..." "Yellow" + while (!$ping -and $timeout -lt 1800){ + try{ + Invoke-RestMethod -Uri "https://api.github.com/zen" + Write-Log "Connected !" "Green" + $ping = $true + return $ping + } + catch{ + Start-Sleep 10 + $timeout += 10 + Write-Log "Checking internet connection. $($timeout)s." "Yellow" + #Send Notif if no connection for 5 min + if ($timeout -eq 300){ + Write-Log "Notify 'No connection'" "Yellow" + $Title = $NotifLocale.local.outputs.output[0].title + $Message = $NotifLocale.local.outputs.output[0].message + $MessageType = "warning" + $Balise = "connection" + Start-NotifTask $Title $Message $MessageType $Balise + } + } + } + Write-Log "Timeout. No internet connection !" "Red" + #Send Notif if no connection for 30 min + $Title = $NotifLocale.local.outputs.output[1].title + $Message = $NotifLocale.local.outputs.output[1].message + $MessageType = "error" + $Balise = "connection" + Start-NotifTask $Title $Message $MessageType $Balise + return $ping +} + +function Get-WingetOutdated { + class Software { + [string]$Name + [string]$Id + [string]$Version + [string]$AvailableVersion + } + + #Get WinGet Location + $WingetCmd = Get-Command winget.exe -ErrorAction SilentlyContinue + if ($WingetCmd){ + $script:upgradecmd = $WingetCmd.Source + } + elseif (Test-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\AppInstallerCLI.exe"){ + #WinGet < 1.17 + $script:upgradecmd = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\AppInstallerCLI.exe" | Select-Object -ExpandProperty Path + } + elseif (Test-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe"){ + #WinGet > 1.17 + $script:upgradecmd = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe" | Select-Object -ExpandProperty Path + } + else{ + Write-Log "Winget not installed !" + return + } + + #Run winget to list apps and accept source agrements (necessary on first run) + & $upgradecmd list --accept-source-agreements | Out-Null + + #Get list of available upgrades on winget format + $upgradeResult = & $upgradecmd upgrade | Out-String + + #Start Convertion of winget format to an array. Check if "-----" exists + if (!($upgradeResult -match "-----")){ + return + } + + #Split winget output to lines + $lines = $upgradeResult.Split([Environment]::NewLine).Replace("¦ ","") + + # Find the line that starts with "------" + $fl = 0 + while (-not $lines[$fl].StartsWith("-----")){ + $fl++ + } + + #Get header line + $fl = $fl - 2 + + #Get header titles + $index = $lines[$fl] -split '\s+' + + # Line $i has the header, we can find char where we find ID and Version + $idStart = $lines[$fl].IndexOf($index[1]) + $versionStart = $lines[$fl].IndexOf($index[2]) + $availableStart = $lines[$fl].IndexOf($index[3]) + $sourceStart = $lines[$fl].IndexOf($index[4]) + + # Now cycle in real package and split accordingly + $upgradeList = @() + For ($i = $fl + 2; $i -le $lines.Length; $i++){ + $line = $lines[$i] + if ($line.Length -gt ($sourceStart+5) -and -not $line.StartsWith('-')){ + $software = [Software]::new() + $software.Name = $line.Substring(0, $idStart).TrimEnd() + $software.Id = $line.Substring($idStart, $versionStart - $idStart).TrimEnd() + $software.Version = $line.Substring($versionStart, $availableStart - $versionStart).TrimEnd() + $software.AvailableVersion = $line.Substring($availableStart, $sourceStart - $availableStart).TrimEnd() + #check if Avalaible Version is > than Current Version (block "unknow" versions loop) + if ([version]$software.AvailableVersion -gt [version]$software.Version){ + $upgradeList += $software + } + } + } + + return $upgradeList +} + +function Get-ExcludedApps{ + if (Test-Path "$WorkingDir\excluded_apps.txt"){ + return Get-Content -Path "$WorkingDir\excluded_apps.txt" + } +} + + +<# MAIN #> + +#Run initialisation +Init + +#Check network connectivity +if (Test-Network){ + + #Get exclude apps list + $toSkip = Get-ExcludedApps + + #Get outdated Winget packages + Write-Log "Checking available updates..." "yellow" + $outdated = Get-WingetOutdated + + #Log list of app to update + foreach ($app in $outdated){ + #List available updates + $Log = "Available update : $($app.Name). Current version : $($app.Version). Available version : $($app.AvailableVersion)." + $Log | Write-host + $Log | out-file -filepath $LogFile -Append + } + + #Count good update installs + $InstallOK = 0 + + #For each app, notify and update + foreach ($app in $outdated){ + + if (-not ($toSkip -contains $app.Id)){ + + #Send available update notification + Write-Log "Updating $($app.Name) from $($app.Version) to $($app.AvailableVersion)..." "Cyan" + $Title = $NotifLocale.local.outputs.output[2].title -f $($app.Name) + $Message = $NotifLocale.local.outputs.output[2].message -f $($app.Version), $($app.AvailableVersion) + $MessageType = "info" + $Balise = $($app.Name) + Start-NotifTask $Title $Message $MessageType $Balise + + #Winget upgrade + Write-Log "------ Winget - $($app.Name) Upgrade Starts ------" "Gray" + & $upgradecmd upgrade --id $($app.Id) --all --accept-package-agreements --accept-source-agreements -h + Write-Log "----- Winget - $($app.Name) Upgrade Finished -----" "Gray" + + #Check installed version + $checkoutdated = Get-WingetOutdated + $FailedToUpgrade = $false + foreach ($checkapp in $checkoutdated){ + if ($($checkapp.Id) -eq $($app.Id)) { + $FailedToUpgrade = $true + } + } + + #Notify installation + if ($FailedToUpgrade -eq $false){ + #Send success updated app notification + Write-Log "$($app.Name) updated to $($app.AvailableVersion) !" "Green" + + #Send Notif + $Title = $NotifLocale.local.outputs.output[3].title -f $($app.Name) + $Message = $NotifLocale.local.outputs.output[3].message -f $($app.AvailableVersion) + $MessageType = "success" + $Balise = $($app.Name) + Start-NotifTask $Title $Message $MessageType $Balise + + $InstallOK += 1 + } + else { + #Send failed updated app notification + Write-Log "$($app.Name) update failed." "Red" + + #Send Notif + $Title = $NotifLocale.local.outputs.output[4].title -f $($app.Name) + $Message = $NotifLocale.local.outputs.output[4].message + $MessageType = "error" + $Balise = $($app.Name) + Start-NotifTask $Title $Message $MessageType $Balise + } + } + else{ + Write-Log "$($app.Name) : Skipped upgrade because it is in the excluded app list" "Gray" + } + } + + if ($InstallOK -gt 0){ + Write-Log "$InstallOK apps updated ! No more update." "Green" + } + if ($InstallOK -eq 0){ + Write-Log "No new update." "Green" + } +} + +#End +Write-Log "End of process!" "Cyan" +Sleep 3