wingetautoupdate/winget-update/winget-upgrade.ps1

311 lines
11 KiB
PowerShell
Raw Permalink Normal View History

2022-01-16 17:05:33 +00:00
function Init {
#Var
$Script:WorkingDir = $PSScriptRoot
2022-01-16 17:05:33 +00:00
#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
2022-01-20 21:12:11 +00:00
#Get locale file for Notification
#Default en-US
2022-01-22 09:53:04 +00:00
$DefaultLocale = "$WorkingDir\locale\en-US.xml"
2022-01-20 21:12:11 +00:00
#Get OS locale
$Locale = Get-WinSystemLocale
#Test if OS locale config file exists
2022-01-22 09:53:04 +00:00
$LocaleFile = "$WorkingDir\locale\$($locale.Name).xml"
if(Test-Path $LocaleFile){
[xml]$Script:NotifLocale = Get-Content $LocaleFile -Encoding UTF8 -ErrorAction SilentlyContinue
2022-01-22 15:46:01 +00:00
$LocaleNotif = "Notification Langugage : $($locale.Name)"
2022-01-20 21:12:11 +00:00
}
else{
2022-01-22 09:53:04 +00:00
[xml]$Script:NotifLocale = Get-Content $DefaultLocale -Encoding UTF8 -ErrorAction SilentlyContinue
2022-01-22 15:46:01 +00:00
$LocaleNotif = "Notification Langugage : en-US"
}
Write-Log $LocaleNotif "Cyan"
2022-01-16 17:05:33 +00:00
}
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
}
2022-01-21 15:56:21 +00:00
function Start-NotifTask ($Title,$Message,$MessageType,$Balise) {
2022-01-16 17:05:33 +00:00
#Add XML variables
[xml]$ToastTemplate = @"
<toast launch="ms-get-started://redirect?id=apps_action">
<visual>
<binding template="ToastImageAndText03">
<text id="1">$Title</text>
<text id="2">$Message</text>
<image id="1" src="$WorkingDir\icons\$MessageType.png" />
</binding>
</visual>
<tag>$Balise</tag>
</toast>
"@
#Save XML File
2022-01-21 17:15:37 +00:00
$ToastTemplateLocation = "C:\ProgramData\winget-update\"
if (!(Test-Path $ToastTemplateLocation)){
New-Item -ItemType Directory -Force -Path $ToastTemplateLocation
}
$ToastTemplate.Save("$ToastTemplateLocation\notif.xml")
2022-01-16 17:05:33 +00:00
#Send Notification to user. First, check if script it is run as admin (or system)
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
if ($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)){
Get-ScheduledTask -TaskName "Winget Update Notify" -ErrorAction SilentlyContinue | Start-ScheduledTask -ErrorAction SilentlyContinue
#Wait for notification to display
while ((Get-ScheduledTask -TaskName "Winget Update Notify").State -ne 'Ready') {
Write-Output "Waiting for scheduled task..."
Start-Sleep 3
}
}
#else, run as user
else{
& wscript.exe "$WorkingDir\Invisible.vbs" "powershell.exe -ExecutionPolicy Bypass -File """$WorkingDir\winget-notify.ps1""
2022-01-16 17:05:33 +00:00
}
}
function Test-Network {
$timeout = 0
$ping = $false
#test connectivity during 30 min then timeout
Write-Log "Checking internet connection..." "Yellow"
while (!$ping -and $timeout -lt 1800){
try{
2022-01-22 09:53:04 +00:00
Invoke-RestMethod -Uri "https://api.github.com/zen"
2022-01-22 15:46:01 +00:00
Write-Log "Connected !" "Green"
2022-01-16 17:05:33 +00:00
$ping = $true
2022-01-22 15:46:01 +00:00
return $ping
2022-01-16 17:05:33 +00:00
}
catch{
2022-01-21 15:56:21 +00:00
Start-Sleep 10
2022-01-16 17:05:33 +00:00
$timeout += 10
Write-Log "Checking internet connection. $($timeout)s." "Yellow"
}
if ($timeout -eq 300){
#Send Notif if no connection for 5 min
Write-Log "Notify 'No connection'" "Yellow"
2022-01-22 09:53:04 +00:00
$Title = $NotifLocale.local.outputs.output[0].title
$Message = $NotifLocale.local.outputs.output[0].message
2022-01-16 17:05:33 +00:00
$MessageType = "warning"
$Balise = "connection"
2022-01-21 16:22:42 +00:00
Start-NotifTask $Title $Message $MessageType $Balise
2022-01-16 17:05:33 +00:00
}
}
return $ping
}
function Get-WingetOutdated {
class Software {
[string]$Name
[string]$Id
[string]$Version
[string]$AvailableVersion
}
#Get WinGet Location to run as system
2022-01-18 22:38:56 +00:00
$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"){
2022-01-16 17:05:33 +00:00
#WinGet < 1.17
2022-01-21 15:56:21 +00:00
$script:upgradecmd = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\AppInstallerCLI.exe" | Select-Object -ExpandProperty Path
2022-01-16 17:05:33 +00:00
}
elseif (Test-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe"){
#WinGet > 1.17
2022-01-21 15:56:21 +00:00
$script:upgradecmd = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe" | Select-Object -ExpandProperty Path
2022-01-16 17:05:33 +00:00
}
else{
Write-Log "No Winget installed !"
return
}
2022-01-18 08:49:48 +00:00
2022-01-18 22:38:56 +00:00
#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
2022-01-16 19:22:15 +00:00
$upgradeResult = & $upgradecmd upgrade | Out-String
2022-01-16 17:05:33 +00:00
2022-01-21 15:56:21 +00:00
#Start Convertion of winget format to an array. Check if "-----" exists
2022-01-16 17:05:33 +00:00
if (!($upgradeResult -match "-----")){
return
}
2022-01-21 15:56:21 +00:00
#Split winget output to lines
2022-01-16 17:05:33 +00:00
$lines = $upgradeResult.Split([Environment]::NewLine)
2022-01-18 22:38:56 +00:00
# Find the line that starts with "------"
2022-01-16 17:05:33 +00:00
$fl = 0
2022-01-22 15:46:01 +00:00
while (-not $lines[$fl].StartsWith("-----")){
2022-01-16 17:05:33 +00:00
$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 = @()
2022-01-22 15:46:01 +00:00
For ($i = $fl + 2; $i -le $lines.Length; $i++){
2022-01-16 17:05:33 +00:00
$line = $lines[$i]
2022-01-22 15:46:01 +00:00
if ($line.Length -gt ($sourceStart) -and -not $line.StartsWith('-')){
2022-01-16 17:05:33 +00:00
$software = [Software]::new()
2022-01-22 15:46:01 +00:00
$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)
$IsNewVersion = [version]$software.AvailableVersion -gt [version]$software.Version
if ($IsNewVersion){
2022-01-22 15:46:01 +00:00
$upgradeList += $software
}
2022-01-16 17:05:33 +00:00
}
}
return $upgradeList
}
2022-01-18 08:49:48 +00:00
function Get-ExcludedApps{
if (Test-Path "$WorkingDir\excluded_apps.txt"){
return Get-Content -Path "$WorkingDir\excluded_apps.txt"
}
}
2022-01-16 17:05:33 +00:00
### MAIN ###
#Run initialisation
Init
#Check network connectivity
$ping = Test-Network
if ($ping){
2022-01-21 15:56:21 +00:00
#Get exclude apps list
2022-01-18 08:49:48 +00:00
$toSkip = Get-ExcludedApps
2022-01-21 15:56:21 +00:00
#Get outdated Winget packages
2022-01-16 17:05:33 +00:00
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"
2022-01-22 09:53:04 +00:00
$Title = $NotifLocale.local.outputs.output[2].title -f $($app.Name)
$Message = $NotifLocale.local.outputs.output[2].message -f $($app.Version), $($app.AvailableVersion)
2022-01-16 17:05:33 +00:00
$MessageType = "info"
$Balise = $($app.Name)
2022-01-21 16:22:42 +00:00
Start-NotifTask $Title $Message $MessageType $Balise
2022-01-16 17:05:33 +00:00
#Install update
$Log = "#--- Winget - $($app.Name) Upgrade Starts ---"
$Log | Write-host -ForegroundColor Gray
$Log | out-file -filepath $LogFile -Append
#Winget upgrade
2022-01-18 09:12:34 +00:00
& $upgradecmd upgrade -e --id $($app.Id) --accept-package-agreements --accept-source-agreements -h
2022-01-21 15:56:21 +00:00
Start-Sleep 3
2022-01-16 17:05:33 +00:00
$Log = "#--- Winget - $($app.Name) Upgrade Finished ---"
$Log | Write-host -ForegroundColor Gray
$Log | out-file -filepath $LogFile -Append
#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
2022-01-22 09:53:04 +00:00
$Title = $NotifLocale.local.outputs.output[3].title -f $($app.Name)
$Message = $NotifLocale.local.outputs.output[3].message -f $($app.AvailableVersion)
2022-01-16 17:05:33 +00:00
$MessageType = "success"
$Balise = $($app.Name)
2022-01-21 16:22:42 +00:00
Start-NotifTask $Title $Message $MessageType $Balise
2022-01-16 17:05:33 +00:00
$InstallOK += 1
}
else {
#Send failed updated app notification
Write-Log "$($app.Name) update failed." "Red"
#Send Notif
2022-01-22 09:53:04 +00:00
$Title = $NotifLocale.local.outputs.output[4].title -f $($app.Name)
$Message = $NotifLocale.local.outputs.output[4].message
2022-01-16 17:05:33 +00:00
$MessageType = "error"
$Balise = $($app.Name)
2022-01-21 16:22:42 +00:00
Start-NotifTask $Title $Message $MessageType $Balise
2022-01-16 17:05:33 +00:00
}
}
else{
2022-01-20 21:12:11 +00:00
Write-Log "$($app.Name) : Skipped upgrade because it is in the excluded app list" "Gray"
2022-01-16 17:05:33 +00:00
}
}
if ($InstallOK -gt 0){
Write-Log "$InstallOK apps updated ! No more update." "Green"
}
if ($InstallOK -eq 0){
Write-Log "No new update." "Green"
}
}
else{
Write-Log "Timeout. No internet connection !" "Red"
#Send Notif
2022-01-22 09:53:04 +00:00
$Title = $NotifLocale.local.outputs.output[1].title
$Message = $NotifLocale.local.outputs.output[1].message
2022-01-16 17:05:33 +00:00
$MessageType = "error"
$Balise = "connection"
2022-01-21 16:22:42 +00:00
Start-NotifTask $Title $Message $MessageType $Balise
2022-01-16 17:05:33 +00:00
}
Write-Log "End of process!" "Cyan"
Sleep 3