diff --git a/Winget-AutoUpdate-Install.ps1 b/Winget-AutoUpdate-Install.ps1 index 6ab9df9..dfea1a2 100644 --- a/Winget-AutoUpdate-Install.ps1 +++ b/Winget-AutoUpdate-Install.ps1 @@ -1,611 +1,738 @@ <# -.SYNOPSIS -Configure Winget to daily update installed apps. + .SYNOPSIS + Configure Winget to daily update installed apps. -.DESCRIPTION -Install powershell scripts and scheduled task to daily run Winget upgrade and notify connected users. -Posibility to exclude apps from auto-update -https://github.com/Romanitho/Winget-AutoUpdate + .DESCRIPTION + Install powershell scripts and scheduled task to daily run Winget upgrade and notify connected users. + Posibility to exclude apps from auto-update + https://github.com/Romanitho/Winget-AutoUpdate -.PARAMETER Silent -Install Winget-AutoUpdate and prerequisites silently + .PARAMETER Silent + Install Winget-AutoUpdate and prerequisites silently -.PARAMETER MaxLogFiles -Specify number of allowed log files (Default is 3 of 0-99: Setting MaxLogFiles to 0 don't delete any old archived log files, 1 keeps the original one and just let it grow) + .PARAMETER MaxLogFiles + Specify number of allowed log files (Default is 3 of 0-99: Setting MaxLogFiles to 0 don't delete any old archived log files, 1 keeps the original one and just let it grow) -.PARAMETER MaxLogSize -Specify the size of the log file in bytes before rotating. (Default is 1048576 = 1 MB) + .PARAMETER MaxLogSize + Specify the size of the log file in bytes before rotating. (Default is 1048576 = 1 MB) -.PARAMETER WingetUpdatePath -Specify Winget-AutoUpdate installation localtion. Default: C:\ProgramData\Winget-AutoUpdate\ + .PARAMETER WingetUpdatePath + 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. + .PARAMETER DoNotUpdate + Do not run Winget-AutoUpdate after installation. By default, Winget-AutoUpdate is run just after installation. -.PARAMETER DisableWAUAutoUpdate -Disable Winget-AutoUpdate update checking. By default, WAU auto update if new version is available on Github. + .PARAMETER DisableWAUAutoUpdate + Disable Winget-AutoUpdate update checking. By default, WAU auto update if new version is available on Github. -.PARAMETER UseWhiteList -Use White List instead of Black List. This setting will not create the "exclude_apps.txt" but "include_apps.txt" + .PARAMETER UseWhiteList + Use White List instead of Black List. This setting will not create the "exclude_apps.txt" but "include_apps.txt" -.PARAMETER ListPath -Get Black/White List from Path (URL/UNC/GPO/Local) + .PARAMETER ListPath + Get Black/White List from Path (URL/UNC/GPO/Local) -.PARAMETER ModsPath -Get mods from Path (URL/UNC/Local/AzureBlob) + .PARAMETER ModsPath + Get mods from Path (URL/UNC/Local/AzureBlob) -.PARAMETER AzureBlobURL -Set the Azure Storage Blob URL including the SAS token. The token requires at a minimum 'Read' and 'List' permissions. It is recommended to set this at the container level + .PARAMETER AzureBlobURL + Set the Azure Storage Blob URL including the SAS token. The token requires at a minimum 'Read' and 'List' permissions. It is recommended to set this at the container level -.PARAMETER Uninstall -Remove scheduled tasks and scripts. + .PARAMETER Uninstall + Remove scheduled tasks and scripts. -.PARAMETER NoClean -Keep critical files when installing/uninstalling + .PARAMETER NoClean + Keep critical files when installing/uninstalling -.PARAMETER DesktopShortcut -Create a shortcut for user interaction on the Desktop to run task "Winget-AutoUpdate" + .PARAMETER DesktopShortcut + Create a shortcut for user interaction on the Desktop to run task "Winget-AutoUpdate" -.PARAMETER StartMenuShortcut -Create shortcuts for user interaction in the Start Menu to run task "Winget-AutoUpdate", open Logs and Web Help + .PARAMETER StartMenuShortcut + Create shortcuts for user interaction in the Start Menu to run task "Winget-AutoUpdate", open Logs and Web Help -.PARAMETER NotificationLevel -Specify the Notification level: Full (Default, displays all notification), SuccessOnly (Only displays notification for success) or None (Does not show any popup). + .PARAMETER NotificationLevel + Specify the Notification level: Full (Default, displays all notification), SuccessOnly (Only displays notification for success) or None (Does not show any popup). -.PARAMETER UpdatesAtLogon -Set WAU to run at user logon. + .PARAMETER UpdatesAtLogon + Set WAU to run at user logon. -.PARAMETER UpdatesInterval -Specify the update frequency: Daily (Default), BiDaily, Weekly, BiWeekly, Monthly or Never + .PARAMETER UpdatesInterval + Specify the update frequency: Daily (Default), BiDaily, Weekly, BiWeekly, Monthly or Never -.PARAMETER UpdatesAtTime -Specify the time of the update interval execution time. Default 6AM + .PARAMETER UpdatesAtTime + Specify the time of the update interval execution time. Default 6AM -.PARAMETER RunOnMetered -Run WAU on metered connection. Default No. + .PARAMETER RunOnMetered + Run WAU on metered connection. Default No. -.PARAMETER InstallUserContext -Install WAU with system and user context executions + .PARAMETER InstallUserContext + Install WAU with system and user context executions -.PARAMETER BypassListForUsers -Configure WAU to bypass the Black/White list when run in user context. Applications installed in system context will be ignored under user context. + .PARAMETER BypassListForUsers + Configure WAU to bypass the Black/White list when run in user context. Applications installed in system context will be ignored under user context. -.EXAMPLE -.\Winget-AutoUpdate-Install.ps1 -Silent -DoNotUpdate -MaxLogFiles 4 -MaxLogSize 2097152 + .EXAMPLE + .\Winget-AutoUpdate-Install.ps1 -Silent -DoNotUpdate -MaxLogFiles 4 -MaxLogSize 2097152 -.EXAMPLE -.\Winget-AutoUpdate-Install.ps1 -Silent -UseWhiteList + .EXAMPLE + .\Winget-AutoUpdate-Install.ps1 -Silent -UseWhiteList -.EXAMPLE -.\Winget-AutoUpdate-Install.ps1 -Silent -ListPath https://www.domain.com/WAULists -StartMenuShortcut -UpdatesInterval BiDaily + .EXAMPLE + .\Winget-AutoUpdate-Install.ps1 -Silent -ListPath https://www.domain.com/WAULists -StartMenuShortcut -UpdatesInterval BiDaily -.EXAMPLE -.\Winget-AutoUpdate-Install.ps1 -Silent -ModsPath https://www.domain.com/WAUMods -DesktopShortcut -UpdatesInterval Weekly + .EXAMPLE + .\Winget-AutoUpdate-Install.ps1 -Silent -ModsPath https://www.domain.com/WAUMods -DesktopShortcut -UpdatesInterval Weekly -.EXAMPLE -.\Winget-AutoUpdate-Install.ps1 -Silent -UpdatesAtLogon -UpdatesInterval Weekly + .EXAMPLE + .\Winget-AutoUpdate-Install.ps1 -Silent -UpdatesAtLogon -UpdatesInterval Weekly -.EXAMPLE -.\Winget-AutoUpdate-Install.ps1 -Silent -Uninstall -NoClean + .EXAMPLE + .\Winget-AutoUpdate-Install.ps1 -Silent -Uninstall -NoClean #> [CmdletBinding()] -param( - [Parameter(Mandatory = $False)] [Alias('S')] [Switch] $Silent = $false, - [Parameter(Mandatory = $False)] [Alias('Path')] [String] $WingetUpdatePath = "$env:ProgramData\Winget-AutoUpdate", - [Parameter(Mandatory = $False)] [Alias('List')] [String] $ListPath, - [Parameter(Mandatory = $False)] [Alias('Mods')] [String] $ModsPath, - [Parameter(Mandatory = $False)] [Alias('AzureBlobURL')] [String] $AzureBlobSASURL, - [Parameter(Mandatory = $False)] [Switch] $DoNotUpdate = $false, - [Parameter(Mandatory = $False)] [Switch] $DisableWAUAutoUpdate = $false, - [Parameter(Mandatory = $False)] [Switch] $RunOnMetered = $false, - [Parameter(Mandatory = $False)] [Switch] $Uninstall = $false, - [Parameter(Mandatory = $False)] [Switch] $NoClean = $false, - [Parameter(Mandatory = $False)] [Switch] $DesktopShortcut = $false, - [Parameter(Mandatory = $False)] [Switch] $StartMenuShortcut = $false, - [Parameter(Mandatory = $False)] [Switch] $UseWhiteList = $false, - [Parameter(Mandatory = $False)] [ValidateSet("Full", "SuccessOnly", "None")] [String] $NotificationLevel = "Full", - [Parameter(Mandatory = $False)] [Switch] $UpdatesAtLogon = $false, - [Parameter(Mandatory = $False)] [ValidateSet("Daily", "BiDaily", "Weekly", "BiWeekly", "Monthly", "Never")] [String] $UpdatesInterval = "Daily", - [Parameter(Mandatory = $False)] [DateTime] $UpdatesAtTime = ("06am"), - [Parameter(Mandatory = $False)] [Switch] $BypassListForUsers = $false, - [Parameter(Mandatory = $False)] [Switch] $InstallUserContext = $false, - [Parameter(Mandatory = $False)] [ValidateRange(0, 99)] [int32] $MaxLogFiles = 3, - [Parameter(Mandatory = $False)] [int64] $MaxLogSize = 1048576 # in bytes, default is 1048576 = 1 MB +param ( + [Alias('S')] + [Switch] + $Silent = $false, + [Alias('Path')] + [String] + $WingetUpdatePath = "$env:ProgramData\Winget-AutoUpdate", + [Alias('List')] + [String] + $ListPath, + [Alias('Mods')] + [String] + $ModsPath, + [Alias('AzureBlobURL')] + [String] + $AzureBlobSASURL, + [Switch] + $DoNotUpdate = $false, + [Switch] + $DisableWAUAutoUpdate = $false, + [Switch] + $RunOnMetered = $false, + [Switch] + $Uninstall = $false, + [Switch] + $NoClean = $false, + [Switch] + $DesktopShortcut = $false, + [Switch] + $StartMenuShortcut = $false, + [Switch] + $UseWhiteList = $false, + [ValidateSet('Full', 'SuccessOnly', 'None')] + [String] + $NotificationLevel = 'Full', + [Switch] + $UpdatesAtLogon = $false, + [ValidateSet('Daily', 'BiDaily', 'Weekly', 'BiWeekly', 'Monthly', 'Never')] + [String] + $UpdatesInterval = 'Daily', + [DateTime] + $UpdatesAtTime = ('06am'), + [Switch] + $BypassListForUsers = $false, + [Switch] + $InstallUserContext = $false, + [ValidateRange(0, 99)] + [int] + $MaxLogFiles = 3, + [long] + $MaxLogSize = 1048576 # in bytes, default is 1048576 = 1 MB ) <# FUNCTIONS #> -function Install-Prerequisites { +function Install-Prerequisites +{ + Write-Host -Object "`nChecking prerequisites..." -ForegroundColor Yellow - Write-Host "`nChecking prerequisites..." -ForegroundColor Yellow + #Check if Visual C++ 2019 or 2022 installed + $Visual2019 = 'Microsoft Visual C++ 2015-2019 Redistributable*' + $Visual2022 = 'Microsoft Visual C++ 2015-2022 Redistributable*' + $path = Get-Item HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object -FilterScript { + $_.GetValue('DisplayName') -like $Visual2019 -or $_.GetValue('DisplayName') -like $Visual2022 + } - #Check if Visual C++ 2019 or 2022 installed - $Visual2019 = "Microsoft Visual C++ 2015-2019 Redistributable*" - $Visual2022 = "Microsoft Visual C++ 2015-2022 Redistributable*" - $path = Get-Item HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object { $_.GetValue("DisplayName") -like $Visual2019 -or $_.GetValue("DisplayName") -like $Visual2022 } - - #If not installed, ask for installation - if (!($path)) { - #If -silent option, force installation - if ($Silent) { + #If not installed, ask for installation + if (!($path)) + { + #If -silent option, force installation + if ($Silent) + { + $InstallApp = 1 + } + else + { + #Ask for installation + $MsgBoxTitle = 'Winget Prerequisites' + $MsgBoxContent = 'Microsoft Visual C++ 2015-2022 is required. Would you like to install it?' + $MsgBoxTimeOut = 60 + $MsgBoxReturn = (New-Object -ComObject 'Wscript.Shell').Popup($MsgBoxContent, $MsgBoxTimeOut, $MsgBoxTitle, 4 + 32) + if ($MsgBoxReturn -ne 7) + { $InstallApp = 1 - } - else { - #Ask for installation - $MsgBoxTitle = "Winget Prerequisites" - $MsgBoxContent = "Microsoft Visual C++ 2015-2022 is required. Would you like to install it?" - $MsgBoxTimeOut = 60 - $MsgBoxReturn = (New-Object -ComObject "Wscript.Shell").Popup($MsgBoxContent, $MsgBoxTimeOut, $MsgBoxTitle, 4 + 32) - if ($MsgBoxReturn -ne 7) { - $InstallApp = 1 + } + else + { + $InstallApp = 0 + } + } + #Install if approved + if ($InstallApp -eq 1) + { + try + { + if ((Get-CimInstance Win32_OperatingSystem).OSArchitecture -like '*64*') + { + $OSArch = 'x64' } - else { - $InstallApp = 0 + else + { + $OSArch = 'x86' } - } - #Install if approved - if ($InstallApp -eq 1) { - try { - if ((Get-CimInStance Win32_OperatingSystem).OSArchitecture -like "*64*") { - $OSArch = "x64" - } - else { - $OSArch = "x86" - } - Write-host "-> Downloading VC_redist.$OSArch.exe..." - $SourceURL = "https://aka.ms/vs/17/release/VC_redist.$OSArch.exe" - $Installer = $WingetUpdatePath + "\VC_redist.$OSArch.exe" - $ProgressPreference = 'SilentlyContinue' - Invoke-WebRequest $SourceURL -UseBasicParsing -OutFile (New-Item -Path $Installer -Force) - Write-host "-> Installing VC_redist.$OSArch.exe..." - Start-Process -FilePath $Installer -Args "/quiet /norestart" -Wait - Remove-Item $Installer -ErrorAction Ignore - Write-host "MS Visual C++ 2015-2022 installed successfully" -ForegroundColor Green - } - catch { - Write-host "MS Visual C++ 2015-2022 installation failed." -ForegroundColor Red - Start-Sleep 3 - } - } - else { - Write-host "-> MS Visual C++ 2015-2022 will not be installed." -ForegroundColor Magenta - } - } - else { - Write-Host "Prerequisites checked. OK" -ForegroundColor Green - } + Write-Host -Object "-> Downloading VC_redist.$OSArch.exe..." + $SourceURL = "https://aka.ms/vs/17/release/VC_redist.$OSArch.exe" + $Installer = $WingetUpdatePath + "\VC_redist.$OSArch.exe" + $ProgressPreference = 'SilentlyContinue' + Invoke-WebRequest -Uri $SourceURL -UseBasicParsing -OutFile (New-Item -Path $Installer -Force) + Write-Host -Object "-> Installing VC_redist.$OSArch.exe..." + Start-Process -FilePath $Installer -ArgumentList '/quiet /norestart' -Wait + Remove-Item $Installer -ErrorAction Ignore + Write-Host -Object 'MS Visual C++ 2015-2022 installed successfully' -ForegroundColor Green + } + catch + { + Write-Host -Object 'MS Visual C++ 2015-2022 installation failed.' -ForegroundColor Red + Start-Sleep -Seconds 3 + } + } + else + { + Write-Host -Object '-> MS Visual C++ 2015-2022 will not be installed.' -ForegroundColor Magenta + } + } + else + { + Write-Host -Object 'Prerequisites checked. OK' -ForegroundColor Green + } } -function Install-WinGet { +function Install-WinGet +{ + Write-Host -Object "`nChecking if Winget is installed" -ForegroundColor Yellow - Write-Host "`nChecking if Winget is installed" -ForegroundColor Yellow + #Check Package Install + $TestWinGet = Get-AppxProvisionedPackage -Online | Where-Object -FilterScript { + $_.DisplayName -eq 'Microsoft.DesktopAppInstaller' + } - #Check Package Install - $TestWinGet = Get-AppxProvisionedPackage -Online | Where-Object { $_.DisplayName -eq "Microsoft.DesktopAppInstaller" } + #Current: v1.5.2201 = 1.20.2201.0 = 2023.808.2243.0 + if ([Version]$TestWinGet.Version -ge '2023.808.2243.0') + { + Write-Host -Object 'Winget is Installed' -ForegroundColor Green + } + else + { + Write-Host -Object '-> Winget is not installed:' - #Current: v1.5.2201 = 1.20.2201.0 = 2023.808.2243.0 - If ([Version]$TestWinGet.Version -ge "2023.808.2243.0") { + #Check if $WingetUpdatePath exist + if (!(Test-Path $WingetUpdatePath)) + { + $null = New-Item -ItemType Directory -Force -Path $WingetUpdatePath + } - Write-Host "Winget is Installed" -ForegroundColor Green + #Downloading and Installing Dependencies in SYSTEM context + if (!(Get-AppxPackage -Name 'Microsoft.UI.Xaml.2.7')) + { + Write-Host -Object '-> Downloading Microsoft.UI.Xaml.2.7...' + $UiXamlUrl = 'https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.7.0' + $UiXamlZip = "$WingetUpdatePath\Microsoft.UI.XAML.2.7.zip" + Invoke-RestMethod -Uri $UiXamlUrl -OutFile $UiXamlZip + Expand-Archive -Path $UiXamlZip -DestinationPath "$WingetUpdatePath\extracted" -Force + try + { + Write-Host -Object '-> Installing Microsoft.UI.Xaml.2.7...' + $null = Add-AppxProvisionedPackage -Online -PackagePath "$WingetUpdatePath\extracted\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.7.appx" -SkipLicense + Write-Host -Object 'Microsoft.UI.Xaml.2.7 installed successfully' -ForegroundColor Green + } + catch + { + Write-Host -Object 'Failed to intall Wicrosoft.UI.Xaml.2.7...' -ForegroundColor Red + } + Remove-Item -Path $UiXamlZip -Force + Remove-Item -Path "$WingetUpdatePath\extracted" -Force -Recurse + } - } - Else { + if (!(Get-AppxPackage -Name 'Microsoft.VCLibs.140.00.UWPDesktop')) + { + Write-Host -Object '-> Downloading Microsoft.VCLibs.140.00.UWPDesktop...' + $VCLibsUrl = 'https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx' + $VCLibsFile = "$WingetUpdatePath\Microsoft.VCLibs.x64.14.00.Desktop.appx" + Invoke-RestMethod -Uri $VCLibsUrl -OutFile $VCLibsFile + try + { + Write-Host -Object '-> Installing Microsoft.VCLibs.140.00.UWPDesktop...' + $null = Add-AppxProvisionedPackage -Online -PackagePath $VCLibsFile -SkipLicense + Write-Host -Object 'Microsoft.VCLibs.140.00.UWPDesktop installed successfully' -ForegroundColor Green + } + catch + { + Write-Host -Object 'Failed to intall Microsoft.VCLibs.140.00.UWPDesktop...' -ForegroundColor Red + } + Remove-Item -Path $VCLibsFile -Force + } - Write-Host "-> Winget is not installed:" + #Download WinGet MSIXBundle + Write-Host -Object '-> Downloading Winget MSIXBundle for App Installer...' + $WinGetURL = 'https://github.com/microsoft/winget-cli/releases/download/v1.5.2201/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle' + $WebClient = New-Object -TypeName System.Net.WebClient + $WebClient.DownloadFile($WinGetURL, "$WingetUpdatePath\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle") - #Check if $WingetUpdatePath exist - if (!(Test-Path $WingetUpdatePath)) { - New-Item -ItemType Directory -Force -Path $WingetUpdatePath | Out-Null - } - - #Downloading and Installing Dependencies in SYSTEM context - if (!(Get-AppxPackage -Name 'Microsoft.UI.Xaml.2.7')) { - Write-Host "-> Downloading Microsoft.UI.Xaml.2.7..." - $UiXamlUrl = "https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.7.0" - $UiXamlZip = "$WingetUpdatePath\Microsoft.UI.XAML.2.7.zip" - Invoke-RestMethod -Uri $UiXamlUrl -OutFile $UiXamlZip - Expand-Archive -Path $UiXamlZip -DestinationPath "$WingetUpdatePath\extracted" -Force - try { - Write-Host "-> Installing Microsoft.UI.Xaml.2.7..." - Add-AppxProvisionedPackage -Online -PackagePath "$WingetUpdatePath\extracted\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.7.appx" -SkipLicense | Out-Null - Write-host "Microsoft.UI.Xaml.2.7 installed successfully" -ForegroundColor Green - } - catch { - Write-Host "Failed to intall Wicrosoft.UI.Xaml.2.7..." -ForegroundColor Red - } - Remove-Item -Path $UiXamlZip -Force - Remove-Item -Path "$WingetUpdatePath\extracted" -Force -Recurse - } - - if (!(Get-AppxPackage -Name 'Microsoft.VCLibs.140.00.UWPDesktop')) { - Write-Host "-> Downloading Microsoft.VCLibs.140.00.UWPDesktop..." - $VCLibsUrl = "https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx" - $VCLibsFile = "$WingetUpdatePath\Microsoft.VCLibs.x64.14.00.Desktop.appx" - Invoke-RestMethod -Uri $VCLibsUrl -OutFile $VCLibsFile - try { - Write-Host "-> Installing Microsoft.VCLibs.140.00.UWPDesktop..." - Add-AppxProvisionedPackage -Online -PackagePath $VCLibsFile -SkipLicense | Out-Null - Write-host "Microsoft.VCLibs.140.00.UWPDesktop installed successfully" -ForegroundColor Green - } - catch { - Write-Host "Failed to intall Microsoft.VCLibs.140.00.UWPDesktop..." -ForegroundColor Red - } - Remove-Item -Path $VCLibsFile -Force - } - - #Download WinGet MSIXBundle - Write-Host "-> Downloading Winget MSIXBundle for App Installer..." - $WinGetURL = "https://github.com/microsoft/winget-cli/releases/download/v1.5.2201/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" - $WebClient = New-Object System.Net.WebClient - $WebClient.DownloadFile($WinGetURL, "$WingetUpdatePath\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle") - - #Install WinGet MSIXBundle in SYSTEM context - try { - Write-Host "-> Installing Winget MSIXBundle for App Installer..." - Add-AppxProvisionedPackage -Online -PackagePath "$WingetUpdatePath\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -SkipLicense | Out-Null - Write-host "Winget MSIXBundle for App Installer installed successfully" -ForegroundColor Green - } - catch { - Write-Host "Failed to intall Winget MSIXBundle for App Installer..." -ForegroundColor Red - } - - #Remove WinGet MSIXBundle - Remove-Item -Path "$WingetUpdatePath\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -Force -ErrorAction Continue - - } + #Install WinGet MSIXBundle in SYSTEM context + try + { + Write-Host -Object '-> Installing Winget MSIXBundle for App Installer...' + $null = Add-AppxProvisionedPackage -Online -PackagePath "$WingetUpdatePath\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -SkipLicense + Write-Host -Object 'Winget MSIXBundle for App Installer installed successfully' -ForegroundColor Green + } + catch + { + Write-Host -Object 'Failed to intall Winget MSIXBundle for App Installer...' -ForegroundColor Red + } + #Remove WinGet MSIXBundle + Remove-Item -Path "$WingetUpdatePath\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -Force -ErrorAction Continue + } } -function Install-WingetAutoUpdate { +function Install-WingetAutoUpdate +{ + Write-Host -Object "`nInstalling WAU..." -ForegroundColor Yellow - Write-Host "`nInstalling WAU..." -ForegroundColor Yellow + try + { + #Copy files to location (and clean old install) + if (!(Test-Path $WingetUpdatePath)) + { + $null = New-Item -ItemType Directory -Force -Path $WingetUpdatePath + } + else + { + if (!$NoClean) + { + Remove-Item -Path "$WingetUpdatePath\*" -Exclude *.log -Recurse -Force + } + else + { + #Keep critical files + Get-ChildItem -Path $WingetUpdatePath -Exclude *.txt, mods, logs | Remove-Item -Recurse -Force + } + } + Copy-Item -Path "$PSScriptRoot\Winget-AutoUpdate\*" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue - try { - #Copy files to location (and clean old install) - if (!(Test-Path $WingetUpdatePath)) { - New-Item -ItemType Directory -Force -Path $WingetUpdatePath | Out-Null - } - else { - if (!$NoClean) { - Remove-Item -Path "$WingetUpdatePath\*" -Exclude *.log -Recurse -Force + #White List or Black List apps + if ($UseWhiteList) + { + if (!$NoClean) + { + if ((Test-Path -Path "$PSScriptRoot\included_apps.txt")) + { + Copy-Item -Path "$PSScriptRoot\included_apps.txt" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue } - else { - #Keep critical files - Get-ChildItem -Path $WingetUpdatePath -Exclude *.txt, mods, logs | Remove-Item -Recurse -Force + else + { + if (!$ListPath) + { + $null = New-Item -Path $WingetUpdatePath -Name 'included_apps.txt' -ItemType 'file' -ErrorAction SilentlyContinue + } } - } - Copy-Item -Path "$PSScriptRoot\Winget-AutoUpdate\*" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue - - #White List or Black List apps - if ($UseWhiteList) { - if (!$NoClean) { - if ((Test-Path "$PSScriptRoot\included_apps.txt")) { - Copy-Item -Path "$PSScriptRoot\included_apps.txt" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue - } - else { - if (!$ListPath) { - New-Item -Path $WingetUpdatePath -Name "included_apps.txt" -ItemType "file" -ErrorAction SilentlyContinue | Out-Null - } - } + } + elseif (!(Test-Path -Path "$WingetUpdatePath\included_apps.txt")) + { + if ((Test-Path -Path "$PSScriptRoot\included_apps.txt")) + { + Copy-Item -Path "$PSScriptRoot\included_apps.txt" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue } - elseif (!(Test-Path "$WingetUpdatePath\included_apps.txt")) { - if ((Test-Path "$PSScriptRoot\included_apps.txt")) { - Copy-Item -Path "$PSScriptRoot\included_apps.txt" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue - } - else { - if (!$ListPath) { - New-Item -Path $WingetUpdatePath -Name "included_apps.txt" -ItemType "file" -ErrorAction SilentlyContinue | Out-Null - } - } + else + { + if (!$ListPath) + { + $null = New-Item -Path $WingetUpdatePath -Name 'included_apps.txt' -ItemType 'file' -ErrorAction SilentlyContinue + } } - } - else { - if (!$NoClean) { - Copy-Item -Path "$PSScriptRoot\excluded_apps.txt" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue - } - elseif (!(Test-Path "$WingetUpdatePath\excluded_apps.txt")) { - Copy-Item -Path "$PSScriptRoot\excluded_apps.txt" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue - } - } + } + } + else + { + if (!$NoClean) + { + Copy-Item -Path "$PSScriptRoot\excluded_apps.txt" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue + } + elseif (!(Test-Path -Path "$WingetUpdatePath\excluded_apps.txt")) + { + Copy-Item -Path "$PSScriptRoot\excluded_apps.txt" -Destination $WingetUpdatePath -Recurse -Force -ErrorAction SilentlyContinue + } + } - # Set dummy regkeys for notification name and icon - & reg add "HKCR\AppUserModelId\Windows.SystemToast.Winget.Notification" /v DisplayName /t REG_EXPAND_SZ /d "Application Update" /f | Out-Null - & reg add "HKCR\AppUserModelId\Windows.SystemToast.Winget.Notification" /v IconUri /t REG_EXPAND_SZ /d %SystemRoot%\system32\@WindowsUpdateToastIcon.png /f | Out-Null + # Set dummy regkeys for notification name and icon + $null = & "$env:windir\system32\reg.exe" add 'HKCR\AppUserModelId\Windows.SystemToast.Winget.Notification' /v DisplayName /t REG_EXPAND_SZ /d 'Application Update' /f + $null = & "$env:windir\system32\reg.exe" add 'HKCR\AppUserModelId\Windows.SystemToast.Winget.Notification' /v IconUri /t REG_EXPAND_SZ /d %SystemRoot%\system32\@WindowsUpdateToastIcon.png /f - # Settings for the scheduled task for Updates - $taskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$($WingetUpdatePath)\winget-upgrade.ps1`"" - $taskTriggers = @() - if ($UpdatesAtLogon) { - $tasktriggers += New-ScheduledTaskTrigger -AtLogOn - } - if ($UpdatesInterval -eq "Daily") { - $tasktriggers += New-ScheduledTaskTrigger -Daily -At $UpdatesAtTime - } - elseif ($UpdatesInterval -eq "BiDaily") { - $tasktriggers += New-ScheduledTaskTrigger -Daily -At $UpdatesAtTime -DaysInterval 2 - } - elseif ($UpdatesInterval -eq "Weekly") { - $tasktriggers += New-ScheduledTaskTrigger -Weekly -At $UpdatesAtTime -DaysOfWeek 2 - } - elseif ($UpdatesInterval -eq "BiWeekly") { - $tasktriggers += New-ScheduledTaskTrigger -Weekly -At $UpdatesAtTime -DaysOfWeek 2 -WeeksInterval 2 - } - elseif ($UpdatesInterval -eq "Monthly") { - $tasktriggers += New-ScheduledTaskTrigger -Weekly -At $UpdatesAtTime -DaysOfWeek 2 -WeeksInterval 4 - } - $taskUserPrincipal = New-ScheduledTaskPrincipal -UserId S-1-5-18 -RunLevel Highest - $taskSettings = New-ScheduledTaskSettingsSet -Compatibility Win8 -StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 03:00:00 + # Settings for the scheduled task for Updates + $taskAction = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$($WingetUpdatePath)\winget-upgrade.ps1`"" + $taskTriggers = @() + if ($UpdatesAtLogon) + { + $taskTriggers += New-ScheduledTaskTrigger -AtLogOn + } + if ($UpdatesInterval -eq 'Daily') + { + $taskTriggers += New-ScheduledTaskTrigger -Daily -At $UpdatesAtTime + } + elseif ($UpdatesInterval -eq 'BiDaily') + { + $taskTriggers += New-ScheduledTaskTrigger -Daily -At $UpdatesAtTime -DaysInterval 2 + } + elseif ($UpdatesInterval -eq 'Weekly') + { + $taskTriggers += New-ScheduledTaskTrigger -Weekly -At $UpdatesAtTime -DaysOfWeek 2 + } + elseif ($UpdatesInterval -eq 'BiWeekly') + { + $taskTriggers += New-ScheduledTaskTrigger -Weekly -At $UpdatesAtTime -DaysOfWeek 2 -WeeksInterval 2 + } + elseif ($UpdatesInterval -eq 'Monthly') + { + $taskTriggers += New-ScheduledTaskTrigger -Weekly -At $UpdatesAtTime -DaysOfWeek 2 -WeeksInterval 4 + } + $taskUserPrincipal = New-ScheduledTaskPrincipal -UserId S-1-5-18 -RunLevel Highest + $taskSettings = New-ScheduledTaskSettingsSet -Compatibility Win8 -StartWhenAvailable -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 03:00:00 - # Set up the task, and register it - if ($taskTriggers) { - $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings -Trigger $taskTriggers - } - else { - $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings - } - - Register-ScheduledTask -TaskName 'Winget-AutoUpdate' -InputObject $task -Force | Out-Null + # Set up the task, and register it + if ($taskTriggers) + { + $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings -Trigger $taskTriggers + } + else + { + $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings + } - if ($InstallUserContext) { - # Settings for the scheduled task in User context - $taskAction = New-ScheduledTaskAction -Execute "wscript.exe" -Argument "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\winget-upgrade.ps1`"`"" - $taskUserPrincipal = New-ScheduledTaskPrincipal -GroupId S-1-5-11 - $taskSettings = New-ScheduledTaskSettingsSet -Compatibility Win8 -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 03:00:00 + $null = Register-ScheduledTask -TaskName 'Winget-AutoUpdate' -InputObject $task -Force - # Set up the task for user apps - $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings - Register-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -InputObject $task -Force | Out-Null - } + if ($InstallUserContext) + { + # Settings for the scheduled task in User context + $taskAction = New-ScheduledTaskAction -Execute 'wscript.exe' -Argument "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\winget-upgrade.ps1`"`"" + $taskUserPrincipal = New-ScheduledTaskPrincipal -GroupId S-1-5-11 + $taskSettings = New-ScheduledTaskSettingsSet -Compatibility Win8 -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 03:00:00 - # Settings for the scheduled task for Notifications - $taskAction = New-ScheduledTaskAction -Execute "wscript.exe" -Argument "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\winget-notify.ps1`"`"" - $taskUserPrincipal = New-ScheduledTaskPrincipal -GroupId S-1-5-11 - $taskSettings = New-ScheduledTaskSettingsSet -Compatibility Win8 -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 00:05:00 + # Set up the task for user apps + $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings + $null = Register-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -InputObject $task -Force + } - # Set up the task, and register it - $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings - Register-ScheduledTask -TaskName 'Winget-AutoUpdate-Notify' -InputObject $task -Force | Out-Null + # Settings for the scheduled task for Notifications + $taskAction = New-ScheduledTaskAction -Execute 'wscript.exe' -Argument "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\winget-notify.ps1`"`"" + $taskUserPrincipal = New-ScheduledTaskPrincipal -GroupId S-1-5-11 + $taskSettings = New-ScheduledTaskSettingsSet -Compatibility Win8 -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 00:05:00 - #Set task readable/runnable for all users - $scheduler = New-Object -ComObject "Schedule.Service" - $scheduler.Connect() - $task = $scheduler.GetFolder("").GetTask("Winget-AutoUpdate") - $sec = $task.GetSecurityDescriptor(0xF) - $sec = $sec + '(A;;GRGX;;;AU)' - $task.SetSecurityDescriptor($sec, 0) + # Set up the task, and register it + $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings + $null = Register-ScheduledTask -TaskName 'Winget-AutoUpdate-Notify' -InputObject $task -Force - # Configure Reg Key - $regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" - New-Item $regPath -Force | Out-Null - New-ItemProperty $regPath -Name DisplayName -Value "Winget-AutoUpdate (WAU)" -Force | Out-Null - New-ItemProperty $regPath -Name DisplayIcon -Value "C:\Windows\System32\shell32.dll,-16739" -Force | Out-Null - New-ItemProperty $regPath -Name DisplayVersion -Value $WAUVersion -Force | Out-Null - New-ItemProperty $regPath -Name InstallLocation -Value $WingetUpdatePath -Force | Out-Null - New-ItemProperty $regPath -Name UninstallString -Value "powershell.exe -noprofile -executionpolicy bypass -file `"$WingetUpdatePath\WAU-Uninstall.ps1`"" -Force | Out-Null - New-ItemProperty $regPath -Name QuietUninstallString -Value "powershell.exe -noprofile -executionpolicy bypass -file `"$WingetUpdatePath\WAU-Uninstall.ps1`"" -Force | Out-Null - New-ItemProperty $regPath -Name NoModify -Value 1 -Force | Out-Null - New-ItemProperty $regPath -Name NoRepair -Value 1 -Force | Out-Null - New-ItemProperty $regPath -Name Publisher -Value "Romanitho" -Force | Out-Null - New-ItemProperty $regPath -Name URLInfoAbout -Value "https://github.com/Romanitho/Winget-AutoUpdate" -Force | Out-Null - New-ItemProperty $regPath -Name WAU_NotificationLevel -Value $NotificationLevel -Force | Out-Null - if ($WAUVersion -match "-"){ - New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value 1 -PropertyType DWord -Force | Out-Null - } - else { - New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value 0 -PropertyType DWord -Force | Out-Null - } - New-ItemProperty $regPath -Name WAU_PostUpdateActions -Value 0 -PropertyType DWord -Force | Out-Null - New-ItemProperty $regPath -Name WAU_MaxLogFiles -Value $MaxLogFiles -PropertyType DWord -Force | Out-Null - New-ItemProperty $regPath -Name WAU_MaxLogSize -Value $MaxLogSize -PropertyType DWord -Force | Out-Null - if ($DisableWAUAutoUpdate) { - New-ItemProperty $regPath -Name WAU_DisableAutoUpdate -Value 1 -Force | Out-Null - } - if ($UseWhiteList) { - New-ItemProperty $regPath -Name WAU_UseWhiteList -Value 1 -PropertyType DWord -Force | Out-Null - } - if (!$RunOnMetered) { - New-ItemProperty $regPath -Name WAU_DoNotRunOnMetered -Value 1 -PropertyType DWord -Force | Out-Null - } - if ($ListPath) { - New-ItemProperty $regPath -Name WAU_ListPath -Value $ListPath -Force | Out-Null - } - if ($ModsPath) { - New-ItemProperty $regPath -Name WAU_ModsPath -Value $ModsPath -Force | Out-Null - } - if ($AzureBlobSASURL) { - New-ItemProperty $regPath -Name WAU_AzureBlobSASURL -Value $AzureBlobSASURL -Force | Out-Null - } - if ($BypassListForUsers) { - New-ItemProperty $regPath -Name WAU_BypassListForUsers -Value 1 -PropertyType DWord -Force | Out-Null - } + #Set task readable/runnable for all users + $scheduler = New-Object -ComObject 'Schedule.Service' + $scheduler.Connect() + $task = $scheduler.GetFolder('').GetTask('Winget-AutoUpdate') + $sec = $task.GetSecurityDescriptor(0xF) + $sec = $sec + '(A;;GRGX;;;AU)' + $task.SetSecurityDescriptor($sec, 0) - #Log file and symlink initialization - . "$WingetUpdatePath\functions\Start-Init.ps1" - Start-Init + # Configure Reg Key + $regPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate' + $null = New-Item $regPath -Force + $null = New-ItemProperty $regPath -Name DisplayName -Value 'Winget-AutoUpdate (WAU)' -Force + $null = New-ItemProperty $regPath -Name DisplayIcon -Value 'C:\Windows\System32\shell32.dll,-16739' -Force + $null = New-ItemProperty $regPath -Name DisplayVersion -Value $WAUVersion -Force + $null = New-ItemProperty $regPath -Name InstallLocation -Value $WingetUpdatePath -Force + $null = New-ItemProperty $regPath -Name UninstallString -Value "powershell.exe -noprofile -executionpolicy bypass -file `"$WingetUpdatePath\WAU-Uninstall.ps1`"" -Force + $null = New-ItemProperty $regPath -Name QuietUninstallString -Value "powershell.exe -noprofile -executionpolicy bypass -file `"$WingetUpdatePath\WAU-Uninstall.ps1`"" -Force + $null = New-ItemProperty $regPath -Name NoModify -Value 1 -Force + $null = New-ItemProperty $regPath -Name NoRepair -Value 1 -Force + $null = New-ItemProperty $regPath -Name Publisher -Value 'Romanitho' -Force + $null = New-ItemProperty $regPath -Name URLInfoAbout -Value 'https://github.com/Romanitho/Winget-AutoUpdate' -Force + $null = New-ItemProperty $regPath -Name WAU_NotificationLevel -Value $NotificationLevel -Force + if ($WAUVersion -match '-') + { + $null = New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value 1 -PropertyType DWord -Force + } + else + { + $null = New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value 0 -PropertyType DWord -Force + } + $null = New-ItemProperty $regPath -Name WAU_PostUpdateActions -Value 0 -PropertyType DWord -Force + $null = New-ItemProperty $regPath -Name WAU_MaxLogFiles -Value $MaxLogFiles -PropertyType DWord -Force + $null = New-ItemProperty $regPath -Name WAU_MaxLogSize -Value $MaxLogSize -PropertyType DWord -Force + if ($DisableWAUAutoUpdate) + { + $null = New-ItemProperty $regPath -Name WAU_DisableAutoUpdate -Value 1 -Force + } + if ($UseWhiteList) + { + $null = New-ItemProperty $regPath -Name WAU_UseWhiteList -Value 1 -PropertyType DWord -Force + } + if (!$RunOnMetered) + { + $null = New-ItemProperty $regPath -Name WAU_DoNotRunOnMetered -Value 1 -PropertyType DWord -Force + } + if ($ListPath) + { + $null = New-ItemProperty $regPath -Name WAU_ListPath -Value $ListPath -Force + } + if ($ModsPath) + { + $null = New-ItemProperty $regPath -Name WAU_ModsPath -Value $ModsPath -Force + } + if ($AzureBlobSASURL) + { + $null = New-ItemProperty $regPath -Name WAU_AzureBlobSASURL -Value $AzureBlobSASURL -Force + } + if ($BypassListForUsers) + { + $null = New-ItemProperty $regPath -Name WAU_BypassListForUsers -Value 1 -PropertyType DWord -Force + } - #Security check - Write-host "`nChecking Mods Directory:" -ForegroundColor Yellow - . "$WingetUpdatePath\functions\Invoke-ModsProtect.ps1" - $Protected = Invoke-ModsProtect "$WingetUpdatePath\mods" - if ($Protected -eq $True) { - Write-Host "The mods directory is now secured!`n" -ForegroundColor Green - } - elseif ($Protected -eq $False) { - Write-Host "The mods directory was already secured!`n" -ForegroundColor Green - } - else { - Write-Host "Error: The mods directory couldn't be verified as secured!`n" -ForegroundColor Red - } + #Log file and symlink initialization + . "$WingetUpdatePath\functions\Start-Init.ps1" + Start-Init - #Create Shortcuts - if ($StartMenuShortcut) { - if (!(Test-Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)")) { - New-Item -ItemType Directory -Force -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" | Out-Null - } - Add-Shortcut "wscript.exe" "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Check for updated Apps.lnk" "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\user-run.ps1`"`"" "${env:SystemRoot}\System32\shell32.dll,-16739" "Manual start of Winget-AutoUpdate (WAU)..." - Add-Shortcut "wscript.exe" "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Open logs.lnk" "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\user-run.ps1`" -Logs`"" "${env:SystemRoot}\System32\shell32.dll,-16763" "Open existing WAU logs..." - Add-Shortcut "wscript.exe" "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Web Help.lnk" "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\user-run.ps1`" -Help`"" "${env:SystemRoot}\System32\shell32.dll,-24" "Help for WAU..." - } + #Security check + Write-Host -Object "`nChecking Mods Directory:" -ForegroundColor Yellow + . "$WingetUpdatePath\functions\Invoke-ModsProtect.ps1" + $Protected = Invoke-ModsProtect "$WingetUpdatePath\mods" + if ($Protected -eq $True) + { + Write-Host -Object "The mods directory is now secured!`n" -ForegroundColor Green + } + elseif ($Protected -eq $false) + { + Write-Host -Object "The mods directory was already secured!`n" -ForegroundColor Green + } + else + { + Write-Host -Object "Error: The mods directory couldn't be verified as secured!`n" -ForegroundColor Red + } - if ($DesktopShortcut) { - Add-Shortcut "wscript.exe" "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\user-run.ps1`"`"" "${env:SystemRoot}\System32\shell32.dll,-16739" "Manual start of Winget-AutoUpdate (WAU)..." - } + #Create Shortcuts + if ($StartMenuShortcut) + { + if (!(Test-Path -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)")) + { + $null = New-Item -ItemType Directory -Force -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" + } + Add-Shortcut 'wscript.exe' "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Check for updated Apps.lnk" "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\user-run.ps1`"`"" "${env:SystemRoot}\System32\shell32.dll,-16739" 'Manual start of Winget-AutoUpdate (WAU)...' + Add-Shortcut 'wscript.exe' "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Open logs.lnk" "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\user-run.ps1`" -Logs`"" "${env:SystemRoot}\System32\shell32.dll,-16763" 'Open existing WAU logs...' + Add-Shortcut 'wscript.exe' "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Web Help.lnk" "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\user-run.ps1`" -Help`"" "${env:SystemRoot}\System32\shell32.dll,-24" 'Help for WAU...' + } - Write-host "WAU Installation succeeded!" -ForegroundColor Green - Start-sleep 1 + if ($DesktopShortcut) + { + Add-Shortcut 'wscript.exe' "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" "`"$($WingetUpdatePath)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WingetUpdatePath)\user-run.ps1`"`"" "${env:SystemRoot}\System32\shell32.dll,-16739" 'Manual start of Winget-AutoUpdate (WAU)...' + } - #Run Winget ? - Start-WingetAutoUpdate - } - catch { - Write-host "WAU Installation failed! Run me with admin rights" -ForegroundColor Red - Start-sleep 1 - return $False - } + Write-Host -Object 'WAU Installation succeeded!' -ForegroundColor Green + Start-Sleep -Seconds 1 + + #Run Winget ? + Start-WingetAutoUpdate + } + catch + { + Write-Host -Object 'WAU Installation failed! Run me with admin rights' -ForegroundColor Red + Start-Sleep -Seconds 1 + return $false + } } -function Uninstall-WingetAutoUpdate { +function Uninstall-WingetAutoUpdate +{ + Write-Host -Object "`nUninstalling WAU..." -ForegroundColor Yellow - Write-Host "`nUninstalling WAU..." -ForegroundColor Yellow + try + { + #Get registry install location + $InstallLocation = Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate\' -Name InstallLocation - try { - #Get registry install location - $InstallLocation = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate\" -Name InstallLocation - - #Check if installed location exists and delete - if (Test-Path ($InstallLocation)) { - - if (!$NoClean) { - Remove-Item $InstallLocation -Force -Recurse - if (Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log") { - Remove-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -Force -ErrorAction SilentlyContinue | Out-Null - } - if (Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log") { - Remove-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -Force -ErrorAction SilentlyContinue | Out-Null - } + #Check if installed location exists and delete + if (Test-Path ($InstallLocation)) + { + if (!$NoClean) + { + Remove-Item $InstallLocation -Force -Recurse + if (Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log") + { + $null = Remove-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -Force -ErrorAction SilentlyContinue } - else { - #Keep critical files - Get-ChildItem -Path $InstallLocation -Exclude *.txt, mods, logs | Remove-Item -Recurse -Force + if (Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log") + { + $null = Remove-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -Force -ErrorAction SilentlyContinue } - Get-ScheduledTask -TaskName "Winget-AutoUpdate" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False - Get-ScheduledTask -TaskName "Winget-AutoUpdate-Notify" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False - Get-ScheduledTask -TaskName "Winget-AutoUpdate-UserContext" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False - & reg delete "HKCR\AppUserModelId\Windows.SystemToast.Winget.Notification" /f | Out-Null - & reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" /f | Out-Null + } + else + { + #Keep critical files + Get-ChildItem -Path $InstallLocation -Exclude *.txt, mods, logs | Remove-Item -Recurse -Force + } + Get-ScheduledTask -TaskName 'Winget-AutoUpdate' -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false + Get-ScheduledTask -TaskName 'Winget-AutoUpdate-Notify' -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false + Get-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false + $null = & "$env:windir\system32\reg.exe" delete 'HKCR\AppUserModelId\Windows.SystemToast.Winget.Notification' /f + $null = & "$env:windir\system32\reg.exe" delete 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate' /f - if ((Test-Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)")) { - Remove-Item -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" -Recurse -Force | Out-Null - } + if ((Test-Path -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)")) + { + $null = Remove-Item -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" -Recurse -Force + } - if ((Test-Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk")) { - Remove-Item -Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" -Force | Out-Null - } + if ((Test-Path -Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk")) + { + $null = Remove-Item -Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" -Force + } - Write-host "Uninstallation succeeded!" -ForegroundColor Green - Start-sleep 1 - } - else { - Write-host "$InstallLocation not found! Uninstallation failed!" -ForegroundColor Red - } - } - catch { - Write-host "Uninstallation failed! Run as admin ?" -ForegroundColor Red - Start-sleep 1 - } + Write-Host -Object 'Uninstallation succeeded!' -ForegroundColor Green + Start-Sleep -Seconds 1 + } + else + { + Write-Host -Object "$InstallLocation not found! Uninstallation failed!" -ForegroundColor Red + } + } + catch + { + Write-Host -Object 'Uninstallation failed! Run as admin ?' -ForegroundColor Red + Start-Sleep -Seconds 1 + } } -function Start-WingetAutoUpdate { - #If -DoNotUpdate is true, skip. - if (!($DoNotUpdate)) { - #If -Silent, run Winget-AutoUpdate now - if ($Silent) { +function Start-WingetAutoUpdate +{ + #If -DoNotUpdate is true, skip. + if (!($DoNotUpdate)) + { + #If -Silent, run Winget-AutoUpdate now + if ($Silent) + { + $RunWinget = 1 + } + #Ask for WingetAutoUpdate + else + { + $MsgBoxTitle = 'Winget-AutoUpdate' + $MsgBoxContent = 'Would you like to run Winget-AutoUpdate now?' + $MsgBoxTimeOut = 60 + $MsgBoxReturn = (New-Object -ComObject 'Wscript.Shell').Popup($MsgBoxContent, $MsgBoxTimeOut, $MsgBoxTitle, 4 + 32) + if ($MsgBoxReturn -ne 7) + { $RunWinget = 1 - } - #Ask for WingetAutoUpdate - else { - $MsgBoxTitle = "Winget-AutoUpdate" - $MsgBoxContent = "Would you like to run Winget-AutoUpdate now?" - $MsgBoxTimeOut = 60 - $MsgBoxReturn = (New-Object -ComObject "Wscript.Shell").Popup($MsgBoxContent, $MsgBoxTimeOut, $MsgBoxTitle, 4 + 32) - if ($MsgBoxReturn -ne 7) { - $RunWinget = 1 + } + else + { + $RunWinget = 0 + } + } + if ($RunWinget -eq 1) + { + try + { + Write-Host -Object "`nRunning Winget-AutoUpdate..." -ForegroundColor Yellow + Get-ScheduledTask -TaskName 'Winget-AutoUpdate' -ErrorAction SilentlyContinue | Start-ScheduledTask -ErrorAction SilentlyContinue + while ((Get-ScheduledTask -TaskName 'Winget-AutoUpdate').State -ne 'Ready') + { + Start-Sleep -Seconds 1 } - else { - $RunWinget = 0 - } - } - if ($RunWinget -eq 1) { - try { - Write-host "`nRunning Winget-AutoUpdate..." -ForegroundColor Yellow - Get-ScheduledTask -TaskName "Winget-AutoUpdate" -ErrorAction SilentlyContinue | Start-ScheduledTask -ErrorAction SilentlyContinue - while ((Get-ScheduledTask -TaskName "Winget-AutoUpdate").State -ne 'Ready') { - Start-Sleep 1 - } - } - catch { - Write-host "Failed to run Winget-AutoUpdate..." -ForegroundColor Red - } - } - } - else { - Write-host "Skip running Winget-AutoUpdate" - } + } + catch + { + Write-Host -Object 'Failed to run Winget-AutoUpdate...' -ForegroundColor Red + } + } + } + else + { + Write-Host -Object 'Skip running Winget-AutoUpdate' + } } -function Add-Shortcut ($Target, $Shortcut, $Arguments, $Icon, $Description) { - $WScriptShell = New-Object -ComObject WScript.Shell - $Shortcut = $WScriptShell.CreateShortcut($Shortcut) - $Shortcut.TargetPath = $Target - $Shortcut.Arguments = $Arguments - $Shortcut.IconLocation = $Icon - $Shortcut.Description = $Description - $Shortcut.Save() +function Add-Shortcut +{ + [CmdletBinding()] + param + ( + $Target, + $Shortcut, + $Arguments, + $Icon, + $Description + ) + $WScriptShell = New-Object -ComObject WScript.Shell + $Shortcut = $WScriptShell.CreateShortcut($Shortcut) + $Shortcut.TargetPath = $Target + $Shortcut.Arguments = $Arguments + $Shortcut.IconLocation = $Icon + $Shortcut.Description = $Description + $Shortcut.Save() } <# APP INFO #> -$WAUVersion = Get-Content "$PSScriptRoot\Winget-AutoUpdate\Version.txt" -ErrorAction SilentlyContinue +$WAUVersion = Get-Content -Path "$PSScriptRoot\Winget-AutoUpdate\Version.txt" -ErrorAction SilentlyContinue <# MAIN #> #If running as a 32-bit process on an x64 system, re-launch as a 64-bit process -if ("$env:PROCESSOR_ARCHITEW6432" -ne "ARM64") { - if (Test-Path "$($env:WINDIR)\SysNative\WindowsPowerShell\v1.0\powershell.exe") { - Start-Process "$($env:WINDIR)\SysNative\WindowsPowerShell\v1.0\powershell.exe" -Wait -NoNewWindow -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command $($MyInvocation.line)" - Exit $lastexitcode - } +if ("$env:PROCESSOR_ARCHITEW6432" -ne 'ARM64') +{ + if (Test-Path -Path "$($env:windir)\SysNative\WindowsPowerShell\v1.0\powershell.exe") + { + Start-Process -FilePath "$($env:windir)\SysNative\WindowsPowerShell\v1.0\powershell.exe" -Wait -NoNewWindow -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command $($MyInvocation.line)" + exit $lastexitcode + } } -Write-Host "`n" -Write-Host "`t 888 888 d8888 888 888" -ForegroundColor Magenta -Write-Host "`t 888 o 888 d88888 888 888" -ForegroundColor Magenta -Write-Host "`t 888 d8b 888 d88P888 888 888" -ForegroundColor Magenta -Write-Host "`t 888 d888b 888 d88P 888 888 888" -ForegroundColor Magenta -Write-Host "`t 888d88888b888 d88P 888 888 888" -ForegroundColor Magenta -Write-Host "`t 88888P Y88888 d88P 888 888 888" -ForegroundColor Cyan -Write-Host "`t 8888P Y8888 d88P 888 888 888" -ForegroundColor Magenta -Write-Host "`t 888P Y888 d88P 888 Y8888888P`n" -ForegroundColor Magenta -Write-Host "`t Winget-AutoUpdate $WAUVersion`n" -ForegroundColor Cyan -Write-Host "`t https://github.com/Romanitho/Winget-AutoUpdate`n" -ForegroundColor Magenta -Write-Host "`t________________________________________________________`n`n" +Write-Host -Object "`n" +Write-Host -Object "`t 888 888 d8888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 888 o 888 d88888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 888 d8b 888 d88P888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 888 d888b 888 d88P 888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 888d88888b888 d88P 888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 88888P Y88888 d88P 888 888 888" -ForegroundColor Cyan +Write-Host -Object "`t 8888P Y8888 d88P 888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 888P Y888 d88P 888 Y8888888P`n" -ForegroundColor Magenta +Write-Host -Object "`t Winget-AutoUpdate $WAUVersion`n" -ForegroundColor Cyan +Write-Host -Object "`t https://github.com/Romanitho/Winget-AutoUpdate`n" -ForegroundColor Magenta +Write-Host -Object "`t________________________________________________________`n`n" -if (!$Uninstall) { - Write-host "Installing WAU to $WingetUpdatePath\" - Install-Prerequisites - Install-WinGet - Install-WingetAutoUpdate +if (!$Uninstall) +{ + Write-Host -Object "Installing WAU to $WingetUpdatePath\" + Install-Prerequisites + Install-WinGet + Install-WingetAutoUpdate } -else { - Write-Host "Uninstalling WAU..." - Uninstall-WingetAutoUpdate +else +{ + Write-Host -Object 'Uninstalling WAU...' + Uninstall-WingetAutoUpdate } -Remove-Item "$WingetUpdatePath\Version.txt" -Force -Write-host "`nEnd of process." -ForegroundColor Cyan -Start-Sleep 3 +Remove-Item -Path "$WingetUpdatePath\Version.txt" -Force +Write-Host -Object "`nEnd of process." -ForegroundColor Cyan +Start-Sleep -Seconds 3 diff --git a/Winget-AutoUpdate/User-Run.ps1 b/Winget-AutoUpdate/User-Run.ps1 index 176fb26..d2c8d6b 100644 --- a/Winget-AutoUpdate/User-Run.ps1 +++ b/Winget-AutoUpdate/User-Run.ps1 @@ -1,32 +1,36 @@ <# -.SYNOPSIS -Handle user interaction from shortcuts and show a Toast notification + .SYNOPSIS + Handle user interaction from shortcuts and show a Toast notification -.DESCRIPTION -Act on shortcut run (DEFAULT: Check for updated Apps) + .DESCRIPTION + Act on shortcut run (DEFAULT: Check for updated Apps) -.PARAMETER Logs -Open the Log file from Winget-AutoUpdate installation location + .PARAMETER Logs + Open the Log file from Winget-AutoUpdate installation location -.PARAMETER Help -Open the Web Help page -https://github.com/Romanitho/Winget-AutoUpdate + .PARAMETER Help + Open the Web Help page + https://github.com/Romanitho/Winget-AutoUpdate -.EXAMPLE -.\user-run.ps1 -Logs + .EXAMPLE + .\user-run.ps1 -Logs #> [CmdletBinding()] -param( - [Parameter(Mandatory = $False)] [Switch] $Logs = $false, - [Parameter(Mandatory = $False)] [Switch] $Help = $false +param ( + [Switch] + $Logs = $False, + [Switch] + $Help = $False ) -function Test-WAUisRunning { - If (((Get-ScheduledTask -TaskName 'Winget-AutoUpdate').State -eq 'Running') -or ((Get-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext').State -eq 'Running')) { - Return $True - } +function Test-WAUisRunning +{ + if (((Get-ScheduledTask -TaskName 'Winget-AutoUpdate' -ErrorAction SilentlyContinue).State -eq 'Running') -or ((Get-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -ErrorAction SilentlyContinue).State -eq 'Running')) + { + return $True + } } <# MAIN #> @@ -42,61 +46,72 @@ $Script:WorkingDir = $PSScriptRoot Get-NotifLocale #Set common variables -$OnClickAction = "$WorkingDir\logs\updates.log" +$OnClickAction = ('{0}\logs\updates.log' -f $WorkingDir) $Button1Text = $NotifLocale.local.outputs.output[11].message -if ($Logs) { - if (Test-Path "$WorkingDir\logs\updates.log") { - Invoke-Item "$WorkingDir\logs\updates.log" - } - else { - #Not available yet - $Message = $NotifLocale.local.outputs.output[5].message - $MessageType = "warning" - Start-NotifTask -Message $Message -MessageType $MessageType -UserRun - } +if ($Logs) +{ + if (Test-Path -Path ('{0}\logs\updates.log' -f $WorkingDir)) + { + Invoke-Item -Path ('{0}\logs\updates.log' -f $WorkingDir) + } + else + { + #Not available yet + $Message = $NotifLocale.local.outputs.output[5].message + $MessageType = 'warning' + Start-NotifTask -Message $Message -MessageType $MessageType -UserRun + } } -elseif ($Help) { - Start-Process "https://github.com/Romanitho/Winget-AutoUpdate" +elseif ($Help) +{ + Start-Process -FilePath 'https://github.com/Romanitho/Winget-AutoUpdate' } -else { - try { - #Check if WAU is currently running - if (Test-WAUisRunning) { - $Message = $NotifLocale.local.outputs.output[8].message - $MessageType = "warning" - Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun - break - } - #Run scheduled task - Get-ScheduledTask -TaskName "Winget-AutoUpdate" -ErrorAction Stop | Start-ScheduledTask -ErrorAction Stop - #Starting check - Send notification - $Message = $NotifLocale.local.outputs.output[6].message - $MessageType = "info" - Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun - #Sleep until the task is done - While (Test-WAUisRunning) { - Start-Sleep 3 - } +else +{ + try + { + # Check if WAU is currently running + if (Test-WAUisRunning) + { + $Message = $NotifLocale.local.outputs.output[8].message + $MessageType = 'warning' + Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun + break + } + # Run scheduled task + Get-ScheduledTask -TaskName 'Winget-AutoUpdate' -ErrorAction Stop | Start-ScheduledTask -ErrorAction Stop + # Starting check - Send notification + $Message = $NotifLocale.local.outputs.output[6].message + $MessageType = 'info' + Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun + # Sleep until the task is done + while (Test-WAUisRunning) + { + Start-Sleep -Seconds 3 + } - #Test if there was a list_/winget_error - if (Test-Path "$WorkingDir\logs\error.txt") { - $MessageType = "error" - $Critical = Get-Content "$WorkingDir\logs\error.txt" -Raw - $Critical = $Critical.Trim() - $Critical = $Critical.Substring(0, [Math]::Min($Critical.Length, 50)) - $Message = "Critical:`n$Critical..." - } - else { - $MessageType = "success" - $Message = $NotifLocale.local.outputs.output[9].message - } - Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun - } - catch { - #Check failed - Just send notification - $Message = $NotifLocale.local.outputs.output[7].message - $MessageType = "error" - Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun - } + # Test if there was a list_/winget_error + if (Test-Path -Path ('{0}\logs\error.txt' -f $WorkingDir) -ErrorAction SilentlyContinue) + { + $MessageType = 'error' + $Critical = Get-Content -Path ('{0}\logs\error.txt' -f $WorkingDir) -Raw + $Critical = $Critical.Trim() + $Critical = $Critical.Substring(0, [Math]::Min($Critical.Length, 50)) + $Message = ("Critical:`n{0}..." -f $Critical) + } + else + { + $MessageType = 'success' + $Message = $NotifLocale.local.outputs.output[9].message + } + Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun + } + catch + { + # Check failed - Just send notification + $Message = $NotifLocale.local.outputs.output[7].message + $MessageType = 'error' + Start-NotifTask -Message $Message -MessageType $MessageType -Button1Text $Button1Text -Button1Action $OnClickAction -ButtonDismiss -UserRun + } } diff --git a/Winget-AutoUpdate/WAU-Uninstall.ps1 b/Winget-AutoUpdate/WAU-Uninstall.ps1 index ff10d8d..32e4eab 100644 --- a/Winget-AutoUpdate/WAU-Uninstall.ps1 +++ b/Winget-AutoUpdate/WAU-Uninstall.ps1 @@ -1,85 +1,97 @@ <# -.SYNOPSIS -Uninstall Winget-AutoUpdate + .SYNOPSIS + Uninstall Winget-AutoUpdate -.DESCRIPTION -Uninstalls Winget-AutoUpdate (DEFAULT: clean old install) -https://github.com/Romanitho/Winget-AutoUpdate + .DESCRIPTION + Uninstalls Winget-AutoUpdate (DEFAULT: clean old install) + https://github.com/Romanitho/Winget-AutoUpdate -.PARAMETER NoClean -Uninstall Winget-AutoUpdate (keep critical files) + .PARAMETER NoClean + Uninstall Winget-AutoUpdate (keep critical files) -.EXAMPLE -.\WAU-Uninstall.ps1 -NoClean + .EXAMPLE + .\WAU-Uninstall.ps1 -NoClean #> - [CmdletBinding()] -param( - [Parameter(Mandatory = $False)] [Switch] $NoClean = $false +param ( + [Switch] + $NoClean = $false ) -Write-Host "`n" -Write-Host "`t 888 888 d8888 888 888" -ForegroundColor Magenta -Write-Host "`t 888 o 888 d88888 888 888" -ForegroundColor Magenta -Write-Host "`t 888 d8b 888 d88P888 888 888" -ForegroundColor Magenta -Write-Host "`t 888 d888b 888 d88P 888 888 888" -ForegroundColor Magenta -Write-Host "`t 888d88888b888 d88P 888 888 888" -ForegroundColor Magenta -Write-Host "`t 88888P Y88888 d88P 888 888 888" -ForegroundColor Cyan -Write-Host "`t 8888P Y8888 d88P 888 888 888" -ForegroundColor Magenta -Write-Host "`t 888P Y888 d88P 888 Y8888888P`n" -ForegroundColor Magenta -Write-Host "`t Winget-AutoUpdate`n" -ForegroundColor Cyan -Write-Host "`t https://github.com/Romanitho/Winget-AutoUpdate`n" -ForegroundColor Magenta -Write-Host "`t________________________________________________________`n`n" +Write-Host -Object "`n" +Write-Host -Object "`t 888 888 d8888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 888 o 888 d88888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 888 d8b 888 d88P888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 888 d888b 888 d88P 888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 888d88888b888 d88P 888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 88888P Y88888 d88P 888 888 888" -ForegroundColor Cyan +Write-Host -Object "`t 8888P Y8888 d88P 888 888 888" -ForegroundColor Magenta +Write-Host -Object "`t 888P Y888 d88P 888 Y8888888P`n" -ForegroundColor Magenta +Write-Host -Object "`t Winget-AutoUpdate`n" -ForegroundColor Cyan +Write-Host -Object "`t https://github.com/Romanitho/Winget-AutoUpdate`n" -ForegroundColor Magenta +Write-Host -Object "`t________________________________________________________`n`n" -try { - Write-host "Uninstalling WAU..." -ForegroundColor Yellow - #Get registry install location - $InstallLocation = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate\" -Name InstallLocation +try +{ + Write-Host -Object 'Uninstalling WAU...' -ForegroundColor Yellow - #Check if installed location exists and delete - if (Test-Path ($InstallLocation)) { + # Get registry install location + $InstallLocation = (Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate\' -Name InstallLocation) - if (!$NoClean) { - Remove-Item "$InstallLocation\*" -Force -Recurse -Exclude "*.log" - } - else { - #Keep critical files - Get-ChildItem -Path $InstallLocation -Exclude *.txt, mods, logs | Remove-Item -Recurse -Force - } - Get-ScheduledTask -TaskName "Winget-AutoUpdate" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False - Get-ScheduledTask -TaskName "Winget-AutoUpdate-Notify" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False - Get-ScheduledTask -TaskName "Winget-AutoUpdate-UserContext" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False - & reg delete "HKCR\AppUserModelId\Windows.SystemToast.Winget.Notification" /f | Out-Null - & reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" /f | Out-Null - if (Test-Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate") { - & reg delete "HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" /f | Out-Null - } + # Check if installed location exists and delete + if (Test-Path -Path ($InstallLocation)) + { + if (!$NoClean) + { + $null = (Remove-Item -Path ('{0}\*' -f $InstallLocation) -Force -Confirm:$false -Recurse -Exclude '*.log') + } + else + { + # Keep critical files + $null = (Get-ChildItem -Path $InstallLocation -Exclude *.txt, mods, logs | Remove-Item -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue) + } + $null = (Get-ScheduledTask -TaskName 'Winget-AutoUpdate' -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false) + $null = (Get-ScheduledTask -TaskName 'Winget-AutoUpdate-Notify' -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false) + $null = (Get-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false) + $null = & "$env:windir\system32\reg.exe" delete 'HKCR\AppUserModelId\Windows.SystemToast.Winget.Notification' /f + $null = & "$env:windir\system32\reg.exe" delete 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate' /f - if ((Test-Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)")) { - Remove-Item -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" -Recurse -Force | Out-Null - } + if (Test-Path -Path 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate' -ErrorAction SilentlyContinue) + { + $null = & "$env:windir\system32\reg.exe" delete 'HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate' /f + } - if ((Test-Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk")) { - Remove-Item -Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" -Force | Out-Null - } + if ((Test-Path -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)")) + { + $null = (Remove-Item -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" -Recurse -Force -Confirm:$false) + } - #Remove Intune Logs if they are existing - if (Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log") { - Remove-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -Force -ErrorAction SilentlyContinue | Out-Null - } - if (Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log") { - Remove-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -Force -ErrorAction SilentlyContinue | Out-Null - } + if ((Test-Path -Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk")) + { + $null = (Remove-Item -Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" -Force -Confirm:$false) + } - Write-host "Uninstallation succeeded!" -ForegroundColor Green - } - else { - Write-host "$InstallLocation not found! Uninstallation failed!" -ForegroundColor Red - } + # Remove Intune Logs if they are existing + if (Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log") + { + $null = (Remove-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -Force -Confirm:$false -ErrorAction SilentlyContinue) + } + if (Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -ErrorAction SilentlyContinue) + { + $null = (Remove-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -Force -Confirm:$false -ErrorAction SilentlyContinue) + } + + Write-Host -Object 'Uninstallation succeeded!' -ForegroundColor Green + } + else + { + Write-Host -Object ('{0} not found! Uninstallation failed!' -f $InstallLocation) -ForegroundColor Red + } } -catch { - Write-host "`nUninstallation failed! Run as admin ?" -ForegroundColor Red +catch +{ + Write-Host -Object "`nUninstallation failed! Run as admin ?" -ForegroundColor Red } -Start-sleep 2 +Start-Sleep -Seconds 2 diff --git a/Winget-AutoUpdate/Winget-Notify.ps1 b/Winget-AutoUpdate/Winget-Notify.ps1 index de22ef7..4164a6f 100644 --- a/Winget-AutoUpdate/Winget-Notify.ps1 +++ b/Winget-AutoUpdate/Winget-Notify.ps1 @@ -1,24 +1,29 @@ -#Send Notify Script +# Send Notify Script -#get xml notif config -$WAUinstalledPath = Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate\" -Name InstallLocation -[xml]$NotifConf = Get-Content "$WAUinstalledPath\config\notif.xml" -Encoding UTF8 -ErrorAction SilentlyContinue -if (!($NotifConf)) { - break +# get xml notif config +$WAUinstalledPath = (Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate\' -Name InstallLocation) +[xml]$NotifConf = (Get-Content -Path "$WAUinstalledPath\config\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 +# Load Assemblies +$null = (Add-Type -AssemblyName Windows.Data) +$null = (Add-Type -AssemblyName Windows.UI) -#Prepare XML +$null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] +$null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] + +# Prepare XML $ToastXml = [Windows.Data.Xml.Dom.XmlDocument]::New() $ToastXml.LoadXml($NotifConf.OuterXml) -#Specify Launcher App ID -$LauncherID = "Windows.SystemToast.Winget.Notification" +# Specify Launcher App ID +$LauncherID = 'Windows.SystemToast.Winget.Notification' -#Prepare and Create Toast -$ToastMessage = [Windows.UI.Notifications.ToastNotification]::New($ToastXML) +# Prepare and Create Toast +$ToastMessage = [Windows.UI.Notifications.ToastNotification]::New($ToastXml) $ToastMessage.Tag = $NotifConf.toast.tag [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($LauncherID).Show($ToastMessage) diff --git a/Winget-AutoUpdate/Winget-Upgrade.ps1 b/Winget-AutoUpdate/Winget-Upgrade.ps1 index 25cfbc7..72af605 100644 --- a/Winget-AutoUpdate/Winget-Upgrade.ps1 +++ b/Winget-AutoUpdate/Winget-Upgrade.ps1 @@ -1,345 +1,419 @@ <# LOAD FUNCTIONS #> -#Get the Working Dir +# Get the Working Dir $Script:WorkingDir = $PSScriptRoot -#Get Functions -Get-ChildItem "$WorkingDir\functions" | ForEach-Object { . $_.FullName } +# Get Functions +Get-ChildItem -Path "$WorkingDir\functions" | ForEach-Object { + . $_.FullName +} <# MAIN #> -#Check if running account is system or interactive logon -$Script:IsSystem = [System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem +# Check if running account is system or interactive logon +$Script:IsSystem = [Security.Principal.WindowsIdentity]::GetCurrent().IsSystem -#Run log initialisation function +# Run log initialisation function Start-Init -#Get WAU Configurations -$Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" +# Get WAU Configurations +$Script:WAUConfig = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate') #Log running context and more... -if ($IsSystem) { - Write-ToLog "Running in System context" +if ($IsSystem) +{ + Write-ToLog 'Running in System context' - #Get and set Domain/Local Policies (GPO) - $ActivateGPOManagement, $ChangedSettings = Get-Policies - if ($ActivateGPOManagement) { - Write-ToLog "Activated WAU GPO Management detected, comparing..." - if ($null -ne $ChangedSettings -and $ChangedSettings -ne 0) { - Write-ToLog "Changed settings detected and applied" "Yellow" - } - else { - Write-ToLog "No Changed settings detected" "Yellow" - } - } + #Get and set Domain/Local Policies (GPO) + $ActivateGPOManagement, $ChangedSettings = Get-Policies + if ($ActivateGPOManagement) + { + Write-ToLog 'Activated WAU GPO Management detected, comparing...' + if ($null -ne $ChangedSettings -and $ChangedSettings -ne 0) + { + Write-ToLog 'Changed settings detected and applied' 'Yellow' + } + else + { + Write-ToLog 'No Changed settings detected' 'Yellow' + } + } - # Maximum number of log files to keep. Default is 3. Setting MaxLogFiles to 0 will keep all log files. - $MaxLogFiles = $WAUConfig.WAU_MaxLogFiles - if ($null -eq $MaxLogFiles) { - [int32] $MaxLogFiles = 3 - } - else { - [int32] $MaxLogFiles = $MaxLogFiles - } + # Maximum number of log files to keep. Default is 3. Setting MaxLogFiles to 0 will keep all log files. + $MaxLogFiles = $WAUConfig.WAU_MaxLogFiles + if ($null -eq $MaxLogFiles) + { + [int]$MaxLogFiles = 3 + } + else + { + [int]$MaxLogFiles = $MaxLogFiles + } - # Maximum size of log file. - $MaxLogSize = $WAUConfig.WAU_MaxLogSize - if (!$MaxLogSize) { - [int64] $MaxLogSize = 1048576 # in bytes, default is 1048576 = 1 MB - } - else { - [int64] $MaxLogSize = $MaxLogSize - } + # Maximum size of log file. + $MaxLogSize = $WAUConfig.WAU_MaxLogSize + if (!$MaxLogSize) + { + [long]$MaxLogSize = 1048576 # in bytes, default is 1048576 = 1 MB + } + else + { + [long]$MaxLogSize = $MaxLogSize + } - #LogRotation if System - $LogRotate = Invoke-LogRotation $LogFile $MaxLogFiles $MaxLogSize - if ($LogRotate -eq $False) { - Write-ToLog "An Exception occured during Log Rotation..." - } + #LogRotation if System + $LogRotate = Invoke-LogRotation $LogFile $MaxLogFiles $MaxLogSize + if ($LogRotate -eq $False) + { + Write-ToLog 'An Exception occured during Log Rotation...' + } - #Run post update actions if necessary if run as System - if (!($WAUConfig.WAU_PostUpdateActions -eq 0)) { - Invoke-PostUpdateActions - } - #Run Scope Machine funtion if run as System - $SettingsPath = "$Env:windir\system32\config\systemprofile\AppData\Local\Microsoft\WinGet\Settings\defaultState\settings.json" - Add-ScopeMachine $SettingsPath + #Run post update actions if necessary if run as System + if (!($WAUConfig.WAU_PostUpdateActions -eq 0)) + { + Invoke-PostUpdateActions + } + #Run Scope Machine funtion if run as System + $SettingsPath = "$Env:windir\system32\config\systemprofile\AppData\Local\Microsoft\WinGet\Settings\defaultState\settings.json" + Add-ScopeMachine $SettingsPath } -else { - Write-ToLog "Running in User context" +else +{ + Write-ToLog 'Running in User context' } #Get Notif Locale function $LocaleDisplayName = Get-NotifLocale -Write-ToLog "Notification Level: $($WAUConfig.WAU_NotificationLevel). Notification Language: $LocaleDisplayName" "Cyan" +Write-ToLog "Notification Level: $($WAUConfig.WAU_NotificationLevel). Notification Language: $LocaleDisplayName" 'Cyan' #Check network connectivity -if (Test-Network) { - #Check if Winget is installed and get Winget cmd - $TestWinget = Get-WingetCmd +if (Test-Network) +{ + #Check if Winget is installed and get Winget cmd + $TestWinget = Get-WingetCmd - if ($TestWinget) { - #Get Current Version - $WAUCurrentVersion = $WAUConfig.DisplayVersion - Write-ToLog "WAU current version: $WAUCurrentVersion" - if ($IsSystem) { - #Check if WAU update feature is enabled or not if run as System - $WAUDisableAutoUpdate = $WAUConfig.WAU_DisableAutoUpdate - #If yes then check WAU update if run as System - if ($WAUDisableAutoUpdate -eq 1) { - Write-ToLog "WAU AutoUpdate is Disabled." "Gray" + if ($TestWinget) + { + #Get Current Version + $WAUCurrentVersion = $WAUConfig.DisplayVersion + Write-ToLog "WAU current version: $WAUCurrentVersion" + if ($IsSystem) + { + #Check if WAU update feature is enabled or not if run as System + $WAUDisableAutoUpdate = $WAUConfig.WAU_DisableAutoUpdate + #If yes then check WAU update if run as System + if ($WAUDisableAutoUpdate -eq 1) + { + Write-ToLog 'WAU AutoUpdate is Disabled.' 'Gray' + } + else + { + Write-ToLog 'WAU AutoUpdate is Enabled.' 'Green' + #Get Available Version + $Script:WAUAvailableVersion = Get-WAUAvailableVersion + #Compare + if ([version]$WAUAvailableVersion.Replace('-', '.') -ne [version]$WAUCurrentVersion.Replace('-', '.')) + { + #If new version is available, update it + Write-ToLog "WAU Available version: $WAUAvailableVersion" 'Yellow' + Update-WAU } - else { - Write-ToLog "WAU AutoUpdate is Enabled." "Green" - #Get Available Version - $Script:WAUAvailableVersion = Get-WAUAvailableVersion - #Compare - if ([version]$WAUAvailableVersion.Replace("-", ".") -ne [version]$WAUCurrentVersion.Replace("-", ".")) { - #If new version is available, update it - Write-ToLog "WAU Available version: $WAUAvailableVersion" "Yellow" - Update-WAU - } - else { - Write-ToLog "WAU is up to date." "Green" - } + else + { + Write-ToLog 'WAU is up to date.' 'Green' } + } - #Delete previous list_/winget_error (if they exist) if run as System - if (Test-Path "$WorkingDir\logs\error.txt") { - Remove-Item "$WorkingDir\logs\error.txt" -Force + #Delete previous list_/winget_error (if they exist) if run as System + if (Test-Path -Path "$WorkingDir\logs\error.txt") + { + Remove-Item -Path "$WorkingDir\logs\error.txt" -Force + } + + #Get External ListPath if run as System + if ($WAUConfig.WAU_ListPath) + { + $ListPathClean = $($WAUConfig.WAU_ListPath.TrimEnd(' ', '\', '/')) + Write-ToLog "WAU uses External Lists from: $ListPathClean" + if ($ListPathClean -ne 'GPO') + { + $NewList = Test-ListPath $ListPathClean $WAUConfig.WAU_UseWhiteList $WAUConfig.InstallLocation.TrimEnd(' ', '\') + if ($ReachNoPath) + { + Write-ToLog "Couldn't reach/find/compare/copy from $ListPathClean..." 'Red' + if ($ListPathClean -notlike 'http*') + { + if (Test-Path -Path "$ListPathClean" -PathType Leaf) + { + Write-ToLog 'PATH must end with a Directory, not a File...' 'Red' + } + } + else + { + if ($ListPathClean -match '_apps.txt') + { + Write-ToLog 'PATH must end with a Directory, not a File...' 'Red' + } + } + $Script:ReachNoPath = $False + } + if ($NewList) + { + Write-ToLog "Newer List downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(' ', '\'))" 'Yellow' + } + else + { + if ($WAUConfig.WAU_UseWhiteList -and (Test-Path -Path "$WorkingDir\included_apps.txt")) + { + Write-ToLog 'List (white) is up to date.' 'Green' + } + elseif (!$WAUConfig.WAU_UseWhiteList -and (Test-Path -Path "$WorkingDir\excluded_apps.txt")) + { + Write-ToLog 'List (black) is up to date.' 'Green' + } + else + { + Write-ToLog "Critical: White/Black List doesn't exist, exiting..." 'Red' + New-Item -Path "$WorkingDir\logs\error.txt" -Value "White/Black List doesn't exist" -Force + exit 1 + } + } } + } - #Get External ListPath if run as System - if ($WAUConfig.WAU_ListPath) { - $ListPathClean = $($WAUConfig.WAU_ListPath.TrimEnd(" ", "\", "/")) - Write-ToLog "WAU uses External Lists from: $ListPathClean" - if ($ListPathClean -ne "GPO") { - $NewList = Test-ListPath $ListPathClean $WAUConfig.WAU_UseWhiteList $WAUConfig.InstallLocation.TrimEnd(" ", "\") - if ($ReachNoPath) { - Write-ToLog "Couldn't reach/find/compare/copy from $ListPathClean..." "Red" - if ($ListPathClean -notlike "http*") { - if (Test-Path -Path "$ListPathClean" -PathType Leaf) { - Write-ToLog "PATH must end with a Directory, not a File..." "Red" - } - } - else { - if ($ListPathClean -match "_apps.txt") { - Write-ToLog "PATH must end with a Directory, not a File..." "Red" - } - } - $Script:ReachNoPath = $False - } - if ($NewList) { - Write-ToLog "Newer List downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))" "Yellow" - } - else { - if ($WAUConfig.WAU_UseWhiteList -and (Test-Path "$WorkingDir\included_apps.txt")) { - Write-ToLog "List (white) is up to date." "Green" - } - elseif (!$WAUConfig.WAU_UseWhiteList -and (Test-Path "$WorkingDir\excluded_apps.txt")) { - Write-ToLog "List (black) is up to date." "Green" - } - else { - Write-ToLog "Critical: White/Black List doesn't exist, exiting..." "Red" - New-Item "$WorkingDir\logs\error.txt" -Value "White/Black List doesn't exist" -Force - Exit 1 - } - } - } + #Get External ModsPath if run as System + if ($WAUConfig.WAU_ModsPath) + { + $ModsPathClean = $($WAUConfig.WAU_ModsPath.TrimEnd(' ', '\', '/')) + Write-ToLog "WAU uses External Mods from: $ModsPathClean" + if ($WAUConfig.WAU_AzureBlobSASURL) + { + $NewMods, $DeletedMods = Test-ModsPath $ModsPathClean $WAUConfig.InstallLocation.TrimEnd(' ', '\') $WAUConfig.WAU_AzureBlobSASURL.TrimEnd(' ') } - - #Get External ModsPath if run as System - if ($WAUConfig.WAU_ModsPath) { - $ModsPathClean = $($WAUConfig.WAU_ModsPath.TrimEnd(" ", "\", "/")) - Write-ToLog "WAU uses External Mods from: $ModsPathClean" - if ($WAUConfig.WAU_AzureBlobSASURL) { - $NewMods, $DeletedMods = Test-ModsPath $ModsPathClean $WAUConfig.InstallLocation.TrimEnd(" ", "\") $WAUConfig.WAU_AzureBlobSASURL.TrimEnd(" ") - } - else { - $NewMods, $DeletedMods = Test-ModsPath $ModsPathClean $WAUConfig.InstallLocation.TrimEnd(" ", "\") - } - if ($ReachNoPath) { - Write-ToLog "Couldn't reach/find/compare/copy from $ModsPathClean..." "Red" - $Script:ReachNoPath = $False - } - if ($NewMods -gt 0) { - Write-ToLog "$NewMods newer Mods downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))\mods" "Yellow" - } - else { - if (Test-Path "$WorkingDir\mods\*.ps1") { - Write-ToLog "Mods are up to date." "Green" - } - else { - Write-ToLog "No Mods are implemented..." "Yellow" - } - } - if ($DeletedMods -gt 0) { - Write-ToLog "$DeletedMods Mods deleted (not externally managed) from local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))\mods" "Red" - } + else + { + $NewMods, $DeletedMods = Test-ModsPath $ModsPathClean $WAUConfig.InstallLocation.TrimEnd(' ', '\') } - - #Test if _WAU-mods.ps1 exist: Mods for WAU (if Network is active/any Winget is installed/running as SYSTEM) - $Mods = "$WorkingDir\mods" - if (Test-Path "$Mods\_WAU-mods.ps1") { - Write-ToLog "Running Mods for WAU..." "Yellow" - & "$Mods\_WAU-mods.ps1" - $ModsExitCode = $LASTEXITCODE - #If _WAU-mods.ps1 has ExitCode 1 - Re-run WAU - if ($ModsExitCode -eq 1) { - Write-ToLog "Re-run WAU" - Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command `"$WorkingDir\winget-upgrade.ps1`"" - Exit - } + if ($ReachNoPath) + { + Write-ToLog "Couldn't reach/find/compare/copy from $ModsPathClean..." 'Red' + $Script:ReachNoPath = $False } - - } - - if ($($WAUConfig.WAU_ListPath) -eq "GPO") { - $Script:GPOList = $True - } - - #Get White or Black list - if ($WAUConfig.WAU_UseWhiteList -eq 1) { - Write-ToLog "WAU uses White List config" - $toUpdate = Get-IncludedApps - $UseWhiteList = $true - } - else { - Write-ToLog "WAU uses Black List config" - $toSkip = Get-ExcludedApps - } - - #Fix and count the array if GPO List as ERROR handling! - if ($GPOList) { - if ($UseWhiteList) { - $WhiteList = $toUpdate.GetUpperBound(0) - if ($null -eq $WhiteList) { - Write-ToLog "Critical: Whitelist doesn't exist in GPO, exiting..." "Red" - New-Item "$WorkingDir\logs\error.txt" -Value "Whitelist doesn't exist in GPO" -Force - Exit 1 - } - $toUpdate = $toUpdate.Data + if ($NewMods -gt 0) + { + Write-ToLog "$NewMods newer Mods downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(' ', '\'))\mods" 'Yellow' } - else { - $BlackList = $toSkip.GetUpperBound(0) - if ($null -eq $BlackList) { - Write-ToLog "Critical: Blacklist doesn't exist in GPO, exiting..." "Red" - New-Item "$WorkingDir\logs\error.txt" -Value "Blacklist doesn't exist in GPO" -Force - Exit 1 - } - $toSkip = $toSkip.Data + else + { + if (Test-Path -Path "$WorkingDir\mods\*.ps1") + { + Write-ToLog 'Mods are up to date.' 'Green' + } + else + { + Write-ToLog 'No Mods are implemented...' 'Yellow' + } } - } - - #Get outdated Winget packages - Write-ToLog "Checking application updates on Winget Repository..." "yellow" - $outdated = Get-WingetOutdatedApps - - #If something unusual happened - if ($outdated -like "An unusual*") { - Write-ToLog "$outdated" "cyan" - $outdated = $False - } - - #Run only if $outdated is populated! - if ($outdated) { - #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 + if ($DeletedMods -gt 0) + { + Write-ToLog "$DeletedMods Mods deleted (not externally managed) from local path: $($WAUConfig.InstallLocation.TrimEnd(' ', '\'))\mods" 'Red' } + } - #Count good update installations - $Script:InstallOK = 0 - - #Trick under user context when -BypassListForUsers is used - if ($IsSystem -eq $false -and $WAUConfig.WAU_BypassListForUsers -eq 1) { - Write-ToLog "Bypass system list in user context is Enabled." - $UseWhiteList = $false - $toSkip = $null + #Test if _WAU-mods.ps1 exist: Mods for WAU (if Network is active/any Winget is installed/running as SYSTEM) + $Mods = "$WorkingDir\mods" + if (Test-Path -Path "$Mods\_WAU-mods.ps1") + { + Write-ToLog 'Running Mods for WAU...' 'Yellow' + & "$Mods\_WAU-mods.ps1" + $ModsExitCode = $LASTEXITCODE + #If _WAU-mods.ps1 has ExitCode 1 - Re-run WAU + if ($ModsExitCode -eq 1) + { + Write-ToLog 'Re-run WAU' + Start-Process -FilePath powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command `"$WorkingDir\winget-upgrade.ps1`"" + exit } + } - #If White List - if ($UseWhiteList) { - #For each app, notify and update - foreach ($app in $outdated) { - if (($toUpdate -contains $app.Id) -and $($app.Version) -ne "Unknown") { - Update-App $app - } - #if current app version is unknown - elseif ($($app.Version) -eq "Unknown") { - Write-ToLog "$($app.Name) : Skipped upgrade because current version is 'Unknown'" "Gray" - } - #if app is in "excluded list" - else { - Write-ToLog "$($app.Name) : Skipped upgrade because it is not in the included app list" "Gray" - } - } + } + + if ($($WAUConfig.WAU_ListPath) -eq 'GPO') + { + $Script:GPOList = $True + } + + #Get White or Black list + if ($WAUConfig.WAU_UseWhiteList -eq 1) + { + Write-ToLog 'WAU uses White List config' + $toUpdate = Get-IncludedApps + $UseWhiteList = $true + } + else + { + Write-ToLog 'WAU uses Black List config' + $toSkip = Get-ExcludedApps + } + + #Fix and count the array if GPO List as ERROR handling! + if ($GPOList) + { + if ($UseWhiteList) + { + $WhiteList = $toUpdate.GetUpperBound(0) + if ($null -eq $WhiteList) + { + Write-ToLog "Critical: Whitelist doesn't exist in GPO, exiting..." 'Red' + New-Item -Path "$WorkingDir\logs\error.txt" -Value "Whitelist doesn't exist in GPO" -Force + exit 1 } - #If Black List or default - else { - #For each app, notify and update - foreach ($app in $outdated) { - if (-not ($toSkip -contains $app.Id) -and $($app.Version) -ne "Unknown") { - Update-App $app - } - #if current app version is unknown - elseif ($($app.Version) -eq "Unknown") { - Write-ToLog "$($app.Name) : Skipped upgrade because current version is 'Unknown'" "Gray" - } - #if app is in "excluded list" - else { - Write-ToLog "$($app.Name) : Skipped upgrade because it is in the excluded app list" "Gray" - } - } + $toUpdate = $toUpdate.Data + } + else + { + $BlackList = $toSkip.GetUpperBound(0) + if ($null -eq $BlackList) + { + Write-ToLog "Critical: Blacklist doesn't exist in GPO, exiting..." 'Red' + New-Item -Path "$WorkingDir\logs\error.txt" -Value "Blacklist doesn't exist in GPO" -Force + exit 1 } + $toSkip = $toSkip.Data + } + } - if ($InstallOK -gt 0) { - Write-ToLog "$InstallOK apps updated ! No more update." "Green" + #Get outdated Winget packages + Write-ToLog 'Checking application updates on Winget Repository...' 'yellow' + $outdated = Get-WingetOutdatedApps + + #If something unusual happened + if ($outdated -like 'An unusual*') + { + Write-ToLog "$outdated" 'cyan' + $outdated = $False + } + + #Run only if $outdated is populated! + if ($outdated) + { + #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 installations + $Script:InstallOK = 0 + + #Trick under user context when -BypassListForUsers is used + if ($IsSystem -eq $false -and $WAUConfig.WAU_BypassListForUsers -eq 1) + { + Write-ToLog 'Bypass system list in user context is Enabled.' + $UseWhiteList = $false + $toSkip = $null + } + + #If White List + if ($UseWhiteList) + { + #For each app, notify and update + foreach ($app in $outdated) + { + if (($toUpdate -contains $app.Id) -and $($app.Version) -ne 'Unknown') + { + Update-App $app + } + #if current app version is unknown + elseif ($($app.Version) -eq 'Unknown') + { + Write-ToLog "$($app.Name) : Skipped upgrade because current version is 'Unknown'" 'Gray' + } + #if app is in "excluded list" + else + { + Write-ToLog "$($app.Name) : Skipped upgrade because it is not in the included app list" 'Gray' + } } - } - - if ($InstallOK -eq 0 -or !$InstallOK) { - Write-ToLog "No new update." "Green" - } - - #Check if any user is logged on if System and run User task (if installed) - if ($IsSystem) { - #User check routine from: https://stackoverflow.com/questions/23219718/powershell-script-to-see-currently-logged-in-users-domain-and-machine-status - $explorerprocesses = @(Get-WmiObject -Query "Select * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue) - If ($explorerprocesses.Count -eq 0) { - Write-ToLog "No explorer process found / Nobody interactively logged on..." + } + #If Black List or default + else + { + #For each app, notify and update + foreach ($app in $outdated) + { + if (-not ($toSkip -contains $app.Id) -and $($app.Version) -ne 'Unknown') + { + Update-App $app + } + #if current app version is unknown + elseif ($($app.Version) -eq 'Unknown') + { + Write-ToLog "$($app.Name) : Skipped upgrade because current version is 'Unknown'" 'Gray' + } + #if app is in "excluded list" + else + { + Write-ToLog "$($app.Name) : Skipped upgrade because it is in the excluded app list" 'Gray' + } } - Else { - #Run WAU in user context if the user task exist - $UserScheduledTask = Get-ScheduledTask -TaskName "Winget-AutoUpdate-UserContext" -ErrorAction SilentlyContinue - if ($UserScheduledTask) { + } - #Get Winget system apps to excape them befor running user context - Write-ToLog "User logged on, get a list of installed Winget apps in System context..." - Get-WingetSystemApps + if ($InstallOK -gt 0) + { + Write-ToLog "$InstallOK apps updated ! No more update." 'Green' + } + } - #Run user context scheduled task - Write-ToLog "Starting WAU in User context" - Start-ScheduledTask $UserScheduledTask.TaskName -ErrorAction SilentlyContinue - Exit 0 - } - elseif (!$UserScheduledTask) { - Write-ToLog "User context execution not installed..." - } + if ($InstallOK -eq 0 -or !$InstallOK) + { + Write-ToLog 'No new update.' 'Green' + } + + #Check if any user is logged on if System and run User task (if installed) + if ($IsSystem) + { + #User check routine from: https://stackoverflow.com/questions/23219718/powershell-script-to-see-currently-logged-in-users-domain-and-machine-status + $explorerprocesses = @(Get-WmiObject -Query "Select * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue) + if ($explorerprocesses.Count -eq 0) + { + Write-ToLog 'No explorer process found / Nobody interactively logged on...' + } + else + { + #Run WAU in user context if the user task exist + $UserScheduledTask = Get-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -ErrorAction SilentlyContinue + if ($UserScheduledTask) + { + + #Get Winget system apps to excape them befor running user context + Write-ToLog 'User logged on, get a list of installed Winget apps in System context...' + Get-WingetSystemApps + + #Run user context scheduled task + Write-ToLog 'Starting WAU in User context' + Start-ScheduledTask -TaskName $UserScheduledTask.TaskName -ErrorAction SilentlyContinue + exit 0 } - } - } - else { - Write-ToLog "Critical: Winget not installed or detected, exiting..." "red" - New-Item "$WorkingDir\logs\error.txt" -Value "Winget not installed or detected" -Force - Write-ToLog "End of process!" "Cyan" - Exit 1 - } + elseif (!$UserScheduledTask) + { + Write-ToLog 'User context execution not installed...' + } + } + } + } + else + { + Write-ToLog 'Critical: Winget not installed or detected, exiting...' 'red' + New-Item -Path "$WorkingDir\logs\error.txt" -Value 'Winget not installed or detected' -Force + Write-ToLog 'End of process!' 'Cyan' + exit 1 + } } #End -Write-ToLog "End of process!" "Cyan" -Start-Sleep 3 +Write-ToLog 'End of process!' 'Cyan' +Start-Sleep -Seconds 3 diff --git a/Winget-AutoUpdate/functions/Add-ScopeMachine.ps1 b/Winget-AutoUpdate/functions/Add-ScopeMachine.ps1 index 44bb7e4..e0dcb72 100644 --- a/Winget-AutoUpdate/functions/Add-ScopeMachine.ps1 +++ b/Winget-AutoUpdate/functions/Add-ScopeMachine.ps1 @@ -1,20 +1,40 @@ -#Function to configure the prefered scope option as Machine -function Add-ScopeMachine ($SettingsPath) { +# Function to configure the prefered scope option as Machine +function Add-ScopeMachine +{ + [CmdletBinding()] + param + ( + [string] + $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 + if (Test-Path -Path $SettingsPath -ErrorAction SilentlyContinue) + { + $ConfigFile = (Get-Content -Path $SettingsPath -ErrorAction SilentlyContinue | Where-Object -FilterScript { + ($_ -notmatch '//') + } | ConvertFrom-Json) + } + if (!$ConfigFile) + { + $ConfigFile = @{ + } + } + + if ($ConfigFile.installBehavior.preferences.scope) + { + $ConfigFile.installBehavior.preferences.scope = 'Machine' + } + else + { + $Scope = (New-Object -TypeName PSObject -Property $(@{ + scope = 'Machine' + })) + $Preference = (New-Object -TypeName PSObject -Property $(@{ + preferences = $Scope + })) + $null = (Add-Member -InputObject $ConfigFile -MemberType NoteProperty -Name 'installBehavior' -Value $Preference -Force) + } + + $null = ($ConfigFile | ConvertTo-Json | Out-File -FilePath $SettingsPath -Encoding utf8 -Force -Confirm:$false) } diff --git a/Winget-AutoUpdate/functions/Add-Shortcut.ps1 b/Winget-AutoUpdate/functions/Add-Shortcut.ps1 index 98b6e77..0ab9e23 100644 --- a/Winget-AutoUpdate/functions/Add-Shortcut.ps1 +++ b/Winget-AutoUpdate/functions/Add-Shortcut.ps1 @@ -1,10 +1,26 @@ -#Function to create shortcuts -function Add-Shortcut ($Target, $Shortcut, $Arguments, $Icon, $Description) { - $WScriptShell = New-Object -ComObject WScript.Shell - $Shortcut = $WScriptShell.CreateShortcut($Shortcut) - $Shortcut.TargetPath = $Target - $Shortcut.Arguments = $Arguments - $Shortcut.IconLocation = $Icon - $Shortcut.Description = $Description - $Shortcut.Save() +# Function to create shortcuts +function Add-Shortcut +{ + [CmdletBinding()] + param + ( + [string] + $Target, + [string] + $Shortcut, + [string] + $Arguments, + [string] + $Icon, + [string] + $Description + ) + + $WScriptShell = (New-Object -ComObject WScript.Shell) + $Shortcut = $WScriptShell.CreateShortcut($Shortcut) + $Shortcut.TargetPath = $Target + $Shortcut.Arguments = $Arguments + $Shortcut.IconLocation = $Icon + $Shortcut.Description = $Description + $Shortcut.Save() } diff --git a/Winget-AutoUpdate/functions/Confirm-Installation.ps1 b/Winget-AutoUpdate/functions/Confirm-Installation.ps1 index e96b66d..db7100c 100644 --- a/Winget-AutoUpdate/functions/Confirm-Installation.ps1 +++ b/Winget-AutoUpdate/functions/Confirm-Installation.ps1 @@ -1,27 +1,41 @@ -Function Confirm-Installation ($AppName, $AppVer){ +function Confirm-Installation +{ + # Set json export file - #Set json export file - $JsonFile = "$WorkingDir\Config\InstalledApps.json" + [CmdletBinding()] + param + ( + [string] + $AppName, + [string] + $AppVer + ) - #Get installed apps and version in json file - & $Winget export -s winget -o $JsonFile --include-versions | Out-Null + $JsonFile = ('{0}\Config\InstalledApps.json' -f $WorkingDir) - #Get json content - $Json = Get-Content $JsonFile -Raw | ConvertFrom-Json + # Get installed apps and version in json file + $null = (& $Winget export -s winget -o $JsonFile --include-versions) - #Get apps and version in hashtable - $Packages = $Json.Sources.Packages + # Get json content + $Json = (Get-Content -Path $JsonFile -Raw | ConvertFrom-Json) - #Remove json file - Remove-Item $JsonFile -Force + # Get apps and version in hashtable + $Packages = $Json.Sources.Packages - # Search for specific app and version - $Apps = $Packages | Where-Object { $_.PackageIdentifier -eq $AppName -and $_.Version -like "$AppVer*"} + # Remove json file + $null = (Remove-Item -Path $JsonFile -Force -Confirm:$false -ErrorAction SilentlyContinue) - if ($Apps){ - return $true - } - else{ - return $false - } -} \ No newline at end of file + # Search for specific app and version + $Apps = $Packages | Where-Object -FilterScript { + ($_.PackageIdentifier -eq $AppName -and $_.Version -like ('{0}*' -f $AppVer)) + } + + if ($Apps) + { + return $true + } + else + { + return $false + } +} diff --git a/Winget-AutoUpdate/functions/Get-AZCopy.ps1 b/Winget-AutoUpdate/functions/Get-AZCopy.ps1 index e6f7d54..eddcec8 100644 --- a/Winget-AutoUpdate/functions/Get-AZCopy.ps1 +++ b/Winget-AutoUpdate/functions/Get-AZCopy.ps1 @@ -1,50 +1,59 @@ -#Function to get AZCopy, if it doesn't exist and update it, if it does +# Function to get AZCopy, if it doesn't exist and update it, if it does -Function Get-AZCopy ($WingetUpdatePath) { +function Get-AZCopy +{ + [CmdletBinding()] + param + ( + [string] + $WingetUpdatePath + ) - $AZCopyLink = (Invoke-WebRequest -Uri https://aka.ms/downloadazcopy-v10-windows -UseBasicParsing -MaximumRedirection 0 -ErrorAction SilentlyContinue).headers.location - $AZCopyVersionRegex = [regex]::new("(\d+\.\d+\.\d+)") - $AZCopyLatestVersion = $AZCopyVersionRegex.Match($AZCopyLink).Value + $AZCopyLink = (Invoke-WebRequest -Uri https://aka.ms/downloadazcopy-v10-windows -UseBasicParsing -MaximumRedirection 0 -ErrorAction SilentlyContinue).headers.location + $AZCopyVersionRegex = [regex]::new('(\d+\.\d+\.\d+)') + $AZCopyLatestVersion = $AZCopyVersionRegex.Match($AZCopyLink).Value - if ($null -eq $AZCopyLatestVersion -or "" -eq $AZCopyLatestVersion) { - $AZCopyLatestVersion = "0.0.0" - } + if ($null -eq $AZCopyLatestVersion -or '' -eq $AZCopyLatestVersion) + { + $AZCopyLatestVersion = '0.0.0' + } - if (Test-Path -Path "$WingetUpdatePath\azcopy.exe" -PathType Leaf) { - $AZCopyCurrentVersion = & "$WingetUpdatePath\azcopy.exe" -v - $AZCopyCurrentVersion = $AZCopyVersionRegex.Match($AZCopyCurrentVersion).Value - Write-ToLog "AZCopy version $AZCopyCurrentVersion found" - } - else { - Write-ToLog "AZCopy not already installed" - $AZCopyCurrentVersion = "0.0.0" - } + if (Test-Path -Path ('{0}\azcopy.exe' -f $WingetUpdatePath) -PathType Leaf -ErrorAction SilentlyContinue) + { + $AZCopyCurrentVersion = & "$WingetUpdatePath\azcopy.exe" -v + $AZCopyCurrentVersion = $AZCopyVersionRegex.Match($AZCopyCurrentVersion).Value + Write-ToLog -LogMsg ('AZCopy version {0} found' -f $AZCopyCurrentVersion) + } + else + { + Write-ToLog -LogMsg 'AZCopy not already installed' + $AZCopyCurrentVersion = '0.0.0' + } - if (([version] $AZCopyCurrentVersion) -lt ([version] $AZCopyLatestVersion)) { - Write-ToLog "Installing version $AZCopyLatestVersion of AZCopy" - Invoke-WebRequest -Uri $AZCopyLink -UseBasicParsing -OutFile "$WingetUpdatePath\azcopyv10.zip" - Write-ToLog "Extracting AZCopy zip file" + if (([version]$AZCopyCurrentVersion) -lt ([version]$AZCopyLatestVersion)) + { + Write-ToLog -LogMsg ('Installing version {0} of AZCopy' -f $AZCopyLatestVersion) + $null = (Invoke-WebRequest -Uri $AZCopyLink -UseBasicParsing -OutFile ('{0}\azcopyv10.zip' -f $WingetUpdatePath)) + Write-ToLog -LogMsg 'Extracting AZCopy zip file' + $null = (Expand-Archive -Path ('{0}\azcopyv10.zip' -f $WingetUpdatePath) -DestinationPath $WingetUpdatePath -Force -Confirm:$false) + $AZCopyPathSearch = (Resolve-Path -Path ('{0}\azcopy_*' -f $WingetUpdatePath)) - Expand-archive -Path "$WingetUpdatePath\azcopyv10.zip" -Destinationpath "$WingetUpdatePath" -Force + if ($AZCopyPathSearch -is [array]) + { + $AZCopyEXEPath = $AZCopyPathSearch[$AZCopyPathSearch.Length - 1] + } + else + { + $AZCopyEXEPath = $AZCopyPathSearch + } - $AZCopyPathSearch = Resolve-Path -path "$WingetUpdatePath\azcopy_*" - - if ($AZCopyPathSearch -is [array]) { - $AZCopyEXEPath = $AZCopyPathSearch[$AZCopyPathSearch.Length - 1] - } - else { - $AZCopyEXEPath = $AZCopyPathSearch - } - - Write-ToLog "Copying 'azcopy.exe' to main folder" - Copy-Item "$AZCopyEXEPath\azcopy.exe" -Destination "$WingetUpdatePath\" - - Write-ToLog "Removing temporary AZCopy files" - Remove-Item -Path $AZCopyEXEPath -Recurse - Remove-Item -Path "$WingetUpdatePath\azcopyv10.zip" - - $AZCopyCurrentVersion = & "$WingetUpdatePath\azcopy.exe" -v - $AZCopyCurrentVersion = $AZCopyVersionRegex.Match($AZCopyCurrentVersion).Value - Write-ToLog "AZCopy version $AZCopyCurrentVersion installed" - } -} \ No newline at end of file + Write-ToLog -LogMsg "Copying 'azcopy.exe' to main folder" + $null = (Copy-Item -Path ('{0}\azcopy.exe' -f $AZCopyEXEPath) -Destination ('{0}\' -f $WingetUpdatePath) -Force -Confirm:$false) + Write-ToLog -LogMsg 'Removing temporary AZCopy files' + $null = (Remove-Item -Path $AZCopyEXEPath -Recurse -Force -Confirm:$false) + $null = (Remove-Item -Path ('{0}\azcopyv10.zip' -f $WingetUpdatePath) -Force -Confirm:$false) + $AZCopyCurrentVersion = & "$WingetUpdatePath\azcopy.exe" -v + $AZCopyCurrentVersion = $AZCopyVersionRegex.Match($AZCopyCurrentVersion).Value + Write-ToLog -LogMsg ('AZCopy version {0} installed' -f $AZCopyCurrentVersion) + } +} diff --git a/Winget-AutoUpdate/functions/Get-AppInfo.ps1 b/Winget-AutoUpdate/functions/Get-AppInfo.ps1 index 747a818..57b50e4 100644 --- a/Winget-AutoUpdate/functions/Get-AppInfo.ps1 +++ b/Winget-AutoUpdate/functions/Get-AppInfo.ps1 @@ -1,12 +1,19 @@ -#Get the winget App Information +# Get the winget App Information -Function Get-AppInfo ($AppID) { - #Get AppID Info - $String = & $winget show $AppID --accept-source-agreements -s winget | Out-String +function Get-AppInfo +{ + # Get AppID Info + [CmdletBinding()] + param + ( + [string] + $AppID + ) - #Search for Release Note info - $ReleaseNote = [regex]::match($String, "(?<=Release Notes Url: )(.*)(?=\n)").Groups[0].Value + $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 + # Return Release Note + return $ReleaseNote } diff --git a/Winget-AutoUpdate/functions/Get-ExcludedApps.ps1 b/Winget-AutoUpdate/functions/Get-ExcludedApps.ps1 index 0212e5c..3ac689a 100644 --- a/Winget-AutoUpdate/functions/Get-ExcludedApps.ps1 +++ b/Winget-AutoUpdate/functions/Get-ExcludedApps.ps1 @@ -1,31 +1,31 @@ #Function to get the Block List apps -function Get-ExcludedApps { +function Get-ExcludedApps +{ + if ($GPOList) + { + if (Test-Path -Path 'HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\BlackList' -ErrorAction SilentlyContinue) + { + $Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\BlackList\' - if ($GPOList) { + $ValueNames = (Get-Item -Path 'HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\BlackList').Property - if (Test-Path "HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\BlackList") { - - $Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\BlackList\' - - $ValueNames = (Get-Item -Path "HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\BlackList").Property - - foreach ($ValueName in $ValueNames) { - $AppIDs = [Microsoft.Win32.Registry]::GetValue($Key, $ValueName, $false) - [PSCustomObject]@{ - Value = $ValueName - Data = $AppIDs.Trim() - } + foreach ($ValueName in $ValueNames) + { + $AppIDs = [Microsoft.Win32.Registry]::GetValue($Key, $ValueName, $false) + [PSCustomObject]@{ + Value = $ValueName + Data = $AppIDs.Trim() } + } + } - } - return $AppIDs - - } - elseif (Test-Path "$WorkingDir\excluded_apps.txt") { - - return (Get-Content -Path "$WorkingDir\excluded_apps.txt").Trim() | Where-Object { $_.length -gt 0 } - - } - + return $AppIDs + } + elseif (Test-Path -Path ('{0}\excluded_apps.txt' -f $WorkingDir) -ErrorAction SilentlyContinue) + { + return (Get-Content -Path ('{0}\excluded_apps.txt' -f $WorkingDir)).Trim() | Where-Object -FilterScript { + $_.length -gt 0 + } + } } diff --git a/Winget-AutoUpdate/functions/Get-IncludedApps.ps1 b/Winget-AutoUpdate/functions/Get-IncludedApps.ps1 index ae2a8ad..476944c 100644 --- a/Winget-AutoUpdate/functions/Get-IncludedApps.ps1 +++ b/Winget-AutoUpdate/functions/Get-IncludedApps.ps1 @@ -1,31 +1,30 @@ -#Function to get the allow List apps +# Function to get the allow List apps -function Get-IncludedApps { +function Get-IncludedApps +{ + if ($GPOList) + { + if (Test-Path -Path 'HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\WhiteList' -ErrorAction SilentlyContinue) + { + $Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\WhiteList\' + $ValueNames = (Get-Item -Path 'HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\WhiteList').Property - if ($GPOList) { - - if (Test-Path "HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\WhiteList") { - - $Key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\WhiteList\' - - $ValueNames = (Get-Item -Path "HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate\WhiteList").Property - - foreach ($ValueName in $ValueNames) { - $AppIDs = [Microsoft.Win32.Registry]::GetValue($Key, $ValueName, $false) - [PSCustomObject]@{ - Value = $ValueName - Data = $AppIDs.Trim() - } + foreach ($ValueName in $ValueNames) + { + $AppIDs = [Microsoft.Win32.Registry]::GetValue($Key, $ValueName, $false) + [PSCustomObject]@{ + Value = $ValueName + Data = $AppIDs.Trim() } + } + } - } - return $AppIDs - - } - elseif (Test-Path "$WorkingDir\included_apps.txt") { - - return (Get-Content -Path "$WorkingDir\included_apps.txt").Trim() | Where-Object { $_.length -gt 0 } - - } - + return $AppIDs + } + elseif (Test-Path -Path ('{0}\included_apps.txt' -f $WorkingDir) -ErrorAction SilentlyContinue) + { + return (Get-Content -Path ('{0}\included_apps.txt' -f $WorkingDir)).Trim() | Where-Object -FilterScript { + $_.length -gt 0 + } + } } diff --git a/Winget-AutoUpdate/functions/Get-NotifLocale.ps1 b/Winget-AutoUpdate/functions/Get-NotifLocale.ps1 index f0bd3a2..46147d6 100644 --- a/Winget-AutoUpdate/functions/Get-NotifLocale.ps1 +++ b/Winget-AutoUpdate/functions/Get-NotifLocale.ps1 @@ -1,28 +1,31 @@ #Function to get the locale file for notifications -Function Get-NotifLocale { +function Get-NotifLocale +{ - #Get OS locale - $OSLocale = (Get-UICulture).Parent + # Get OS locale + $OSLocale = (Get-UICulture).Parent - #Test if OS locale notif file exists - $TestOSLocalPath = "$WorkingDir\locale\$($OSLocale.Name).xml" + # Test if OS locale notif file exists + $TestOSLocalPath = ('{0}\locale\{1}.xml' -f $WorkingDir, $OSLocale.Name) - #Set OS Local if file exists - if (Test-Path $TestOSLocalPath) { - $LocaleDisplayName = $OSLocale.DisplayName - $LocaleFile = $TestOSLocalPath - } - #Set English if file doesn't exist - else { - $LocaleDisplayName = "English" - $LocaleFile = "$WorkingDir\locale\en.xml" - } + # Set OS Local if file exists + if (Test-Path -Path $TestOSLocalPath -ErrorAction SilentlyContinue) + { + $LocaleDisplayName = $OSLocale.DisplayName + $LocaleFile = $TestOSLocalPath + } + else + { + # Set English if file doesn't exist + $LocaleDisplayName = 'English' + $LocaleFile = ('{0}\locale\en.xml' -f $WorkingDir) + } - #Get locale XML file content - [xml]$Script:NotifLocale = Get-Content $LocaleFile -Encoding UTF8 -ErrorAction SilentlyContinue + # Get locale XML file content + [xml]$Script:NotifLocale = (Get-Content -Path $LocaleFile -Encoding UTF8 -ErrorAction SilentlyContinue) - #Rerturn langague display name - Return $LocaleDisplayName + # Rerturn langague display name + return $LocaleDisplayName } diff --git a/Winget-AutoUpdate/functions/Get-Policies.ps1 b/Winget-AutoUpdate/functions/Get-Policies.ps1 index 0200341..fd293fb 100644 --- a/Winget-AutoUpdate/functions/Get-Policies.ps1 +++ b/Winget-AutoUpdate/functions/Get-Policies.ps1 @@ -1,364 +1,471 @@ -#Function to get the Domain/Local Policies (GPO) +# Function to get the Domain/Local Policies (GPO) -Function Get-Policies { - #Get WAU Policies and set the Configurations Registry Accordingly - $WAUPolicies = Get-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate" -ErrorAction SilentlyContinue - if ($WAUPolicies) { - if ($($WAUPolicies.WAU_ActivateGPOManagement -eq 1)) { - $ChangedSettings = 0 - $regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" - if ($null -ne $($WAUPolicies.WAU_BypassListForUsers) -and ($($WAUPolicies.WAU_BypassListForUsers) -ne $($WAUConfig.WAU_BypassListForUsers))) { - New-ItemProperty $regPath -Name WAU_BypassListForUsers -Value $($WAUPolicies.WAU_BypassListForUsers) -PropertyType DWord -Force | Out-Null - $ChangedSettings++ +function Get-Policies +{ + # Get WAU Policies and set the Configurations Registry Accordingly + $WAUPolicies = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Romanitho\Winget-AutoUpdate' -ErrorAction SilentlyContinue) + + if ($WAUPolicies) + { + if ($($WAUPolicies.WAU_ActivateGPOManagement -eq 1)) + { + $ChangedSettings = 0 + $regPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate' + + if ($null -ne $($WAUPolicies.WAU_BypassListForUsers) -and ($($WAUPolicies.WAU_BypassListForUsers) -ne $($WAUConfig.WAU_BypassListForUsers))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_BypassListForUsers -Value $($WAUPolicies.WAU_BypassListForUsers) -PropertyType DWord -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_BypassListForUsers) -and ($($WAUConfig.WAU_BypassListForUsers) -or $($WAUConfig.WAU_BypassListForUsers) -eq 0)) + { + $null = (Remove-ItemProperty -Path $regPath -Name WAU_BypassListForUsers -Force -ErrorAction SilentlyContinue -Confirm:$false) + $ChangedSettings++ + } + + if ($null -ne $($WAUPolicies.WAU_DisableAutoUpdate) -and ($($WAUPolicies.WAU_DisableAutoUpdate) -ne $($WAUConfig.WAU_DisableAutoUpdate))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_DisableAutoUpdate -Value $($WAUPolicies.WAU_DisableAutoUpdate) -PropertyType DWord -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_DisableAutoUpdate) -and ($($WAUConfig.WAU_DisableAutoUpdate) -or $($WAUConfig.WAU_DisableAutoUpdate) -eq 0)) + { + $null = (Remove-ItemProperty -Path $regPath -Name WAU_DisableAutoUpdate -Force -ErrorAction SilentlyContinue -Confirm:$false) + $ChangedSettings++ + } + + if ($null -ne $($WAUPolicies.WAU_DoNotRunOnMetered) -and ($($WAUPolicies.WAU_DoNotRunOnMetered) -ne $($WAUConfig.WAU_DoNotRunOnMetered))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_DoNotRunOnMetered -Value $($WAUPolicies.WAU_DoNotRunOnMetered) -PropertyType DWord -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_DoNotRunOnMetered) -and !$($WAUConfig.WAU_DoNotRunOnMetered)) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_DoNotRunOnMetered -Value 1 -PropertyType DWord -Force -Confirm:$false) + $ChangedSettings++ + } + + if ($null -ne $($WAUPolicies.WAU_UpdatePrerelease) -and ($($WAUPolicies.WAU_UpdatePrerelease) -ne $($WAUConfig.WAU_UpdatePrerelease))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatePrerelease -Value $($WAUPolicies.WAU_UpdatePrerelease) -PropertyType DWord -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_UpdatePrerelease) -and $($WAUConfig.WAU_UpdatePrerelease)) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatePrerelease -Value 0 -PropertyType DWord -Force -Confirm:$false) + $ChangedSettings++ + } + + if ($null -ne $($WAUPolicies.WAU_UseWhiteList) -and ($($WAUPolicies.WAU_UseWhiteList) -ne $($WAUConfig.WAU_UseWhiteList))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UseWhiteList -Value $($WAUPolicies.WAU_UseWhiteList) -PropertyType DWord -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_UseWhiteList) -and ($($WAUConfig.WAU_UseWhiteList) -or $($WAUConfig.WAU_UseWhiteList) -eq 0)) + { + $null = (Remove-ItemProperty -Path $regPath -Name WAU_UseWhiteList -Force -ErrorAction SilentlyContinue -Confirm:$false) + $ChangedSettings++ + } + + if ($null -ne $($WAUPolicies.WAU_ListPath) -and ($($WAUPolicies.WAU_ListPath) -ne $($WAUConfig.WAU_ListPath))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_ListPath -Value $($WAUPolicies.WAU_ListPath.TrimEnd(' ', '\', '/')) -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_ListPath) -and $($WAUConfig.WAU_ListPath)) + { + $null = (Remove-ItemProperty -Path $regPath -Name WAU_ListPath -Force -ErrorAction SilentlyContinue -Confirm:$false) + $ChangedSettings++ + } + + if ($null -ne $($WAUPolicies.WAU_ModsPath) -and ($($WAUPolicies.WAU_ModsPath) -ne $($WAUConfig.WAU_ModsPath))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_ModsPath -Value $($WAUPolicies.WAU_ModsPath.TrimEnd(' ', '\', '/')) -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_ModsPath) -and $($WAUConfig.WAU_ModsPath)) + { + $null = (Remove-ItemProperty -Path $regPath -Name WAU_ModsPath -Force -ErrorAction SilentlyContinue -Confirm:$false) + $ChangedSettings++ + } + if ($null -ne $($WAUPolicies.WAU_AzureBlobSASURL) -and ($($WAUPolicies.WAU_AzureBlobSASURL) -ne $($WAUConfig.WAU_AzureBlobSASURL))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_AzureBlobSASURL -Value $($WAUPolicies.WAU_AzureBlobSASURL.TrimEnd(' ', '\', '/')) -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_AzureBlobSASURL) -and $($WAUConfig.WAU_AzureBlobSASURL)) + { + $null = (Remove-ItemProperty -Path $regPath -Name WAU_AzureBlobSASURL -Force -ErrorAction SilentlyContinue -Confirm:$false) + $ChangedSettings++ + } + + if ($null -ne $($WAUPolicies.WAU_NotificationLevel) -and ($($WAUPolicies.WAU_NotificationLevel) -ne $($WAUConfig.WAU_NotificationLevel))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_NotificationLevel -Value $($WAUPolicies.WAU_NotificationLevel) -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_NotificationLevel) -and $($WAUConfig.WAU_NotificationLevel) -ne 'Full') + { + $null = (New-ItemProperty -Path $regPath -Name WAU_NotificationLevel -Value 'Full' -Force -Confirm:$false) + $ChangedSettings++ + } + + if ($null -ne $($WAUPolicies.WAU_UpdatesAtTime) -and ($($WAUPolicies.WAU_UpdatesAtTime) -ne $($WAUConfig.WAU_UpdatesAtTime))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatesAtTime -Value $($WAUPolicies.WAU_UpdatesAtTime) -Force -Confirm:$false) + $Script:WAUConfig = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate') + $service = (New-Object -ComObject Schedule.Service) + $service.Connect($env:COMPUTERNAME) + $folder = $service.GetFolder('\') + $task = $folder.GetTask('Winget-AutoUpdate') + $definition = $task.Definition + + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) + { + if (($definition.Triggers.Item($triggerId).Type -eq '2') -or ($definition.Triggers.Item($triggerId).Type -eq '3')) + { + $PreStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(0, 11) + $PostStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(19, 6) + $Boundary = $PreStartBoundary + $($WAUPolicies.WAU_UpdatesAtTime) + $PostStartBoundary + $definition.Triggers.Item($triggerId).StartBoundary = $Boundary + break + } } - elseif ($null -eq $($WAUPolicies.WAU_BypassListForUsers) -and ($($WAUConfig.WAU_BypassListForUsers) -or $($WAUConfig.WAU_BypassListForUsers) -eq 0)) { - Remove-ItemProperty $regPath -Name WAU_BypassListForUsers -Force -ErrorAction SilentlyContinue | Out-Null - $ChangedSettings++ + $null = $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_UpdatesAtTime) -and $($WAUConfig.WAU_UpdatesAtTime) -ne '06:00:00') + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatesAtTime -Value '06:00:00' -Force -Confirm:$false) + $Script:WAUConfig = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate' + $service = (New-Object -ComObject Schedule.Service) + $service.Connect($env:COMPUTERNAME) + $folder = $service.GetFolder('\') + $task = $folder.GetTask('Winget-AutoUpdate') + $definition = $task.Definition + + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) + { + if (($definition.Triggers.Item($triggerId).Type -eq '2') -or ($definition.Triggers.Item($triggerId).Type -eq '3')) + { + $PreStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(0, 11) + $PostStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(19, 6) + $Boundary = $PreStartBoundary + '06:00:00' + $PostStartBoundary + $definition.Triggers.Item($triggerId).StartBoundary = $Boundary + break + } } - if ($null -ne $($WAUPolicies.WAU_DisableAutoUpdate) -and ($($WAUPolicies.WAU_DisableAutoUpdate) -ne $($WAUConfig.WAU_DisableAutoUpdate))) { - New-ItemProperty $regPath -Name WAU_DisableAutoUpdate -Value $($WAUPolicies.WAU_DisableAutoUpdate) -PropertyType DWord -Force | Out-Null - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_DisableAutoUpdate) -and ($($WAUConfig.WAU_DisableAutoUpdate) -or $($WAUConfig.WAU_DisableAutoUpdate) -eq 0)) { - Remove-ItemProperty $regPath -Name WAU_DisableAutoUpdate -Force -ErrorAction SilentlyContinue | Out-Null - $ChangedSettings++ + $null = $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) + $ChangedSettings++ + } + + if ($null -ne $($WAUPolicies.WAU_UpdatesInterval) -and ($($WAUPolicies.WAU_UpdatesInterval) -ne $($WAUConfig.WAU_UpdatesInterval))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatesInterval -Value $($WAUPolicies.WAU_UpdatesInterval) -Force -Confirm:$false) + $service = (New-Object -ComObject Schedule.Service) + $service.Connect($env:COMPUTERNAME) + $folder = $service.GetFolder('\') + $task = $folder.GetTask('Winget-AutoUpdate') + $definition = $task.Definition + + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) + { + if (($definition.Triggers.Item($triggerId).Type -eq '2') -or ($definition.Triggers.Item($triggerId).Type -eq '3')) + { + $UpdatesAtTime = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(11, 8) + $definition.Triggers.Remove($triggerId) + $triggerId -= 1 + } } - if ($null -ne $($WAUPolicies.WAU_DoNotRunOnMetered) -and ($($WAUPolicies.WAU_DoNotRunOnMetered) -ne $($WAUConfig.WAU_DoNotRunOnMetered))) { - New-ItemProperty $regPath -Name WAU_DoNotRunOnMetered -Value $($WAUPolicies.WAU_DoNotRunOnMetered) -PropertyType DWord -Force | Out-Null - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_DoNotRunOnMetered) -and !$($WAUConfig.WAU_DoNotRunOnMetered)) { - New-ItemProperty $regPath -Name WAU_DoNotRunOnMetered -Value 1 -PropertyType DWord -Force | Out-Null - $ChangedSettings++ + $null = $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) + + if (!$($WAUConfig.WAU_UpdatesAtTime)) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatesAtTime -Value $UpdatesAtTime -Force -Confirm:$false) + $Script:WAUConfig = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate') } - if ($null -ne $($WAUPolicies.WAU_UpdatePrerelease) -and ($($WAUPolicies.WAU_UpdatePrerelease) -ne $($WAUConfig.WAU_UpdatePrerelease))) { - New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value $($WAUPolicies.WAU_UpdatePrerelease) -PropertyType DWord -Force | Out-Null - $ChangedSettings++ + if ($($WAUPolicies.WAU_UpdatesInterval) -ne 'Never') + { + #Count Triggers (correctly) + $service = (New-Object -ComObject Schedule.Service) + $service.Connect($env:COMPUTERNAME) + $folder = $service.GetFolder('\') + $task = $folder.GetTask('Winget-AutoUpdate') + $definition = $task.Definition + $null = $definition.Triggers.Count + switch ($($WAUPolicies.WAU_UpdatesInterval)) + { + 'Daily' + { + $tasktrigger = New-ScheduledTaskTrigger -Daily -At $($WAUConfig.WAU_UpdatesAtTime) + break + } + 'BiDaily' + { + $tasktrigger = New-ScheduledTaskTrigger -Daily -At $($WAUConfig.WAU_UpdatesAtTime) -DaysInterval 2 + break + } + 'Weekly' + { + $tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2 + break + } + 'BiWeekly' + { + $tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2 -WeeksInterval 2 + break + } + 'Monthly' + { + $tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2 -WeeksInterval 4 + break + } + } + if ($definition.Triggers.Count -gt 0) + { + $triggers = @() + $triggers += (Get-ScheduledTask -TaskName 'Winget-AutoUpdate').Triggers + $triggers += $tasktrigger + $null = (Set-ScheduledTask -TaskName 'Winget-AutoUpdate' -Trigger $triggers) + } + else + { + $null = (Set-ScheduledTask -TaskName 'Winget-AutoUpdate' -Trigger $tasktrigger) + } } - elseif ($null -eq $($WAUPolicies.WAU_UpdatePrerelease) -and $($WAUConfig.WAU_UpdatePrerelease)) { - New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value 0 -PropertyType DWord -Force | Out-Null - $ChangedSettings++ + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_UpdatesInterval) -and $($WAUConfig.WAU_UpdatesInterval) -ne 'Daily') + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatesInterval -Value 'Daily' -Force -Confirm:$false) + $service = (New-Object -ComObject Schedule.Service) + $service.Connect($env:COMPUTERNAME) + $folder = $service.GetFolder('\') + $task = $folder.GetTask('Winget-AutoUpdate') + $definition = $task.Definition + + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) + { + if (($definition.Triggers.Item($triggerId).Type -eq '2') -or ($definition.Triggers.Item($triggerId).Type -eq '3')) + { + $UpdatesAtTime = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(11, 8) + $definition.Triggers.Remove($triggerId) + $triggerId -= 1 + } } - if ($null -ne $($WAUPolicies.WAU_UseWhiteList) -and ($($WAUPolicies.WAU_UseWhiteList) -ne $($WAUConfig.WAU_UseWhiteList))) { - New-ItemProperty $regPath -Name WAU_UseWhiteList -Value $($WAUPolicies.WAU_UseWhiteList) -PropertyType DWord -Force | Out-Null - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_UseWhiteList) -and ($($WAUConfig.WAU_UseWhiteList) -or $($WAUConfig.WAU_UseWhiteList) -eq 0)) { - Remove-ItemProperty $regPath -Name WAU_UseWhiteList -Force -ErrorAction SilentlyContinue | Out-Null - $ChangedSettings++ + $null = $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) + + if (!$($WAUConfig.WAU_UpdatesAtTime)) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatesAtTime -Value $UpdatesAtTime -Force -Confirm:$false) + $Script:WAUConfig = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate') } - if ($null -ne $($WAUPolicies.WAU_ListPath) -and ($($WAUPolicies.WAU_ListPath) -ne $($WAUConfig.WAU_ListPath))) { - New-ItemProperty $regPath -Name WAU_ListPath -Value $($WAUPolicies.WAU_ListPath.TrimEnd(" ", "\", "/")) -Force | Out-Null - $ChangedSettings++ + $tasktrigger = (New-ScheduledTaskTrigger -Daily -At $($WAUConfig.WAU_UpdatesAtTime)) + + # Count Triggers (correctly) + $service = (New-Object -ComObject Schedule.Service) + $service.Connect($env:COMPUTERNAME) + $folder = $service.GetFolder('\') + $task = $folder.GetTask('Winget-AutoUpdate') + $definition = $task.Definition + $null = $definition.Triggers.Count + + if ($definition.Triggers.Count -gt 0) + { + $triggers = @() + $triggers += (Get-ScheduledTask -TaskName 'Winget-AutoUpdate').Triggers + $triggers += $tasktrigger + $null = (Set-ScheduledTask -TaskName 'Winget-AutoUpdate' -Trigger $triggers) } - elseif ($null -eq $($WAUPolicies.WAU_ListPath) -and $($WAUConfig.WAU_ListPath)) { - Remove-ItemProperty $regPath -Name WAU_ListPath -Force -ErrorAction SilentlyContinue | Out-Null - $ChangedSettings++ + else + { + $null = (Set-ScheduledTask -TaskName 'Winget-AutoUpdate' -Trigger $tasktrigger) + } + $ChangedSettings++ + } + + if ($null -ne $($WAUPolicies.WAU_UpdatesAtLogon) -and ($($WAUPolicies.WAU_UpdatesAtLogon) -ne $($WAUConfig.WAU_UpdatesAtLogon))) + { + if ($WAUPolicies.WAU_UpdatesAtLogon -eq 1) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatesAtLogon -Value $($WAUPolicies.WAU_UpdatesAtLogon) -PropertyType DWord -Force -Confirm:$false) + $triggers = @() + $triggers += (Get-ScheduledTask -TaskName 'Winget-AutoUpdate').Triggers + # Count Triggers (correctly) + $service = (New-Object -ComObject Schedule.Service) + $service.Connect($env:COMPUTERNAME) + $folder = $service.GetFolder('\') + $task = $folder.GetTask('Winget-AutoUpdate') + $definition = $task.Definition + $triggerLogon = $false + + foreach ($trigger in $definition.Triggers) + { + if ($trigger.Type -eq '9') + { + $triggerLogon = $true + break + } + } + if (!$triggerLogon) + { + $triggers += New-ScheduledTaskTrigger -AtLogOn + $null = (Set-ScheduledTask -TaskName 'Winget-AutoUpdate' -Trigger $triggers) + } + } + else + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatesAtLogon -Value $($WAUPolicies.WAU_UpdatesAtLogon) -PropertyType DWord -Force -Confirm:$false) + $service = (New-Object -ComObject Schedule.Service) + $service.Connect($env:COMPUTERNAME) + $folder = $service.GetFolder('\') + $task = $folder.GetTask('Winget-AutoUpdate') + $definition = $task.Definition + $null = $definition.Triggers.Count + + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) + { + if ($definition.Triggers.Item($triggerId).Type -eq '9') + { + $definition.Triggers.Remove($triggerId) + $triggerId -= 1 + } + } + + $null = $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) } - if ($null -ne $($WAUPolicies.WAU_ModsPath) -and ($($WAUPolicies.WAU_ModsPath) -ne $($WAUConfig.WAU_ModsPath))) { - New-ItemProperty $regPath -Name WAU_ModsPath -Value $($WAUPolicies.WAU_ModsPath.TrimEnd(" ", "\", "/")) -Force | Out-Null - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_ModsPath) -and $($WAUConfig.WAU_ModsPath)) { - Remove-ItemProperty $regPath -Name WAU_ModsPath -Force -ErrorAction SilentlyContinue | Out-Null - $ChangedSettings++ - } - if ($null -ne $($WAUPolicies.WAU_AzureBlobSASURL) -and ($($WAUPolicies.WAU_AzureBlobSASURL) -ne $($WAUConfig.WAU_AzureBlobSASURL))) { - New-ItemProperty $regPath -Name WAU_AzureBlobSASURL -Value $($WAUPolicies.WAU_AzureBlobSASURL.TrimEnd(" ", "\", "/")) -Force | Out-Null - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_AzureBlobSASURL) -and $($WAUConfig.WAU_AzureBlobSASURL)) { - Remove-ItemProperty $regPath -Name WAU_AzureBlobSASURL -Force -ErrorAction SilentlyContinue | Out-Null - $ChangedSettings++ + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_UpdatesAtLogon) -and ($($WAUConfig.WAU_UpdatesAtLogon) -or $($WAUConfig.WAU_UpdatesAtLogon) -eq 0)) + { + $null = (Remove-ItemProperty -Path $regPath -Name WAU_UpdatesAtLogon -Force -ErrorAction SilentlyContinue -Confirm:$false) + $service = (New-Object -ComObject Schedule.Service) + $service.Connect($env:COMPUTERNAME) + $folder = $service.GetFolder('\') + $task = $folder.GetTask('Winget-AutoUpdate') + $definition = $task.Definition + + for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) + { + if ($definition.Triggers.Item($triggerId).Type -eq '9') + { + $definition.Triggers.Remove($triggerId) + $triggerId -= 1 + } } - if ($null -ne $($WAUPolicies.WAU_NotificationLevel) -and ($($WAUPolicies.WAU_NotificationLevel) -ne $($WAUConfig.WAU_NotificationLevel))) { - New-ItemProperty $regPath -Name WAU_NotificationLevel -Value $($WAUPolicies.WAU_NotificationLevel) -Force | Out-Null - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_NotificationLevel) -and $($WAUConfig.WAU_NotificationLevel) -ne "Full") { - New-ItemProperty $regPath -Name WAU_NotificationLevel -Value "Full" -Force | Out-Null - $ChangedSettings++ - } + $null = $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) + $ChangedSettings++ + } - if ($null -ne $($WAUPolicies.WAU_UpdatesAtTime) -and ($($WAUPolicies.WAU_UpdatesAtTime) -ne $($WAUConfig.WAU_UpdatesAtTime))) { - New-ItemProperty $regPath -Name WAU_UpdatesAtTime -Value $($WAUPolicies.WAU_UpdatesAtTime) -Force | Out-Null - $Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" - $service = New-Object -ComObject Schedule.Service - $service.Connect($env:COMPUTERNAME) - $folder = $service.GetFolder('\') - $task = $folder.GetTask("Winget-AutoUpdate") - $definition = $task.Definition - for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { - if (($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")) { - $PreStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(0, 11) - $PostStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(19, 6) - $Boundary = $PreStartBoundary + $($WAUPolicies.WAU_UpdatesAtTime) + $PostStartBoundary - $definition.Triggers.Item($triggerId).StartBoundary = $Boundary - break - $triggerId -= 1 - } - } - $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_UpdatesAtTime) -and $($WAUConfig.WAU_UpdatesAtTime) -ne "06:00:00") { - New-ItemProperty $regPath -Name WAU_UpdatesAtTime -Value "06:00:00" -Force | Out-Null - $Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" - $service = New-Object -ComObject Schedule.Service - $service.Connect($env:COMPUTERNAME) - $folder = $service.GetFolder('\') - $task = $folder.GetTask("Winget-AutoUpdate") - $definition = $task.Definition - for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { - if (($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")) { - $PreStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(0, 11) - $PostStartBoundary = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(19, 6) - $Boundary = $PreStartBoundary + "06:00:00" + $PostStartBoundary - $definition.Triggers.Item($triggerId).StartBoundary = $Boundary - break - $triggerId -= 1 - } - } - $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null - $ChangedSettings++ - } + if ($null -ne $($WAUPolicies.WAU_UserContext) -and ($($WAUPolicies.WAU_UserContext) -ne $($WAUConfig.WAU_UserContext))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UserContext -Value $($WAUPolicies.WAU_UserContext) -PropertyType DWord -Force -Confirm:$false) - if ($null -ne $($WAUPolicies.WAU_UpdatesInterval) -and ($($WAUPolicies.WAU_UpdatesInterval) -ne $($WAUConfig.WAU_UpdatesInterval))) { - New-ItemProperty $regPath -Name WAU_UpdatesInterval -Value $($WAUPolicies.WAU_UpdatesInterval) -Force | Out-Null - $service = New-Object -ComObject Schedule.Service - $service.Connect($env:COMPUTERNAME) - $folder = $service.GetFolder('\') - $task = $folder.GetTask("Winget-AutoUpdate") - $definition = $task.Definition - for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { - if (($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")) { - $UpdatesAtTime = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(11, 8) - $definition.Triggers.Remove($triggerId) - $triggerId -= 1 - } - } - $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null + if ($WAUPolicies.WAU_UserContext -eq 1) + { + # Settings for the scheduled task in User context + $taskAction = New-ScheduledTaskAction -Execute 'wscript.exe' -Argument "`"$($WAUConfig.InstallLocation)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUConfig.InstallLocation)\winget-upgrade.ps1`"`"" + $taskUserPrincipal = New-ScheduledTaskPrincipal -GroupId S-1-5-11 + $taskSettings = New-ScheduledTaskSettingsSet -Compatibility Win8 -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 03:00:00 + # Set up the task for user apps + $task = (New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings) + $null = (Register-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -InputObject $task -Force) + } + else + { + $null = (Get-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false -ErrorAction SilentlyContinue) + } + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_UserContext) -and ($($WAUConfig.WAU_UserContext) -or $($WAUConfig.WAU_UserContext) -eq 0)) + { + $null = (Remove-ItemProperty -Path $regPath -Name WAU_UserContext -Force -ErrorAction SilentlyContinue -Confirm:$false) + $null = (Get-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$false -ErrorAction SilentlyContinue) + $ChangedSettings++ + } - if (!$($WAUConfig.WAU_UpdatesAtTime)) { - New-ItemProperty $regPath -Name WAU_UpdatesAtTime -Value $UpdatesAtTime -Force | Out-Null - $Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" - } + if ($null -ne $($WAUPolicies.WAU_DesktopShortcut) -and ($($WAUPolicies.WAU_DesktopShortcut) -ne $($WAUConfig.WAU_DesktopShortcut))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_DesktopShortcut -Value $($WAUPolicies.WAU_DesktopShortcut) -PropertyType DWord -Force -Confirm:$false) - if ($($WAUPolicies.WAU_UpdatesInterval) -ne "Never") { - #Count Triggers (correctly) - $service = New-Object -ComObject Schedule.Service - $service.Connect($env:COMPUTERNAME) - $folder = $service.GetFolder('\') - $task = $folder.GetTask("Winget-AutoUpdate") - $definition = $task.Definition - $definition.Triggers.Count | Out-Null - switch ($($WAUPolicies.WAU_UpdatesInterval)) { - "Daily" { $tasktrigger = New-ScheduledTaskTrigger -Daily -At $($WAUConfig.WAU_UpdatesAtTime); break } - "BiDaily" { $tasktrigger = New-ScheduledTaskTrigger -Daily -At $($WAUConfig.WAU_UpdatesAtTime) -DaysInterval 2; break } - "Weekly" { $tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2; break } - "BiWeekly" { $tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2 -WeeksInterval 2; break } - "Monthly" { $tasktrigger = New-ScheduledTaskTrigger -Weekly -At $($WAUConfig.WAU_UpdatesAtTime) -DaysOfWeek 2 -WeeksInterval 4; break } - } - if ($definition.Triggers.Count -gt 0) { - $triggers = @() - $triggers += (Get-ScheduledTask "Winget-AutoUpdate").Triggers - $triggers += $tasktrigger - Set-ScheduledTask -TaskName "Winget-AutoUpdate" -Trigger $triggers - } - else { - Set-ScheduledTask -TaskName "Winget-AutoUpdate" -Trigger $tasktrigger - } - } - $ChangedSettings++ + if ($WAUPolicies.WAU_DesktopShortcut -eq 1) + { + Add-Shortcut 'wscript.exe' "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" "`"$($WAUConfig.InstallLocation)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUConfig.InstallLocation)\user-run.ps1`"`"" "${env:SystemRoot}\System32\shell32.dll,-16739" 'Manual start of Winget-AutoUpdate (WAU)...' } - elseif ($null -eq $($WAUPolicies.WAU_UpdatesInterval) -and $($WAUConfig.WAU_UpdatesInterval) -ne "Daily") { - New-ItemProperty $regPath -Name WAU_UpdatesInterval -Value "Daily" -Force | Out-Null - $service = New-Object -ComObject Schedule.Service - $service.Connect($env:COMPUTERNAME) - $folder = $service.GetFolder('\') - $task = $folder.GetTask("Winget-AutoUpdate") - $definition = $task.Definition - for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { - if (($definition.Triggers.Item($triggerId).Type -eq "2") -or ($definition.Triggers.Item($triggerId).Type -eq "3")) { - $UpdatesAtTime = ($definition.Triggers.Item($triggerId).StartBoundary).Substring(11, 8) - $definition.Triggers.Remove($triggerId) - $triggerId -= 1 - } - } - $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null + else + { + $null = (Remove-Item -Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" -Force -Confirm:$false) + } + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_DesktopShortcut) -and ($($WAUConfig.WAU_DesktopShortcut) -or $($WAUConfig.WAU_DesktopShortcut) -eq 0)) + { + $null = (Remove-ItemProperty -Path $regPath -Name WAU_DesktopShortcut -Force -Confirm:$false -ErrorAction SilentlyContinue) + $null = (Remove-Item -Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" -Force -Confirm:$false) + $ChangedSettings++ + } - if (!$($WAUConfig.WAU_UpdatesAtTime)) { - New-ItemProperty $regPath -Name WAU_UpdatesAtTime -Value $UpdatesAtTime -Force | Out-Null - $Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" - } + if ($null -ne $($WAUPolicies.WAU_StartMenuShortcut) -and ($($WAUPolicies.WAU_StartMenuShortcut) -ne $($WAUConfig.WAU_StartMenuShortcut))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_StartMenuShortcut -Value $($WAUPolicies.WAU_StartMenuShortcut) -PropertyType DWord -Force -Confirm:$false) - $tasktrigger = New-ScheduledTaskTrigger -Daily -At $($WAUConfig.WAU_UpdatesAtTime) + if ($WAUPolicies.WAU_StartMenuShortcut -eq 1) + { + if (!(Test-Path -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)")) + { + $null = (New-Item -ItemType Directory -Force -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" -Confirm:$false) + } - #Count Triggers (correctly) - $service = New-Object -ComObject Schedule.Service - $service.Connect($env:COMPUTERNAME) - $folder = $service.GetFolder('\') - $task = $folder.GetTask("Winget-AutoUpdate") - $definition = $task.Definition - $definition.Triggers.Count | Out-Null - if ($definition.Triggers.Count -gt 0) { - $triggers = @() - $triggers += (Get-ScheduledTask "Winget-AutoUpdate").Triggers - $triggers += $tasktrigger - Set-ScheduledTask -TaskName "Winget-AutoUpdate" -Trigger $triggers - } - else { - Set-ScheduledTask -TaskName "Winget-AutoUpdate" -Trigger $tasktrigger - } - $ChangedSettings++ + Add-Shortcut 'wscript.exe' "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Check for updated Apps.lnk" "`"$($WAUConfig.InstallLocation)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUConfig.InstallLocation)\user-run.ps1`"`"" "${env:SystemRoot}\System32\shell32.dll,-16739" 'Manual start of Winget-AutoUpdate (WAU)...' + Add-Shortcut 'wscript.exe' "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Open logs.lnk" "`"$($WAUConfig.InstallLocation)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUConfig.InstallLocation)\user-run.ps1`" -Logs`"" "${env:SystemRoot}\System32\shell32.dll,-16763" 'Open existing WAU logs...' + Add-Shortcut 'wscript.exe' "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Web Help.lnk" "`"$($WAUConfig.InstallLocation)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUConfig.InstallLocation)\user-run.ps1`" -Help`"" "${env:SystemRoot}\System32\shell32.dll,-24" 'Help for WAU...' } + else + { + $null = (Remove-Item -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" -Recurse -Force -Confirm:$false) + } + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_StartMenuShortcut) -and ($($WAUConfig.WAU_StartMenuShortcut) -or $($WAUConfig.WAU_StartMenuShortcut) -eq 0)) + { + $null = (Remove-ItemProperty -Path $regPath -Name WAU_StartMenuShortcut -Force -ErrorAction SilentlyContinue -Confirm:$false) + $null = (Remove-Item -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" -Recurse -Force -Confirm:$false) + $ChangedSettings++ + } - if ($null -ne $($WAUPolicies.WAU_UpdatesAtLogon) -and ($($WAUPolicies.WAU_UpdatesAtLogon) -ne $($WAUConfig.WAU_UpdatesAtLogon))) { - if ($WAUPolicies.WAU_UpdatesAtLogon -eq 1) { - New-ItemProperty $regPath -Name WAU_UpdatesAtLogon -Value $($WAUPolicies.WAU_UpdatesAtLogon) -PropertyType DWord -Force | Out-Null - $triggers = @() - $triggers += (Get-ScheduledTask "Winget-AutoUpdate").Triggers - #Count Triggers (correctly) - $service = New-Object -ComObject Schedule.Service - $service.Connect($env:COMPUTERNAME) - $folder = $service.GetFolder('\') - $task = $folder.GetTask("Winget-AutoUpdate") - $definition = $task.Definition - $triggerLogon = $false - foreach ($trigger in $definition.Triggers) { - if ($trigger.Type -eq "9") { - $triggerLogon = $true - break - } - } - if (!$triggerLogon) { - $triggers += New-ScheduledTaskTrigger -AtLogon - Set-ScheduledTask -TaskName "Winget-AutoUpdate" -Trigger $triggers - } - } - else { - New-ItemProperty $regPath -Name WAU_UpdatesAtLogon -Value $($WAUPolicies.WAU_UpdatesAtLogon) -PropertyType DWord -Force | Out-Null - $service = New-Object -ComObject Schedule.Service - $service.Connect($env:COMPUTERNAME) - $folder = $service.GetFolder('\') - $task = $folder.GetTask("Winget-AutoUpdate") - $definition = $task.Definition - $definition.Triggers.Count | Out-Null - for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { - if ($definition.Triggers.Item($triggerId).Type -eq "9") { - $definition.Triggers.Remove($triggerId) - $triggerId -= 1 - } - } - $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null - } - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_UpdatesAtLogon) -and ($($WAUConfig.WAU_UpdatesAtLogon) -or $($WAUConfig.WAU_UpdatesAtLogon) -eq 0)) { - Remove-ItemProperty $regPath -Name WAU_UpdatesAtLogon -Force -ErrorAction SilentlyContinue | Out-Null - $service = New-Object -ComObject Schedule.Service - $service.Connect($env:COMPUTERNAME) - $folder = $service.GetFolder('\') - $task = $folder.GetTask("Winget-AutoUpdate") - $definition = $task.Definition - for ($triggerId = 1; $triggerId -le $definition.Triggers.Count; $triggerId++) { - if ($definition.Triggers.Item($triggerId).Type -eq "9") { - $definition.Triggers.Remove($triggerId) - $triggerId -= 1 - } - } - $folder.RegisterTaskDefinition($task.Name, $definition, 4, $null, $null, $null) | Out-Null - $ChangedSettings++ - } + if ($null -ne $($WAUPolicies.WAU_MaxLogFiles) -and ($($WAUPolicies.WAU_MaxLogFiles) -ne $($WAUConfig.WAU_MaxLogFiles))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_MaxLogFiles -Value $($WAUPolicies.WAU_MaxLogFiles.TrimEnd(' ', '\', '/')) -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_MaxLogFiles) -and $($WAUConfig.WAU_MaxLogFiles) -ne 3) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_MaxLogFiles -Value 3 -Force -Confirm:$false) + $ChangedSettings++ + } - if ($null -ne $($WAUPolicies.WAU_UserContext) -and ($($WAUPolicies.WAU_UserContext) -ne $($WAUConfig.WAU_UserContext))) { - New-ItemProperty $regPath -Name WAU_UserContext -Value $($WAUPolicies.WAU_UserContext) -PropertyType DWord -Force | Out-Null - if ($WAUPolicies.WAU_UserContext -eq 1) { - # Settings for the scheduled task in User context - $taskAction = New-ScheduledTaskAction -Execute "wscript.exe" -Argument "`"$($WAUConfig.InstallLocation)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUConfig.InstallLocation)\winget-upgrade.ps1`"`"" - $taskUserPrincipal = New-ScheduledTaskPrincipal -GroupId S-1-5-11 - $taskSettings = New-ScheduledTaskSettingsSet -Compatibility Win8 -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 03:00:00 + if ($null -ne $($WAUPolicies.WAU_MaxLogSize) -and ($($WAUPolicies.WAU_MaxLogSize) -ne $($WAUConfig.WAU_MaxLogSize))) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_MaxLogSize -Value $($WAUPolicies.WAU_MaxLogSize.TrimEnd(' ', '\', '/')) -Force -Confirm:$false) + $ChangedSettings++ + } + elseif ($null -eq $($WAUPolicies.WAU_MaxLogSize) -and $($WAUConfig.WAU_MaxLogSize) -ne 1048576) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_MaxLogSize -Value 1048576 -Force -Confirm:$false) + $ChangedSettings++ + } - # Set up the task for user apps - $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings - Register-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -InputObject $task -Force - } - else { - Get-ScheduledTask -TaskName "Winget-AutoUpdate-UserContext" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False - } - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_UserContext) -and ($($WAUConfig.WAU_UserContext) -or $($WAUConfig.WAU_UserContext) -eq 0)) { - Remove-ItemProperty $regPath -Name WAU_UserContext -Force -ErrorAction SilentlyContinue | Out-Null - Get-ScheduledTask -TaskName "Winget-AutoUpdate-UserContext" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False - $ChangedSettings++ - } + # Get WAU Configurations after Policies change + $Script:WAUConfig = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate') + } + } - if ($null -ne $($WAUPolicies.WAU_DesktopShortcut) -and ($($WAUPolicies.WAU_DesktopShortcut) -ne $($WAUConfig.WAU_DesktopShortcut))) { - New-ItemProperty $regPath -Name WAU_DesktopShortcut -Value $($WAUPolicies.WAU_DesktopShortcut) -PropertyType DWord -Force | Out-Null - if ($WAUPolicies.WAU_DesktopShortcut -eq 1) { - Add-Shortcut "wscript.exe" "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" "`"$($WAUConfig.InstallLocation)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUConfig.InstallLocation)\user-run.ps1`"`"" "${env:SystemRoot}\System32\shell32.dll,-16739" "Manual start of Winget-AutoUpdate (WAU)..." - } - else { - Remove-Item -Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" -Force | Out-Null - } - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_DesktopShortcut) -and ($($WAUConfig.WAU_DesktopShortcut) -or $($WAUConfig.WAU_DesktopShortcut) -eq 0)) { - Remove-ItemProperty $regPath -Name WAU_DesktopShortcut -Force -ErrorAction SilentlyContinue | Out-Null - Remove-Item -Path "${env:Public}\Desktop\WAU - Check for updated Apps.lnk" -Force | Out-Null - $ChangedSettings++ - } - - if ($null -ne $($WAUPolicies.WAU_StartMenuShortcut) -and ($($WAUPolicies.WAU_StartMenuShortcut) -ne $($WAUConfig.WAU_StartMenuShortcut))) { - New-ItemProperty $regPath -Name WAU_StartMenuShortcut -Value $($WAUPolicies.WAU_StartMenuShortcut) -PropertyType DWord -Force | Out-Null - if ($WAUPolicies.WAU_StartMenuShortcut -eq 1) { - if (!(Test-Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)")) { - New-Item -ItemType Directory -Force -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" | Out-Null - } - Add-Shortcut "wscript.exe" "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Check for updated Apps.lnk" "`"$($WAUConfig.InstallLocation)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUConfig.InstallLocation)\user-run.ps1`"`"" "${env:SystemRoot}\System32\shell32.dll,-16739" "Manual start of Winget-AutoUpdate (WAU)..." - Add-Shortcut "wscript.exe" "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Open logs.lnk" "`"$($WAUConfig.InstallLocation)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUConfig.InstallLocation)\user-run.ps1`" -Logs`"" "${env:SystemRoot}\System32\shell32.dll,-16763" "Open existing WAU logs..." - Add-Shortcut "wscript.exe" "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)\WAU - Web Help.lnk" "`"$($WAUConfig.InstallLocation)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WAUConfig.InstallLocation)\user-run.ps1`" -Help`"" "${env:SystemRoot}\System32\shell32.dll,-24" "Help for WAU..." - } - else { - Remove-Item -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" -Recurse -Force | Out-Null - } - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_StartMenuShortcut) -and ($($WAUConfig.WAU_StartMenuShortcut) -or $($WAUConfig.WAU_StartMenuShortcut) -eq 0)) { - Remove-ItemProperty $regPath -Name WAU_StartMenuShortcut -Force -ErrorAction SilentlyContinue | Out-Null - Remove-Item -Path "${env:ProgramData}\Microsoft\Windows\Start Menu\Programs\Winget-AutoUpdate (WAU)" -Recurse -Force | Out-Null - $ChangedSettings++ - } - - if ($null -ne $($WAUPolicies.WAU_MaxLogFiles) -and ($($WAUPolicies.WAU_MaxLogFiles) -ne $($WAUConfig.WAU_MaxLogFiles))) { - New-ItemProperty $regPath -Name WAU_MaxLogFiles -Value $($WAUPolicies.WAU_MaxLogFiles.TrimEnd(" ", "\", "/")) -Force | Out-Null - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_MaxLogFiles) -and $($WAUConfig.WAU_MaxLogFiles) -ne 3) { - New-ItemProperty $regPath -Name WAU_MaxLogFiles -Value 3 -Force | Out-Null - $ChangedSettings++ - } - - if ($null -ne $($WAUPolicies.WAU_MaxLogSize) -and ($($WAUPolicies.WAU_MaxLogSize) -ne $($WAUConfig.WAU_MaxLogSize))) { - New-ItemProperty $regPath -Name WAU_MaxLogSize -Value $($WAUPolicies.WAU_MaxLogSize.TrimEnd(" ", "\", "/")) -Force | Out-Null - $ChangedSettings++ - } - elseif ($null -eq $($WAUPolicies.WAU_MaxLogSize) -and $($WAUConfig.WAU_MaxLogSize) -ne 1048576) { - New-ItemProperty $regPath -Name WAU_MaxLogSize -Value 1048576 -Force | Out-Null - $ChangedSettings++ - } - - #Get WAU Configurations after Policies change - $Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" - } - } - Return $($WAUPolicies.WAU_ActivateGPOManagement), $ChangedSettings + return $($WAUPolicies.WAU_ActivateGPOManagement), $ChangedSettings } diff --git a/Winget-AutoUpdate/functions/Get-WAUAvailableVersion.ps1 b/Winget-AutoUpdate/functions/Get-WAUAvailableVersion.ps1 index c2241ab..08e0f93 100644 --- a/Winget-AutoUpdate/functions/Get-WAUAvailableVersion.ps1 +++ b/Winget-AutoUpdate/functions/Get-WAUAvailableVersion.ps1 @@ -1,25 +1,22 @@ -#Function to get the latest WAU available version on Github +# Function to get the latest WAU available version on Github -function Get-WAUAvailableVersion { +function Get-WAUAvailableVersion +{ + # Get Github latest version + if ($WAUConfig.WAU_UpdatePrerelease -eq 1) + { + # Log + Write-ToLog -LogMsg 'WAU AutoUpdate Pre-release versions is Enabled' -LogColor 'Cyan' - #Get Github latest version - if ($WAUConfig.WAU_UpdatePrerelease -eq 1) { - - #Log - Write-ToLog "WAU AutoUpdate Pre-release versions is Enabled" "Cyan" - - #Get latest pre-release info - $WAUurl = 'https://api.github.com/repos/Romanitho/Winget-AutoUpdate/releases' - - } - else { - - #Get latest stable info - $WAUurl = 'https://api.github.com/repos/Romanitho/Winget-AutoUpdate/releases/latest' - - } - - #Return version - return ((Invoke-WebRequest $WAUurl -UseBasicParsing | ConvertFrom-Json)[0].tag_name).Replace("v", "") + # Get latest pre-release info + $WAUurl = 'https://api.github.com/repos/Romanitho/Winget-AutoUpdate/releases' + } + else + { + # Get latest stable info + $WAUurl = 'https://api.github.com/repos/Romanitho/Winget-AutoUpdate/releases/latest' + } + # Return version + return ((Invoke-WebRequest -Uri $WAUurl -UseBasicParsing | ConvertFrom-Json)[0].tag_name).Replace('v', '') } diff --git a/Winget-AutoUpdate/functions/Get-WingetCmd.ps1 b/Winget-AutoUpdate/functions/Get-WingetCmd.ps1 index e0be4e4..03fe939 100644 --- a/Winget-AutoUpdate/functions/Get-WingetCmd.ps1 +++ b/Winget-AutoUpdate/functions/Get-WingetCmd.ps1 @@ -1,41 +1,53 @@ -#Function to get the winget command regarding execution context (User, System...) +# Function to get the winget command regarding execution context (User, System...) -Function Get-WingetCmd { +function Get-WingetCmd +{ - #Get WinGet Path (if Admin context) - # Includes Workaround for ARM64 (removed X64 and replaces it with a wildcard) - $ResolveWingetPath = Resolve-Path "$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller_*_*__8wekyb3d8bbwe" | Sort-Object { [version]($_.Path -replace '^[^\d]+_((\d+\.)*\d+)_.*', '$1') } + # Get WinGet Path (if Admin context) + # Includes Workaround for ARM64 (removed X64 and replaces it with a wildcard) + $ResolveWingetPath = (Resolve-Path -Path "$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller_*_*__8wekyb3d8bbwe" | Sort-Object -Property { + [version]($_.Path -replace '^[^\d]+_((\d+\.)*\d+)_.*', '$1') + }) - if ($ResolveWingetPath) { - #If multiple version, pick last one - $WingetPath = $ResolveWingetPath[-1].Path - } + if ($ResolveWingetPath) + { + # If multiple version, pick last one + $WingetPath = $ResolveWingetPath[-1].Path + } - #If running under System or Admin context obtain Winget from Program Files - if((([System.Security.Principal.WindowsIdentity]::GetCurrent().User) -eq "S-1-5-18") -or ($WingetPath)){ - if (Test-Path "$WingetPath\winget.exe") { - $Script:Winget = "$WingetPath\winget.exe" - } - }else{ - #Get Winget Location in User context - $WingetCmd = Get-Command winget.exe -ErrorAction SilentlyContinue - if ($WingetCmd) { - $Script:Winget = $WingetCmd.Source - } - } + #If running under System or Admin context obtain Winget from Program Files + if ((([Security.Principal.WindowsIdentity]::GetCurrent().User) -eq 'S-1-5-18') -or ($WingetPath)) + { + if (Test-Path -Path ('{0}\winget.exe' -f $WingetPath) -ErrorAction SilentlyContinue) + { + $Script:Winget = ('{0}\winget.exe' -f $WingetPath) + } + } + else + { + #Get Winget Location in User context + $WingetCmd = (Get-Command -Name winget.exe -ErrorAction SilentlyContinue) - If(!($Script:Winget)){ - Write-ToLog "Winget not installed or detected !" "Red" - return $false - } + if ($WingetCmd) + { + $Script:Winget = $WingetCmd.Source + } + } - #Run winget to list apps and accept source agrements (necessary on first run) - & $Winget list --accept-source-agreements -s winget | Out-Null + if (!($Script:Winget)) + { + Write-ToLog 'Winget not installed or detected !' 'Red' - #Log Winget installed version - $WingetVer = & $Winget --version - Write-ToLog "Winget Version: $WingetVer" + return $false + } - return $true + # Run winget to list apps and accept source agrements (necessary on first run) + $null = (& $Winget list --accept-source-agreements -s winget) + + # Log Winget installed version + $WingetVer = & $Winget --version + Write-ToLog ('Winget Version: {0}' -f $WingetVer) + + return $true } diff --git a/Winget-AutoUpdate/functions/Get-WingetOutdatedApps.ps1 b/Winget-AutoUpdate/functions/Get-WingetOutdatedApps.ps1 index 59eaffa..c2d1b9e 100644 --- a/Winget-AutoUpdate/functions/Get-WingetOutdatedApps.ps1 +++ b/Winget-AutoUpdate/functions/Get-WingetOutdatedApps.ps1 @@ -1,76 +1,92 @@ -#Function to get the outdated app list, in formatted array +# Function to get the outdated app list, in formatted array -function Get-WingetOutdatedApps { - class Software { - [string]$Name - [string]$Id - [string]$Version - [string]$AvailableVersion - } +function Get-WingetOutdatedApps +{ + class Software { + [string]$Name + [string]$Id + [string]$Version + [string]$AvailableVersion + } - #Get list of available upgrades on winget format - $upgradeResult = & $Winget upgrade --source winget | Out-String + # Get list of available upgrades on winget format + $upgradeResult = (& $Winget upgrade --source winget | Out-String) - #Start Convertion of winget format to an array. Check if "-----" exists (Winget Error Handling) - if (!($upgradeResult -match "-----")) { - return "An unusual thing happened (maybe all apps are upgraded):`n$upgradeResult" - } + # Start Convertion of winget format to an array. Check if "-----" exists (Winget Error Handling) + if (!($upgradeResult -match '-----')) + { + return "An unusual thing happened (maybe all apps are upgraded):`n$upgradeResult" + } - #Split winget output to lines - $lines = $upgradeResult.Split([Environment]::NewLine) | Where-Object { $_ } + # Split winget output to lines + $lines = $upgradeResult.Split([Environment]::NewLine) | Where-Object -FilterScript { + $_ + } - # Find the line that starts with "------" - $fl = 0 - while (-not $lines[$fl].StartsWith("-----")) { - $fl++ - } + # Find the line that starts with "------" + $fl = 0 + while (-not $lines[$fl].StartsWith('-----')) + { + $fl++ + } - #Get header line - $fl = $fl - 1 + # Get header line + $fl = $fl - 1 - #Get header titles [without remove seperator] - $index = $lines[$fl] -split '(?<=\s)(?!\s)' + # Get header titles [without remove seperator] + $index = $lines[$fl] -split '(?<=\s)(?!\s)' - # Line $fl has the header, we can find char where we find ID and Version [and manage non latin characters] - $idStart = $($index[0] -replace '[\u4e00-\u9fa5]', '**').Length - $versionStart = $idStart + $($index[1] -replace '[\u4e00-\u9fa5]', '**').Length - $availableStart = $versionStart + $($index[2] -replace '[\u4e00-\u9fa5]', '**').Length + # Line $fl has the header, we can find char where we find ID and Version [and manage non latin characters] + $idStart = $($index[0] -replace '[\u4e00-\u9fa5]', '**').Length + $versionStart = $idStart + $($index[1] -replace '[\u4e00-\u9fa5]', '**').Length + $availableStart = $versionStart + $($index[2] -replace '[\u4e00-\u9fa5]', '**').Length - # Now cycle in real package and split accordingly - $upgradeList = @() - For ($i = $fl + 2; $i -lt $lines.Length; $i++) { - $line = $lines[$i] -replace "[\u2026]", " " #Fix "..." in long names - if ($line.StartsWith("-----")) { - #Get header line - $fl = $i - 1 + # Now cycle in real package and split accordingly + $upgradeList = @() - #Get header titles [without remove seperator] - $index = $lines[$fl] -split '(?<=\s)(?!\s)' + for ($i = $fl + 2; $i -lt $lines.Length; $i++) + { + $line = $lines[$i] -replace '[\u2026]', ' ' #Fix "..." in long names - # Line $fl has the header, we can find char where we find ID and Version [and manage non latin characters] - $idStart = $($index[0] -replace '[\u4e00-\u9fa5]', '**').Length - $versionStart = $idStart + $($index[1] -replace '[\u4e00-\u9fa5]', '**').Length - $availableStart = $versionStart + $($index[2] -replace '[\u4e00-\u9fa5]', '**').Length - } - #(Alphanumeric | Literal . | Alphanumeric) - the only unique thing in common for lines with applications - if ($line -match "\w\.\w") { - $software = [Software]::new() - #Manage non latin characters - $nameDeclination = $($line.Substring(0, $idStart) -replace '[\u4e00-\u9fa5]', '**').Length - $line.Substring(0, $idStart).Length - $software.Name = $line.Substring(0, $idStart - $nameDeclination).TrimEnd() - $software.Id = $line.Substring($idStart - $nameDeclination, $versionStart - $idStart).TrimEnd() - $software.Version = $line.Substring($versionStart - $nameDeclination, $availableStart - $versionStart).TrimEnd() - $software.AvailableVersion = $line.Substring($availableStart - $nameDeclination).TrimEnd() - #add formated soft to list - $upgradeList += $software - } - } + if ($line.StartsWith('-----')) + { + # Get header line + $fl = $i - 1 - #If current user is not system, remove system apps from list - if ($IsSystem -eq $false) { - $SystemApps = Get-Content -Path "$WorkingDir\winget_system_apps.txt" - $upgradeList = $upgradeList | Where-Object { $SystemApps -notcontains $_.Id } - } + # Get header titles [without remove seperator] + $index = $lines[$fl] -split '(?<=\s)(?!\s)' - return $upgradeList | Sort-Object { Get-Random } + # Line $fl has the header, we can find char where we find ID and Version [and manage non latin characters] + $idStart = $($index[0] -replace '[\u4e00-\u9fa5]', '**').Length + $versionStart = $idStart + $($index[1] -replace '[\u4e00-\u9fa5]', '**').Length + $availableStart = $versionStart + $($index[2] -replace '[\u4e00-\u9fa5]', '**').Length + } + + # (Alphanumeric | Literal . | Alphanumeric) - the only unique thing in common for lines with applications + if ($line -match '\w\.\w') + { + $software = [Software]::new() + # Manage non latin characters + $nameDeclination = $($line.Substring(0, $idStart) -replace '[\u4e00-\u9fa5]', '**').Length - $line.Substring(0, $idStart).Length + $software.Name = $line.Substring(0, $idStart - $nameDeclination).TrimEnd() + $software.Id = $line.Substring($idStart - $nameDeclination, $versionStart - $idStart).TrimEnd() + $software.Version = $line.Substring($versionStart - $nameDeclination, $availableStart - $versionStart).TrimEnd() + $software.AvailableVersion = $line.Substring($availableStart - $nameDeclination).TrimEnd() + # add formated soft to list + $upgradeList += $software + } + } + + # If current user is not system, remove system apps from list + if ($IsSystem -eq $false) + { + $SystemApps = Get-Content -Path ('{0}\winget_system_apps.txt' -f $WorkingDir) + $upgradeList = $upgradeList | Where-Object -FilterScript { + $SystemApps -notcontains $_.Id + } + } + + return $upgradeList | Sort-Object -Property { + Get-Random + } } diff --git a/Winget-AutoUpdate/functions/Get-WingetSystemApps.ps1 b/Winget-AutoUpdate/functions/Get-WingetSystemApps.ps1 index 8f653ea..e7df94b 100644 --- a/Winget-AutoUpdate/functions/Get-WingetSystemApps.ps1 +++ b/Winget-AutoUpdate/functions/Get-WingetSystemApps.ps1 @@ -1,18 +1,17 @@ -function Get-WingetSystemApps { +function Get-WingetSystemApps +{ + # Json File, where to export system installed apps + $jsonFile = ('{0}\winget_system_apps.txt' -f $WorkingDir) - #Json File, where to export system installed apps - $jsonFile = "$WorkingDir\winget_system_apps.txt" + # Get list of installed Winget apps to json file + $null = (& $Winget export -o $jsonFile --accept-source-agreements -s winget) - #Get list of installed Winget apps to json file - & $Winget export -o $jsonFile --accept-source-agreements -s winget | Out-Null + # Convert json file to txt file with app ids + $InstalledApps = (Get-Content -Path $jsonFile | ConvertFrom-Json) - #Convert json file to txt file with app ids - $InstalledApps = get-content $jsonFile | ConvertFrom-Json - - #Save app list - Set-Content $InstalledApps.Sources.Packages.PackageIdentifier -Path $jsonFile - - #Sort app list - Get-Content $jsonFile | Sort-Object | Set-Content $jsonFile + # Save app list + $null = (Set-Content -Value $InstalledApps.Sources.Packages.PackageIdentifier -Path $jsonFile -Force -Confirm:$False -ErrorAction SilentlyContinue) + # Sort app list + $null = (Get-Content -Path $jsonFile | Sort-Object | Set-Content -Path $jsonFile -Force -Confirm:$False -ErrorAction SilentlyContinue) } diff --git a/Winget-AutoUpdate/functions/Invoke-LogRotation.ps1 b/Winget-AutoUpdate/functions/Invoke-LogRotation.ps1 index 82edf17..35d17c8 100644 --- a/Winget-AutoUpdate/functions/Invoke-LogRotation.ps1 +++ b/Winget-AutoUpdate/functions/Invoke-LogRotation.ps1 @@ -1,95 +1,118 @@ -#Function to rotate the logs +# Function to rotate the logs -function Invoke-LogRotation ($LogFile, $MaxLogFiles, $MaxLogSize) { - <# - .SYNOPSIS - Handle log rotation. - .DESCRIPTION - Invoke-LogRotation handles log rotation - .NOTES - Author: Øyvind Kallstad (Minimized and changed for WAU 12.01.2023 by Göran Axel Johannesson) - URL: https://www.powershellgallery.com/packages/Communary.Logger/1.1 - Date: 21.11.2014 - Version: 1.0 - #> +function Invoke-LogRotation +{ + <# + .SYNOPSIS + Handle log rotation. + .DESCRIPTION + Invoke-LogRotation handles log rotation + .NOTES + Author: Øyvind Kallstad (Minimized and changed for WAU 12.01.2023 by Göran Axel Johannesson) + URL: https://www.powershellgallery.com/packages/Communary.Logger/1.1 + Date: 21.11.2014 + Version: 1.0 + #> + param + ( + [string] + $LogFile, + [int] + $MaxLogFiles, + [int] + $MaxLogSize + ) - try { - # get current size of log file - $currentSize = (Get-Item $LogFile).Length + try + { + # get current size of log file + $currentSize = (Get-Item -Path $LogFile).Length - # get log name - $logFileName = Split-Path $LogFile -Leaf - $logFilePath = Split-Path $LogFile - $logFileNameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($logFileName) - $logFileNameExtension = [System.IO.Path]::GetExtension($logFileName) + # get log name + $logFileName = (Split-Path -Path $LogFile -Leaf) + $logFilePath = (Split-Path -Path $LogFile) + $logFileNameWithoutExtension = [IO.Path]::GetFileNameWithoutExtension($logFileName) + $logFileNameExtension = [IO.Path]::GetExtension($logFileName) - # if MaxLogFiles is 1 just keep the original one and let it grow - if (-not($MaxLogFiles -eq 1)) { - if ($currentSize -ge $MaxLogSize) { + # if MaxLogFiles is 1 just keep the original one and let it grow + if (-not ($MaxLogFiles -eq 1)) + { + if ($currentSize -ge $MaxLogSize) + { + # construct name of archived log file + $newLogFileName = $logFileNameWithoutExtension + (Get-Date -Format 'yyyyMMddHHmmss').ToString() + $logFileNameExtension - # construct name of archived log file - $newLogFileName = $logFileNameWithoutExtension + (Get-Date -Format 'yyyyMMddHHmmss').ToString() + $logFileNameExtension + # copy old log file to new using the archived name constructed above + $null = (Copy-Item -Path $LogFile -Destination (Join-Path -Path (Split-Path -Path $LogFile) -ChildPath $newLogFileName)) - # copy old log file to new using the archived name constructed above - Copy-Item -Path $LogFile -Destination (Join-Path (Split-Path $LogFile) $newLogFileName) - - # Create a new log file - try { - Remove-Item -Path $LogFile -Force - New-Item -ItemType File -Path $LogFile -Force - #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 - } - catch { - Return $False - } - - # if MaxLogFiles is 0 don't delete any old archived log files - if (-not($MaxLogFiles -eq 0)) { - - # set filter to search for archived log files - $archivedLogFileFilter = $logFileNameWithoutExtension + '??????????????' + $logFileNameExtension - - # get archived log files - $oldLogFiles = Get-Item -Path "$(Join-Path -Path $logFilePath -ChildPath $archivedLogFileFilter)" - - if ([bool]$oldLogFiles) { - # compare found log files to MaxLogFiles parameter of the log object, and delete oldest until we are - # back to the correct number - if (($oldLogFiles.Count + 1) -gt $MaxLogFiles) { - [int]$numTooMany = (($oldLogFiles.Count) + 1) - $MaxLogFiles - $oldLogFiles | Sort-Object 'LastWriteTime' | Select-Object -First $numTooMany | Remove-Item - } - } - } - - #Log Header - $Log = "##################################################`n# CHECK FOR APP UPDATES - $(Get-Date -Format (Get-culture).DateTimeFormat.ShortDatePattern)`n##################################################" - $Log | out-file -filepath $LogFile -Append - Write-ToLog "Running in System context" - if ($ActivateGPOManagement) { - Write-ToLog "Activated WAU GPO Management detected, comparing..." - if ($null -ne $ChangedSettings -and $ChangedSettings -ne 0) { - Write-ToLog "Changed settings detected and applied" "Yellow" - } - else { - Write-ToLog "No Changed settings detected" "Yellow" - } - } - Write-ToLog "Max Log Size reached: $MaxLogSize bytes - Rotated Logs" - - Return $True + # Create a new log file + try + { + $null = (Remove-Item -Path $LogFile -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-Item -ItemType File -Path $LogFile -Force -Confirm:$False -ErrorAction SilentlyContinue) + # Set ACL for users on logfile + $NewAcl = (Get-Acl -Path $LogFile) + $identity = (New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList 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) + $null = (Set-Acl -Path $LogFile -AclObject $NewAcl) } - } - } - catch { - Return $False - } + catch + { + return $False + } + + # if MaxLogFiles is 0 don't delete any old archived log files + if (-not ($MaxLogFiles -eq 0)) + { + # set filter to search for archived log files + $archivedLogFileFilter = $logFileNameWithoutExtension + '??????????????' + $logFileNameExtension + + # get archived log files + $oldLogFiles = (Get-Item -Path "$(Join-Path -Path $logFilePath -ChildPath $archivedLogFileFilter)") + + if ([bool]$oldLogFiles) + { + # compare found log files to MaxLogFiles parameter of the log object, and delete oldest until we are + # back to the correct number + if (($oldLogFiles.Count + 1) -gt $MaxLogFiles) + { + [int]$numTooMany = (($oldLogFiles.Count) + 1) - $MaxLogFiles + $null = ($oldLogFiles | Sort-Object -Property 'LastWriteTime' | Select-Object -First $numTooMany | Remove-Item -Force -Confirm:$False -ErrorAction SilentlyContinue) + } + } + } + + # Log Header + $Log = "##################################################`n# CHECK FOR APP UPDATES - $(Get-Date -Format (Get-Culture).DateTimeFormat.ShortDatePattern)`n##################################################" + $null = ($Log | Out-File -FilePath $LogFile -Append -Force) + Write-ToLog -LogMsg 'Running in System context' + + if ($ActivateGPOManagement) + { + Write-ToLog -LogMsg 'Activated WAU GPO Management detected, comparing...' + + if ($null -ne $ChangedSettings -and $ChangedSettings -ne 0) + { + Write-ToLog -LogMsg 'Changed settings detected and applied' -LogColor 'Yellow' + } + else + { + Write-ToLog -LogMsg 'No Changed settings detected' -LogColor 'Yellow' + } + } + + Write-ToLog -LogMsg ('Max Log Size reached: {0} bytes - Rotated Logs' -f $MaxLogSize) + + return $True + } + } + } + catch + { + return $False + } } diff --git a/Winget-AutoUpdate/functions/Invoke-ModsProtect.ps1 b/Winget-AutoUpdate/functions/Invoke-ModsProtect.ps1 index 1b56707..2e8fad2 100644 --- a/Winget-AutoUpdate/functions/Invoke-ModsProtect.ps1 +++ b/Winget-AutoUpdate/functions/Invoke-ModsProtect.ps1 @@ -1,65 +1,82 @@ -#Function to check if the mods directory is secured. -#Security: Mods directory must be protected (Users could create scripts of their own - then they'll run in System Context)! -#Check if Local Users have write rights in Mods directory or not (and take action if necessary): +# Function to check if the mods directory is secured. +# Security: Mods directory must be protected (Users could create scripts of their own - then they'll run in System Context)! +# Check if Local Users have write rights in Mods directory or not (and take action if necessary): -function Invoke-ModsProtect ($ModsPath) { - try { - $directory = Get-Item -Path $ModsPath -ErrorAction SilentlyContinue - $acl = Get-Acl -Path $directory.FullName - #Local Users - S-1-5-32-545 - $userSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-545") - #Translate SID to Locale Name - $ntAccount = $userSID.Translate([System.Security.Principal.NTAccount]) - $userName = $ntAccount.Value - $userRights = [System.Security.AccessControl.FileSystemRights]"Write" +function Invoke-ModsProtect +{ + [CmdletBinding()] + param + ( + [string] + $ModsPath + ) - $hasWriteAccess = $False + try + { + $directory = (Get-Item -Path $ModsPath -ErrorAction SilentlyContinue) + $acl = (Get-Acl -Path $directory.FullName) + # Local Users - S-1-5-32-545 + $userSID = (New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList ('S-1-5-32-545')) + # Translate SID to Locale Name + $ntAccount = $userSID.Translate([Security.Principal.NTAccount]) + $userName = $ntAccount.Value + $userRights = [Security.AccessControl.FileSystemRights]'Write' + $hasWriteAccess = $False - foreach ($access in $acl.Access) { - if ($access.IdentityReference.Value -eq $userName -and $access.FileSystemRights -eq $userRights) { - $hasWriteAccess = $True - break - } - } + foreach ($access in $acl.Access) + { + if ($access.IdentityReference.Value -eq $userName -and $access.FileSystemRights -eq $userRights) + { + $hasWriteAccess = $True + break + } + } - if ($hasWriteAccess) { - #Disable inheritance - $acl.SetAccessRuleProtection($True, $True) - # Remove any existing rules - $acl.Access | ForEach-Object { $acl.RemoveAccessRule($_) } - #SYSTEM Full - S-1-5-18 - $userSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-18") - $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($userSID, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow") - $acl.SetAccessRule($rule) - # Save the updated ACL - Set-Acl -Path $directory.FullName -AclObject $acl + if ($hasWriteAccess) + { + # Disable inheritance + $acl.SetAccessRuleProtection($True, $True) - #Administrators Full - S-1-5-32-544 - $acl = Get-Acl -Path $directory.FullName - $userSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544") - $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($userSID, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow") - $acl.SetAccessRule($rule) - Set-Acl -Path $directory.FullName -AclObject $acl + # Remove any existing rules + $acl.Access | ForEach-Object -Process { + $acl.RemoveAccessRule($_) + } - #Local Users ReadAndExecute - S-1-5-32-545 S-1-5-11 - $acl = Get-Acl -Path $directory.FullName - $userSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-545") - $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($userSID, "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow") - $acl.SetAccessRule($rule) - Set-Acl -Path $directory.FullName -AclObject $acl + # SYSTEM Full - S-1-5-18 + $userSID = (New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList ('S-1-5-18')) + $rule = (New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList ($userSID, 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow')) + $acl.SetAccessRule($rule) + # Save the updated ACL + $null = (Set-Acl -Path $directory.FullName -AclObject $acl) - #Authenticated Users ReadAndExecute - S-1-5-11 - $acl = Get-Acl -Path $directory.FullName - $userSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-11") - $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($userSID, "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow") - $acl.SetAccessRule($rule) - Set-Acl -Path $directory.FullName -AclObject $acl + # Administrators Full - S-1-5-32-544 + $acl = (Get-Acl -Path $directory.FullName) + $userSID = (New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList ('S-1-5-32-544')) + $rule = (New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList ($userSID, 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow')) + $acl.SetAccessRule($rule) + $null = (Set-Acl -Path $directory.FullName -AclObject $acl) - return $True - } - return $False - } - catch { - return "Error" - } -} \ No newline at end of file + # Local Users ReadAndExecute - S-1-5-32-545 S-1-5-11 + $acl = (Get-Acl -Path $directory.FullName) + $userSID = (New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList ('S-1-5-32-545')) + $rule = (New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList ($userSID, 'ReadAndExecute', 'ContainerInherit,ObjectInherit', 'None', 'Allow')) + $acl.SetAccessRule($rule) + $null = (Set-Acl -Path $directory.FullName -AclObject $acl) + + # Authenticated Users ReadAndExecute - S-1-5-11 + $acl = (Get-Acl -Path $directory.FullName) + $userSID = (New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList ('S-1-5-11')) + $rule = (New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList ($userSID, 'ReadAndExecute', 'ContainerInherit,ObjectInherit', 'None', 'Allow')) + $acl.SetAccessRule($rule) + $null = (Set-Acl -Path $directory.FullName -AclObject $acl) + + return $True + } + + return $False + } + catch + { + return 'Error' + } +} diff --git a/Winget-AutoUpdate/functions/Invoke-PostUpdateActions.ps1 b/Winget-AutoUpdate/functions/Invoke-PostUpdateActions.ps1 index 2637718..f839679 100644 --- a/Winget-AutoUpdate/functions/Invoke-PostUpdateActions.ps1 +++ b/Winget-AutoUpdate/functions/Invoke-PostUpdateActions.ps1 @@ -1,231 +1,289 @@ -#Function to make actions after WAU update +# Function to make actions after WAU update -function Invoke-PostUpdateActions { +function Invoke-PostUpdateActions +{ + # log + Write-ToLog -LogMsg 'Running Post Update actions:' -LogColor 'yellow' - #log - Write-ToLog "Running Post Update actions:" "yellow" + # Check if Intune Management Extension Logs folder and WAU-updates.log exists, make symlink + if ((Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs" -ErrorAction SilentlyContinue) -and !(Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -ErrorAction SilentlyContinue)) + { + Write-ToLog -LogMsg '-> Creating SymLink for log file in Intune Management Extension log folder' -LogColor 'yellow' + $null = New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -ItemType SymbolicLink -Value $LogFile -Force -ErrorAction SilentlyContinue + } - #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-ToLog "-> Creating SymLink for log file in Intune Management Extension log folder" "yellow" - New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -ItemType SymbolicLink -Value $LogFile -Force -ErrorAction SilentlyContinue | Out-Null - } - #Check if Intune Management Extension Logs folder and WAU-install.log exists, make symlink - if ((Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs") -and (Test-Path "$WorkingDir\logs\install.log") -and !(Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log")) { - Write-host "`nCreating SymLink for log file (WAU-install) in Intune Management Extension log folder" -ForegroundColor Yellow - New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -ItemType SymbolicLink -Value "$WorkingDir\logs\install.log" -Force -ErrorAction SilentlyContinue | Out-Null - } + # Check if Intune Management Extension Logs folder and WAU-install.log exists, make symlink + if ((Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs" -ErrorAction SilentlyContinue) -and (Test-Path -Path ('{0}\logs\install.log' -f $WorkingDir) -ErrorAction SilentlyContinue) -and !(Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -ErrorAction SilentlyContinue)) + { + Write-Host -Object "`nCreating SymLink for log file (WAU-install) in Intune Management Extension log folder" -ForegroundColor Yellow + $null = (New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -ItemType SymbolicLink -Value ('{0}\logs\install.log' -f $WorkingDir) -Force -Confirm:$False -ErrorAction SilentlyContinue) + } - Write-ToLog "-> Checking prerequisites..." "yellow" + Write-ToLog -LogMsg '-> Checking prerequisites...' -LogColor 'yellow' - #Check if Visual C++ 2019 or 2022 installed - $Visual2019 = "Microsoft Visual C++ 2015-2019 Redistributable*" - $Visual2022 = "Microsoft Visual C++ 2015-2022 Redistributable*" - $path = Get-Item HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Where-Object { $_.GetValue("DisplayName") -like $Visual2019 -or $_.GetValue("DisplayName") -like $Visual2022 } + # Check if Visual C++ 2019 or 2022 installed + $Visual2019 = 'Microsoft Visual C++ 2015-2019 Redistributable*' + $Visual2022 = 'Microsoft Visual C++ 2015-2022 Redistributable*' + $path = (Get-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' -ErrorAction SilentlyContinue | Where-Object -FilterScript { + $_.GetValue('DisplayName') -like $Visual2019 -or $_.GetValue('DisplayName') -like $Visual2022 + }) - #If not installed, install - if (!($path)) { - try { - if ((Get-CimInStance Win32_OperatingSystem).OSArchitecture -like "*64*") { - $OSArch = "x64" - } - else { - $OSArch = "x86" - } - Write-ToLog "-> Downloading VC_redist.$OSArch.exe..." - $SourceURL = "https://aka.ms/vs/17/release/VC_redist.$OSArch.exe" - $Installer = "$($WAUConfig.InstallLocation)\VC_redist.$OSArch.exe" - $ProgressPreference = 'SilentlyContinue' - Invoke-WebRequest $SourceURL -UseBasicParsing -OutFile (New-Item -Path $Installer -Force) - Write-ToLog "-> Installing VC_redist.$OSArch.exe..." - Start-Process -FilePath $Installer -Args "/quiet /norestart" -Wait - Remove-Item $Installer -ErrorAction Ignore - Write-ToLog "-> MS Visual C++ 2015-2022 installed successfully" "green" - } - catch { - Write-ToLog "-> MS Visual C++ 2015-2022 installation failed." "red" - } - } - else { - Write-ToLog "-> Prerequisites checked. OK" "green" - } + # If not installed, install + if (!($path)) + { + try + { + if ((Get-CimInstance -ClassName Win32_OperatingSystem).OSArchitecture -like '*64*') + { + $OSArch = 'x64' + } + else + { + $OSArch = 'x86' + } - #Check Package Install - Write-ToLog "-> Checking if Winget is installed/up to date" "yellow" - $TestWinGet = Get-AppxProvisionedPackage -Online | Where-Object { $_.DisplayName -eq "Microsoft.DesktopAppInstaller" } + Write-ToLog -LogMsg ('-> Downloading VC_redist.{0}.exe...' -f $OSArch) + $SourceURL = ('https://aka.ms/vs/17/release/VC_redist.{0}.exe' -f $OSArch) + $Installer = ('{0}\VC_redist.{1}.exe' -f $WAUConfig.InstallLocation, $OSArch) + $ProgressPreference = 'SilentlyContinue' + $null = (Invoke-WebRequest -Uri $SourceURL -UseBasicParsing -OutFile (New-Item -Path $Installer -Force)) + Write-ToLog -LogMsg ('-> Installing VC_redist.{0}.exe...' -f $OSArch) + Start-Process -FilePath $Installer -ArgumentList '/quiet /norestart' -Wait + Remove-Item -Path $Installer -ErrorAction Ignore + Write-ToLog -LogMsg '-> MS Visual C++ 2015-2022 installed successfully' -LogColor 'green' + } + catch + { + Write-ToLog -LogMsg '-> MS Visual C++ 2015-2022 installation failed.' -LogColor 'red' + } + } + else + { + Write-ToLog -LogMsg '-> Prerequisites checked. OK' -LogColor 'green' + } - #Current: v1.5.2201 = 1.20.2201.0 = 2023.808.2243.0 - If ([Version]$TestWinGet.Version -ge "2023.808.2243.0") { + # Check Package Install + Write-ToLog -LogMsg '-> Checking if Winget is installed/up to date' -LogColor 'yellow' + $TestWinGet = Get-AppxProvisionedPackage -Online | Where-Object -FilterScript { + $_.DisplayName -eq 'Microsoft.DesktopAppInstaller' + } - Write-ToLog "-> WinGet is Installed/up to date" "green" + # Current: v1.5.2201 = 1.20.2201.0 = 2023.808.2243.0 + if ([Version]$TestWinGet.Version -ge '2023.808.2243.0') + { + Write-ToLog -LogMsg '-> WinGet is Installed/up to date' -LogColor 'green' + } + else + { + # Download WinGet MSIXBundle + Write-ToLog -LogMsg '-> Not installed/up to date. Downloading WinGet...' + $WinGetURL = 'https://github.com/microsoft/winget-cli/releases/download/v1.5.2201/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle' + $WebClient = New-Object -TypeName System.Net.WebClient + $WebClient.DownloadFile($WinGetURL, ('{0}\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle' -f $WAUConfig.InstallLocation)) - } - Else { + # Install WinGet MSIXBundle + try + { + Write-ToLog -LogMsg '-> Installing Winget MSIXBundle for App Installer...' + $null = Add-AppxProvisionedPackage -Online -PackagePath ('{0}\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle' -f $WAUConfig.InstallLocation) -SkipLicense + Write-ToLog -LogMsg '-> Installed Winget MSIXBundle for App Installer' -LogColor 'green' + } + catch + { + Write-ToLog -LogMsg '-> Failed to intall Winget MSIXBundle for App Installer...' -LogColor 'red' + } - #Download WinGet MSIXBundle - Write-ToLog "-> Not installed/up to date. Downloading WinGet..." - $WinGetURL = "https://github.com/microsoft/winget-cli/releases/download/v1.5.2201/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" - $WebClient = New-Object System.Net.WebClient - $WebClient.DownloadFile($WinGetURL, "$($WAUConfig.InstallLocation)\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle") + # Remove WinGet MSIXBundle + Remove-Item -Path ('{0}\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle' -f $WAUConfig.InstallLocation) -Force -Confirm:$False -ErrorAction Continue + } - #Install WinGet MSIXBundle - try { - Write-ToLog "-> Installing Winget MSIXBundle for App Installer..." - Add-AppxProvisionedPackage -Online -PackagePath "$($WAUConfig.InstallLocation)\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -SkipLicense | Out-Null - Write-ToLog "-> Installed Winget MSIXBundle for App Installer" "green" - } - catch { - Write-ToLog "-> Failed to intall Winget MSIXBundle for App Installer..." "red" - } + # Reset Winget Sources + $ResolveWingetPath = Resolve-Path -Path "$env:programfiles\WindowsApps\Microsoft.DesktopAppInstaller_*_*__8wekyb3d8bbwe\winget.exe" | Sort-Object -Property { + [version]($_.Path -replace '^[^\d]+_((\d+\.)*\d+)_.*', '$1') + } - #Remove WinGet MSIXBundle - Remove-Item -Path "$($WAUConfig.InstallLocation)\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -Force -ErrorAction Continue + if ($ResolveWingetPath) + { + # If multiple version, pick last one + $WingetPath = $ResolveWingetPath[-1].Path + & $WingetPath source reset --force - } + # log + Write-ToLog -LogMsg '-> Winget sources reseted.' -LogColor 'green' + } - #Reset Winget Sources - $ResolveWingetPath = Resolve-Path "$env:programfiles\WindowsApps\Microsoft.DesktopAppInstaller_*_*__8wekyb3d8bbwe\winget.exe" | Sort-Object { [version]($_.Path -replace '^[^\d]+_((\d+\.)*\d+)_.*', '$1') } - if ($ResolveWingetPath) { - #If multiple version, pick last one - $WingetPath = $ResolveWingetPath[-1].Path - & $WingetPath source reset --force + # Create WAU Regkey if not present + $regPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate' - #log - Write-ToLog "-> Winget sources reseted." "green" - } + if (!(Test-Path -Path $regPath -ErrorAction SilentlyContinue)) + { + $null = (New-Item -Path $regPath -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name DisplayName -Value 'Winget-AutoUpdate (WAU)' -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name DisplayIcon -Value 'C:\Windows\System32\shell32.dll,-16739' -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name NoModify -Value 1 -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name NoRepair -Value 1 -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name Publisher -Value 'Romanitho' -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name URLInfoAbout -Value 'https://github.com/Romanitho/Winget-AutoUpdate' -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name InstallLocation -Value $WorkingDir -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name UninstallString -Value "powershell.exe -noprofile -executionpolicy bypass -file `"$WorkingDir\WAU-Uninstall.ps1`"" -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name QuietUninstallString -Value "powershell.exe -noprofile -executionpolicy bypass -file `"$WorkingDir\WAU-Uninstall.ps1`"" -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatePrerelease -Value 0 -PropertyType DWord -Force -Confirm:$False -ErrorAction SilentlyContinue) - #Create WAU Regkey if not present - $regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" - if (!(test-path $regPath)) { - New-Item $regPath -Force - New-ItemProperty $regPath -Name DisplayName -Value "Winget-AutoUpdate (WAU)" -Force - New-ItemProperty $regPath -Name DisplayIcon -Value "C:\Windows\System32\shell32.dll,-16739" -Force - New-ItemProperty $regPath -Name NoModify -Value 1 -Force - New-ItemProperty $regPath -Name NoRepair -Value 1 -Force - New-ItemProperty $regPath -Name Publisher -Value "Romanitho" -Force - New-ItemProperty $regPath -Name URLInfoAbout -Value "https://github.com/Romanitho/Winget-AutoUpdate" -Force - New-ItemProperty $regPath -Name InstallLocation -Value $WorkingDir -Force - New-ItemProperty $regPath -Name UninstallString -Value "powershell.exe -noprofile -executionpolicy bypass -file `"$WorkingDir\WAU-Uninstall.ps1`"" -Force - New-ItemProperty $regPath -Name QuietUninstallString -Value "powershell.exe -noprofile -executionpolicy bypass -file `"$WorkingDir\WAU-Uninstall.ps1`"" -Force - New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value 0 -PropertyType DWord -Force + #log + Write-ToLog -LogMsg ('-> {0} created.' -f $regPath) -LogColor 'green' + } - #log - Write-ToLog "-> $regPath created." "green" - } - #Fix Notif where WAU_NotificationLevel is not set - $regNotif = Get-ItemProperty $regPath -Name WAU_NotificationLevel -ErrorAction SilentlyContinue - if (!$regNotif) { - New-ItemProperty $regPath -Name WAU_NotificationLevel -Value Full -Force + # Fix Notif where WAU_NotificationLevel is not set + $regNotif = Get-ItemProperty -Path $regPath -Name WAU_NotificationLevel -ErrorAction SilentlyContinue - #log - Write-ToLog "-> Notification level setting was missing. Fixed with 'Full' option." - } + if (!$regNotif) + { + New-ItemProperty -Path $regPath -Name WAU_NotificationLevel -Value Full -Force - #Set WAU_MaxLogFiles/WAU_MaxLogSize if not set - $MaxLogFiles = Get-ItemProperty $regPath -Name WAU_MaxLogFiles -ErrorAction SilentlyContinue - if (!$MaxLogFiles) { - New-ItemProperty $regPath -Name WAU_MaxLogFiles -Value 3 -PropertyType DWord -Force | Out-Null - New-ItemProperty $regPath -Name WAU_MaxLogSize -Value 1048576 -PropertyType DWord -Force | Out-Null + # log + Write-ToLog -LogMsg "-> Notification level setting was missing. Fixed with 'Full' option." + } - #log - Write-ToLog "-> MaxLogFiles/MaxLogSize setting was missing. Fixed with 3/1048576 (in bytes, default is 1048576 = 1 MB)." - } + # Set WAU_MaxLogFiles/WAU_MaxLogSize if not set + $MaxLogFiles = Get-ItemProperty -Path $regPath -Name WAU_MaxLogFiles -ErrorAction SilentlyContinue - #Set WAU_ListPath if not set - $ListPath = Get-ItemProperty $regPath -Name WAU_ListPath -ErrorAction SilentlyContinue - if (!$ListPath) { - New-ItemProperty $regPath -Name WAU_ListPath -Force | Out-Null + if (!$MaxLogFiles) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_MaxLogFiles -Value 3 -PropertyType DWord -Force -Confirm:$False -ErrorAction SilentlyContinue) + $null = (New-ItemProperty -Path $regPath -Name WAU_MaxLogSize -Value 1048576 -PropertyType DWord -Force -Confirm:$False -ErrorAction SilentlyContinue) - #log - Write-ToLog "-> ListPath setting was missing. Fixed with empty string." - } + # log + Write-ToLog -LogMsg '-> MaxLogFiles/MaxLogSize setting was missing. Fixed with 3/1048576 (in bytes, default is 1048576 = 1 MB).' + } - #Set WAU_ModsPath if not set - $ModsPath = Get-ItemProperty $regPath -Name WAU_ModsPath -ErrorAction SilentlyContinue - if (!$ModsPath) { - New-ItemProperty $regPath -Name WAU_ModsPath -Force | Out-Null + # Set WAU_ListPath if not set + $ListPath = Get-ItemProperty -Path $regPath -Name WAU_ListPath -ErrorAction SilentlyContinue - #log - Write-ToLog "-> ModsPath setting was missing. Fixed with empty string." - } + if (!$ListPath) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_ListPath -Force -Confirm:$False -ErrorAction SilentlyContinue) - #Security check - Write-ToLog "-> Checking Mods Directory:" "yellow" - $Protected = Invoke-ModsProtect "$($WAUConfig.InstallLocation)\mods" - if ($Protected -eq $True) { - Write-ToLog "-> The mods directory is now secured!" "green" - } - elseif ($Protected -eq $False) { - Write-ToLog "-> The mods directory was already secured!" "green" - } - else { - Write-ToLog "-> Error: The mods directory couldn't be verified as secured!" "red" - } + # log + Write-ToLog -LogMsg '-> ListPath setting was missing. Fixed with empty string.' + } - #Convert about.xml if exists (old WAU versions) to reg - $WAUAboutPath = "$WorkingDir\config\about.xml" - if (test-path $WAUAboutPath) { - [xml]$About = Get-Content $WAUAboutPath -Encoding UTF8 -ErrorAction SilentlyContinue - New-ItemProperty $regPath -Name DisplayVersion -Value $About.app.version -Force + # Set WAU_ModsPath if not set + $ModsPath = (Get-ItemProperty -Path $regPath -Name WAU_ModsPath -ErrorAction SilentlyContinue) - #Remove file once converted - Remove-Item $WAUAboutPath -Force -Confirm:$false + if (!$ModsPath) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_ModsPath -Force -Confirm:$False -ErrorAction SilentlyContinue) - #log - Write-ToLog "-> $WAUAboutPath converted." "green" - } + # log + Write-ToLog -LogMsg '-> ModsPath setting was missing. Fixed with empty string.' + } - #Convert config.xml if exists (previous WAU versions) to reg - $WAUConfigPath = "$WorkingDir\config\config.xml" - if (test-path $WAUConfigPath) { - [xml]$Config = Get-Content $WAUConfigPath -Encoding UTF8 -ErrorAction SilentlyContinue - if ($Config.app.WAUautoupdate -eq "False") { New-ItemProperty $regPath -Name WAU_DisableAutoUpdate -Value 1 -Force } - if ($Config.app.NotificationLevel) { New-ItemProperty $regPath -Name WAU_NotificationLevel -Value $Config.app.NotificationLevel -Force } - if ($Config.app.UseWAUWhiteList -eq "True") { New-ItemProperty $regPath -Name WAU_UseWhiteList -Value 1 -PropertyType DWord -Force } - if ($Config.app.WAUprerelease -eq "True") { New-ItemProperty $regPath -Name WAU_UpdatePrerelease -Value 1 -PropertyType DWord -Force } + # Security check + Write-ToLog -LogMsg '-> Checking Mods Directory:' -LogColor 'yellow' + $Protected = Invoke-ModsProtect ('{0}\mods' -f $WAUConfig.InstallLocation) - #Remove file once converted - Remove-Item $WAUConfigPath -Force -Confirm:$false + if ($Protected -eq $True) + { + Write-ToLog -LogMsg '-> The mods directory is now secured!' -LogColor 'green' + } + elseif ($Protected -eq $False) + { + Write-ToLog -LogMsg '-> The mods directory was already secured!' -LogColor 'green' + } + else + { + Write-ToLog -LogMsg "-> Error: The mods directory couldn't be verified as secured!" -LogColor 'red' + } - #log - Write-ToLog "-> $WAUConfigPath converted." "green" - } + # Convert about.xml if exists (old WAU versions) to reg + $WAUAboutPath = ('{0}\config\about.xml' -f $WorkingDir) - #Remove old functions / files - $FileNames = @( - "$WorkingDir\functions\Get-WAUConfig.ps1", - "$WorkingDir\functions\Get-WAUCurrentVersion.ps1", - "$WorkingDir\functions\Get-WAUUpdateStatus.ps1", - "$WorkingDir\functions\Write-Log.ps1", - "$WorkingDir\Version.txt" - ) - foreach ($FileName in $FileNames) { - if (Test-Path $FileName) { - Remove-Item $FileName -Force -Confirm:$false + if (Test-Path -Path $WAUAboutPath -ErrorAction SilentlyContinue) + { + [xml]$About = Get-Content -Path $WAUAboutPath -Encoding UTF8 -ErrorAction SilentlyContinue + $null = (New-ItemProperty -Path $regPath -Name DisplayVersion -Value $About.app.version -Force -Confirm:$False -ErrorAction SilentlyContinue) - #log - Write-ToLog "-> $FileName removed." "green" - } - } + # Remove file once converted + $null = (Remove-Item -Path $WAUAboutPath -Force -Confirm:$False) - #Remove old registry key - $RegistryKeys = @( - "VersionMajor", - "VersionMinor" - ) - foreach ($RegistryKey in $RegistryKeys) { - if (Get-ItemProperty -Path $regPath -Name $RegistryKey -ErrorAction SilentlyContinue) { - Remove-ItemProperty -Path $regPath -Name $RegistryKey - } - } + #log + Write-ToLog -LogMsg ('-> {0} converted.' -f $WAUAboutPath) -LogColor 'green' + } - #Reset WAU_UpdatePostActions Value - $WAUConfig | New-ItemProperty -Name WAU_PostUpdateActions -Value 0 -Force + # Convert config.xml if exists (previous WAU versions) to reg + $WAUConfigPath = ('{0}\config\config.xml' -f $WorkingDir) - #Get updated WAU Config - $Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" + if (Test-Path -Path $WAUConfigPath -ErrorAction SilentlyContinue) + { + [xml]$Config = (Get-Content -Path $WAUConfigPath -Encoding UTF8 -ErrorAction SilentlyContinue) - #log - Write-ToLog "Post Update actions finished" "green" + if ($Config.app.WAUautoupdate -eq 'False') + { + $null = (New-ItemProperty -Path $regPath -Name WAU_DisableAutoUpdate -Value 1 -Force -Confirm:$False -ErrorAction SilentlyContinue) + } + if ($Config.app.NotificationLevel) + { + $null = (New-ItemProperty -Path $regPath -Name WAU_NotificationLevel -Value $Config.app.NotificationLevel -Force -Confirm:$False -ErrorAction SilentlyContinue) + } + + if ($Config.app.UseWAUWhiteList -eq 'True') + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UseWhiteList -Value 1 -PropertyType DWord -Force -Confirm:$False -ErrorAction SilentlyContinue) + } + + if ($Config.app.WAUprerelease -eq 'True') + { + $null = (New-ItemProperty -Path $regPath -Name WAU_UpdatePrerelease -Value 1 -PropertyType DWord -Force -Confirm:$False -ErrorAction SilentlyContinue) + } + + # Remove file once converted + $null = (Remove-Item -Path $WAUConfigPath -Force -Confirm:$False) + + # log + Write-ToLog -LogMsg ('-> {0} converted.' -f $WAUConfigPath) -LogColor 'green' + } + + # Remove old functions / files + $FileNames = @( + ('{0}\functions\Get-WAUConfig.ps1' -f $WorkingDir), + ('{0}\functions\Get-WAUCurrentVersion.ps1' -f $WorkingDir), + ('{0}\functions\Get-WAUUpdateStatus.ps1' -f $WorkingDir), + ('{0}\functions\Write-Log.ps1' -f $WorkingDir), + ('{0}\Version.txt' -f $WorkingDir) + ) + + foreach ($FileName in $FileNames) + { + if (Test-Path -Path $FileName -ErrorAction SilentlyContinue) + { + $null = (Remove-Item -Path $FileName -Force -Confirm:$False -ErrorAction SilentlyContinue) + + # log + Write-ToLog -LogMsg ('-> {0} removed.' -f $FileName) -LogColor 'green' + } + } + + # Remove old registry key + $RegistryKeys = @( + 'VersionMajor', + 'VersionMinor' + ) + + foreach ($RegistryKey in $RegistryKeys) + { + if (Get-ItemProperty -Path $regPath -Name $RegistryKey -ErrorAction SilentlyContinue) + { + $null = (Remove-ItemProperty -Path $regPath -Name $RegistryKey -Force -Confirm:$False -ErrorAction SilentlyContinue) + } + } + + # Reset WAU_UpdatePostActions Value + $null = ($WAUConfig | New-ItemProperty -Name WAU_PostUpdateActions -Value 0 -Force -Confirm:$False -ErrorAction SilentlyContinue) + + # Get updated WAU Config + $Script:WAUConfig = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate') + + # log + Write-ToLog -LogMsg 'Post Update actions finished' -LogColor 'green' } diff --git a/Winget-AutoUpdate/functions/Start-Init.ps1 b/Winget-AutoUpdate/functions/Start-Init.ps1 index b937ceb..9b74de2 100644 --- a/Winget-AutoUpdate/functions/Start-Init.ps1 +++ b/Winget-AutoUpdate/functions/Start-Init.ps1 @@ -1,65 +1,71 @@ # Initialisation -function Start-Init { +function Start-Init +{ + # Config console output encoding + [Console]::OutputEncoding = [Text.Encoding]::UTF8 - #Config console output encoding - [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 + # Workaround for ARM64 (Access Denied / Win32 internal Server error) + $Script:ProgressPreference = 'SilentlyContinue' + $caller = ((Get-ChildItem -Path $MyInvocation.PSCommandPath).Name) - # Workaround for ARM64 (Access Denied / Win32 internal Server error) - $Script:ProgressPreference = 'SilentlyContinue' + 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 = ('{0}\logs\updates.log' -f $WorkingDir) + } + elseif ($caller -eq 'Winget-AutoUpdate-Install.ps1') + { + $Script:LogFile = ('{0}\logs\updates.log' -f $WingetUpdatePath) + } - $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" - } - elseif ($caller -eq "Winget-AutoUpdate-Install.ps1") { - $Script:LogFile = "$WingetUpdatePath\logs\updates.log" - } + if (!(Test-Path -Path $LogFile -ErrorAction SilentlyContinue)) + { + # Create file if doesn't exist + $null = (New-Item -ItemType File -Path $LogFile -Force -Confirm:$false) + # Set ACL for users on logfile + $NewAcl = (Get-Acl -Path $LogFile) + $identity = (New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList 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 + } + elseif ((Test-Path -Path $LogFile -ErrorAction SilentlyContinue) -and ($caller -eq 'Winget-AutoUpdate-Install.ps1')) + { + #Set ACL for users on logfile + $NewAcl = (Get-Acl -Path $LogFile) + $identity = (New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList 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) + $null = (Set-Acl -Path $LogFile -AclObject $NewAcl) + } - if (!(Test-Path $LogFile)) { - #Create file if doesn't exist - New-Item -ItemType File -Path $LogFile -Force | Out-Null + # Check if Intune Management Extension Logs folder and WAU-updates.log exists, make symlink + if ((Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs") -and !(Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log")) + { + Write-Host -Object "`nCreating SymLink for log file (WAU-updates) in Intune Management Extension log folder" -ForegroundColor Yellow + $null = New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -ItemType SymbolicLink -Value $LogFile -Force -ErrorAction SilentlyContinue + } - #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 - } - elseif ((Test-Path $LogFile) -and ($caller -eq "Winget-AutoUpdate-Install.ps1")) { - #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 (WAU-updates) 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 - } - #Check if Intune Management Extension Logs folder and WAU-install.log exists, make symlink - if ((Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs") -and (Test-Path "$WorkingDir\logs\install.log") -and !(Test-Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log")) { - Write-host "`nCreating SymLink for log file (WAU-install) in Intune Management Extension log folder" -ForegroundColor Yellow - New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -ItemType SymbolicLink -Value "$WorkingDir\logs\install.log" -Force -ErrorAction SilentlyContinue | Out-Null - } - - if ($caller -eq "Winget-Upgrade.ps1") { - #Log file - $Log | out-file -filepath $LogFile -Append - } + # Check if Intune Management Extension Logs folder and WAU-install.log exists, make symlink + if ((Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs" -ErrorAction SilentlyContinue) -and (Test-Path -Path ('{0}\logs\install.log' -f $WorkingDir) -ErrorAction SilentlyContinue) -and !(Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -ErrorAction SilentlyContinue)) + { + Write-Host -Object "`nCreating SymLink for log file (WAU-install) in Intune Management Extension log folder" -ForegroundColor Yellow + $null = (New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-install.log" -ItemType SymbolicLink -Value ('{0}\logs\install.log' -f $WorkingDir) -Force -ErrorAction SilentlyContinue) + } + if ($caller -eq 'Winget-Upgrade.ps1') + { + # Log file + $Log | Out-File -FilePath $LogFile -Append -Force + } } diff --git a/Winget-AutoUpdate/functions/Start-NotifTask.ps1 b/Winget-AutoUpdate/functions/Start-NotifTask.ps1 index 6ffae41..4bb561f 100644 --- a/Winget-AutoUpdate/functions/Start-NotifTask.ps1 +++ b/Winget-AutoUpdate/functions/Start-NotifTask.ps1 @@ -1,175 +1,192 @@ -#Function to send the notifications to user +# Function to send the notifications to user -function Start-NotifTask { +function Start-NotifTask +{ + [CmdletBinding()] + param ( + [String] + $Title = 'Winget-AutoUpdate', + [String] + $Message, + [String] + $MessageType, + [String] + $Balise = 'WAU', + [String] + $OnClickAction, + [String] + $Body, + [String] + $Button1Text, + [String] + $Button1Action, + [Switch] + $ButtonDismiss = $false, + [Switch] + $UserRun = $false + ) - param( - [String]$Title = "Winget-AutoUpdate", - [String]$Message, - [String]$MessageType, - [String]$Balise = "WAU", - [String]$OnClickAction, - [String]$Body, - [String]$Button1Text, - [String]$Button1Action, - [Switch]$ButtonDismiss = $false, - [Switch]$UserRun = $false - ) + if (($WAUConfig.WAU_NotificationLevel -eq 'Full') -or ($WAUConfig.WAU_NotificationLevel -eq 'SuccessOnly' -and $MessageType -eq 'Success') -or ($UserRun)) + { + # XML Toast template creation + [xml]$ToastTemplate = New-Object -TypeName system.Xml.XmlDocument + $ToastTemplate.LoadXml("") - if (($WAUConfig.WAU_NotificationLevel -eq "Full") -or ($WAUConfig.WAU_NotificationLevel -eq "SuccessOnly" -and $MessageType -eq "Success") -or ($UserRun)) { + # Creation of visual node + $XMLvisual = $ToastTemplate.CreateElement('visual') - # XML Toast template creation - [xml]$ToastTemplate = New-Object system.Xml.XmlDocument - $ToastTemplate.LoadXml("") + # Creation of a binding node + $XMLbinding = $ToastTemplate.CreateElement('binding') + $null = $XMLvisual.AppendChild($XMLbinding) + $XMLbindingAtt1 = ($ToastTemplate.CreateAttribute('template')) + $XMLbindingAtt1.Value = 'ToastGeneric' + $null = $XMLbinding.Attributes.Append($XMLbindingAtt1) - # Creation of visual node - $XMLvisual = $ToastTemplate.CreateElement("visual") + $XMLimagepath = ('{0}\icons\{1}.png' -f $WorkingDir, $MessageType) + if (Test-Path -Path $XMLimagepath -ErrorAction SilentlyContinue) + { + # Creation of a image node + $XMLimage = $ToastTemplate.CreateElement('image') + $null = $XMLbinding.AppendChild($XMLimage) + $XMLimageAtt1 = $ToastTemplate.CreateAttribute('placement') + $XMLimageAtt1.Value = 'appLogoOverride' + $null = $XMLimage.Attributes.Append($XMLimageAtt1) + $XMLimageAtt2 = $ToastTemplate.CreateAttribute('src') + $XMLimageAtt2.Value = ('{0}\icons\{1}.png' -f $WorkingDir, $MessageType) + $null = $XMLimage.Attributes.Append($XMLimageAtt2) + } - # Creation of a binding node - $XMLbinding = $ToastTemplate.CreateElement("binding") - $XMLvisual.AppendChild($XMLbinding) | Out-Null - $XMLbindingAtt1 = ($ToastTemplate.CreateAttribute("template")) - $XMLbindingAtt1.Value = "ToastGeneric" - $XMLbinding.Attributes.Append($XMLbindingAtt1) | Out-Null + if ($Title) + { + # Creation of a text node + $XMLtitle = $ToastTemplate.CreateElement('text') + $XMLtitleText = $ToastTemplate.CreateTextNode($Title) + $null = $XMLtitle.AppendChild($XMLtitleText) + $null = $XMLbinding.AppendChild($XMLtitle) + } - $XMLimagepath = "$WorkingDir\icons\$MessageType.png" - if (Test-Path $XMLimagepath) { - # Creation of a image node - $XMLimage = $ToastTemplate.CreateElement("image") - $XMLbinding.AppendChild($XMLimage) | Out-Null - $XMLimageAtt1 = $ToastTemplate.CreateAttribute("placement") - $XMLimageAtt1.Value = "appLogoOverride" - $XMLimage.Attributes.Append($XMLimageAtt1) | Out-Null - $XMLimageAtt2 = $ToastTemplate.CreateAttribute("src") - $XMLimageAtt2.Value = "$WorkingDir\icons\$MessageType.png" - $XMLimage.Attributes.Append($XMLimageAtt2) | Out-Null - } + if ($Message) + { + # Creation of a text node + $XMLtext = $ToastTemplate.CreateElement('text') + $XMLtextText = $ToastTemplate.CreateTextNode($Message) + $null = $XMLtext.AppendChild($XMLtextText) + $null = $XMLbinding.AppendChild($XMLtext) + } - if ($Title) { - # Creation of a text node - $XMLtitle = $ToastTemplate.CreateElement("text") - $XMLtitleText = $ToastTemplate.CreateTextNode($Title) - $XMLtitle.AppendChild($XMLtitleText) | Out-Null - $XMLbinding.AppendChild($XMLtitle) | Out-Null - } + if ($Body) + { + # Creation of a group node + $XMLgroup = $ToastTemplate.CreateElement('group') + $null = $XMLbinding.AppendChild($XMLgroup) - if ($Message) { - # Creation of a text node - $XMLtext = $ToastTemplate.CreateElement("text") - $XMLtextText = $ToastTemplate.CreateTextNode($Message) - $XMLtext.AppendChild($XMLtextText) | Out-Null - $XMLbinding.AppendChild($XMLtext) | Out-Null - } + # Creation of a subgroup node + $XMLsubgroup = $ToastTemplate.CreateElement('subgroup') + $null = $XMLgroup.AppendChild($XMLsubgroup) - if ($Body) { - # Creation of a group node - $XMLgroup = $ToastTemplate.CreateElement("group") - $XMLbinding.AppendChild($XMLgroup) | Out-Null + # Creation of a text node + $XMLcontent = $ToastTemplate.CreateElement('text') + $XMLcontentText = $ToastTemplate.CreateTextNode($Body) + $null = $XMLcontent.AppendChild($XMLcontentText) + $null = $XMLsubgroup.AppendChild($XMLcontent) + $XMLcontentAtt1 = $ToastTemplate.CreateAttribute('hint-style') + $XMLcontentAtt1.Value = 'body' + $null = $XMLcontent.Attributes.Append($XMLcontentAtt1) + $XMLcontentAtt2 = $ToastTemplate.CreateAttribute('hint-wrap') + $XMLcontentAtt2.Value = 'true' + $null = $XMLcontent.Attributes.Append($XMLcontentAtt2) + } - # Creation of a subgroup node - $XMLsubgroup = $ToastTemplate.CreateElement("subgroup") - $XMLgroup.AppendChild($XMLsubgroup) | Out-Null + # Creation of actions node + $XMLactions = $ToastTemplate.CreateElement('actions') - # Creation of a text node - $XMLcontent = $ToastTemplate.CreateElement("text") - $XMLcontentText = $ToastTemplate.CreateTextNode($Body) - $XMLcontent.AppendChild($XMLcontentText) | Out-Null - $XMLsubgroup.AppendChild($XMLcontent) | Out-Null - $XMLcontentAtt1 = $ToastTemplate.CreateAttribute("hint-style") - $XMLcontentAtt1.Value = "body" - $XMLcontent.Attributes.Append($XMLcontentAtt1) | Out-Null - $XMLcontentAtt2 = $ToastTemplate.CreateAttribute("hint-wrap") - $XMLcontentAtt2.Value = "true" - $XMLcontent.Attributes.Append($XMLcontentAtt2) | Out-Null - } + if ($Button1Text) + { + # Creation of action node + $XMLaction = $ToastTemplate.CreateElement('action') + $null = $XMLactions.AppendChild($XMLaction) + $XMLactionAtt1 = $ToastTemplate.CreateAttribute('content') + $XMLactionAtt1.Value = $Button1Text + $null = $XMLaction.Attributes.Append($XMLactionAtt1) + if ($Button1Action) + { + $XMLactionAtt2 = $ToastTemplate.CreateAttribute('arguments') + $XMLactionAtt2.Value = $Button1Action + $null = $XMLaction.Attributes.Append($XMLactionAtt2) + $XMLactionAtt3 = $ToastTemplate.CreateAttribute('activationType') + $XMLactionAtt3.Value = 'Protocol' + $null = $XMLaction.Attributes.Append($XMLactionAtt3) + } + } - # Creation of actions node - $XMLactions = $ToastTemplate.CreateElement("actions") + if ($ButtonDismiss) + { + # Creation of action node + $XMLaction = $ToastTemplate.CreateElement('action') + $null = $XMLactions.AppendChild($XMLaction) + $XMLactionAtt1 = $ToastTemplate.CreateAttribute('content') + $XMLactionAtt1.Value = '' + $null = $XMLaction.Attributes.Append($XMLactionAtt1) + $XMLactionAtt2 = $ToastTemplate.CreateAttribute('arguments') + $XMLactionAtt2.Value = 'dismiss' + $null = $XMLaction.Attributes.Append($XMLactionAtt2) + $XMLactionAtt3 = $ToastTemplate.CreateAttribute('activationType') + $XMLactionAtt3.Value = 'system' + $null = $XMLaction.Attributes.Append($XMLactionAtt3) + } - if ($Button1Text) { - # Creation of action node - $XMLaction = $ToastTemplate.CreateElement("action") - $XMLactions.AppendChild($XMLaction) | Out-Null - $XMLactionAtt1 = $ToastTemplate.CreateAttribute("content") - $XMLactionAtt1.Value = $Button1Text - $XMLaction.Attributes.Append($XMLactionAtt1) | Out-Null - if ($Button1Action) { - $XMLactionAtt2 = $ToastTemplate.CreateAttribute("arguments") - $XMLactionAtt2.Value = $Button1Action - $XMLaction.Attributes.Append($XMLactionAtt2) | Out-Null - $XMLactionAtt3 = $ToastTemplate.CreateAttribute("activationType") - $XMLactionAtt3.Value = "Protocol" - $XMLaction.Attributes.Append($XMLactionAtt3) | Out-Null - } - } + # Creation of tag node + $XMLtag = $ToastTemplate.CreateElement('tag') + $XMLtagText = $ToastTemplate.CreateTextNode($Balise) + $null = $XMLtag.AppendChild($XMLtagText) - if ($ButtonDismiss) { - # Creation of action node - $XMLaction = $ToastTemplate.CreateElement("action") - $XMLactions.AppendChild($XMLaction) | Out-Null - $XMLactionAtt1 = $ToastTemplate.CreateAttribute("content") - $XMLactionAtt1.Value = "" - $XMLaction.Attributes.Append($XMLactionAtt1) | Out-Null - $XMLactionAtt2 = $ToastTemplate.CreateAttribute("arguments") - $XMLactionAtt2.Value = "dismiss" - $XMLaction.Attributes.Append($XMLactionAtt2) | Out-Null - $XMLactionAtt3 = $ToastTemplate.CreateAttribute("activationType") - $XMLactionAtt3.Value = "system" - $XMLaction.Attributes.Append($XMLactionAtt3) | Out-Null - } + # Add the visual node to the xml + $null = $ToastTemplate.LastChild.AppendChild($XMLvisual) + $null = $ToastTemplate.LastChild.AppendChild($XMLactions) + $null = $ToastTemplate.LastChild.AppendChild($XMLtag) - # Creation of tag node - $XMLtag = $ToastTemplate.CreateElement("tag") - $XMLtagText = $ToastTemplate.CreateTextNode($Balise) - $XMLtag.AppendChild($XMLtagText) | Out-Null + if ($OnClickAction) + { + $null = $ToastTemplate.toast.SetAttribute('activationType', 'Protocol') + $null = $ToastTemplate.toast.SetAttribute('launch', $OnClickAction) + } - # Add the visual node to the xml - $ToastTemplate.LastChild.AppendChild($XMLvisual) | Out-Null - $ToastTemplate.LastChild.AppendChild($XMLactions) | Out-Null - $ToastTemplate.LastChild.AppendChild($XMLtag) | Out-Null + # if not "Interactive" user, run as system + if ($IsSystem) + { + # Save XML to File + $ToastTemplateLocation = ('{0}\config\' -f $WAUConfig.InstallLocation) + if (!(Test-Path -Path $ToastTemplateLocation -ErrorAction SilentlyContinue)) + { + $null = (New-Item -ItemType Directory -Force -Confirm:$false -Path $ToastTemplateLocation) + } - if ($OnClickAction) { - $ToastTemplate.toast.SetAttribute("activationType", "Protocol") | Out-Null - $ToastTemplate.toast.SetAttribute("launch", $OnClickAction) | Out-Null - } + $ToastTemplate.Save(('{0}\notif.xml' -f $ToastTemplateLocation)) - #if not "Interactive" user, run as system - if ($IsSystem) { + # Run Notify scheduled task to notify conneted users + $null = (Get-ScheduledTask -TaskName 'Winget-AutoUpdate-Notify' -ErrorAction SilentlyContinue | Start-ScheduledTask -ErrorAction SilentlyContinue) + } + else + { + #else, run as connected user + # Load Assemblies + $null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] + $null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] - #Save XML to File - $ToastTemplateLocation = "$($WAUConfig.InstallLocation)\config\" - if (!(Test-Path $ToastTemplateLocation)) { - New-Item -ItemType Directory -Force -Path $ToastTemplateLocation - } - $ToastTemplate.Save("$ToastTemplateLocation\notif.xml") + # Prepare XML + $ToastXml = [Windows.Data.Xml.Dom.XmlDocument]::New() + $ToastXml.LoadXml($ToastTemplate.OuterXml) - #Run Notify scheduled task to notify conneted users - Get-ScheduledTask -TaskName "Winget-AutoUpdate-Notify" -ErrorAction SilentlyContinue | Start-ScheduledTask -ErrorAction SilentlyContinue + # Specify Launcher App ID + $LauncherID = 'Windows.SystemToast.Winget.Notification' - } - #else, run as connected user - else { - - #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($ToastTemplate.OuterXml) - - #Specify Launcher App ID - $LauncherID = "Windows.SystemToast.Winget.Notification" - - #Prepare and Create Toast - $ToastMessage = [Windows.UI.Notifications.ToastNotification]::New($ToastXml) - $ToastMessage.Tag = $ToastTemplate.toast.tag - [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($LauncherID).Show($ToastMessage) - - } - - #Wait for notification to display - Start-Sleep 3 - - } + # Prepare and Create Toast + $ToastMessage = [Windows.UI.Notifications.ToastNotification]::New($ToastXml) + $ToastMessage.Tag = $ToastTemplate.toast.tag + [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($LauncherID).Show($ToastMessage) + } + # Wait for notification to display + Start-Sleep -Seconds 3 + } } diff --git a/Winget-AutoUpdate/functions/Test-ListPath.ps1 b/Winget-AutoUpdate/functions/Test-ListPath.ps1 index 2ec3d7b..a527ec1 100644 --- a/Winget-AutoUpdate/functions/Test-ListPath.ps1 +++ b/Winget-AutoUpdate/functions/Test-ListPath.ps1 @@ -1,83 +1,121 @@ -#Function to check Block/Allow List External Path +# Function to check Block/Allow List External Path -function Test-ListPath ($ListPath, $UseWhiteList, $WingetUpdatePath) { - # URL, UNC or Local Path - if ($UseWhiteList) { - $ListType = "included_apps.txt" - } - else { - $ListType = "excluded_apps.txt" - } +function Test-ListPath +{ + # URL, UNC or Local Path + [CmdletBinding()] + param + ( + [string] + $ListPath, + [string] + $UseWhiteList, + [string] + $WingetUpdatePath + ) - # Get local and external list paths - $LocalList = -join ($WingetUpdatePath, "\", $ListType) - $ExternalList = -join ($ListPath, "\", $ListType) + if ($UseWhiteList) + { + $ListType = 'included_apps.txt' + } + else + { + $ListType = 'excluded_apps.txt' + } - # Check if a list exists - if (Test-Path "$LocalList") { - $dateLocal = (Get-Item "$LocalList").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") - } + # Get local and external list paths + $LocalList = -join ($WingetUpdatePath, '\', $ListType) + $ExternalList = -join ($ListPath, '\', $ListType) - # If path is URL - if ($ListPath -like "http*") { - $ExternalList = -join ($ListPath, "/", $ListType) - $wc = New-Object System.Net.WebClient - try { - $wc.OpenRead("$ExternalList").Close() | Out-Null - $dateExternal = ([DateTime]$wc.ResponseHeaders['Last-Modified']).ToString("yyyy-MM-dd HH:mm:ss") - if ($dateExternal -gt $dateLocal) { - try { - $wc.DownloadFile($ExternalList, $LocalList) - } - catch { - $Script:ReachNoPath = $True - return $False - } - return $true + # Check if a list exists + if (Test-Path -Path $LocalList -ErrorAction SilentlyContinue) + { + $dateLocal = (Get-Item -Path $LocalList).LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') + } + + # If path is URL + if ($ListPath -like 'http*') + { + $ExternalList = -join ($ListPath, '/', $ListType) + $wc = (New-Object -TypeName System.Net.WebClient) + + try + { + $null = $wc.OpenRead($ExternalList).Close() + $dateExternal = ([DateTime]$wc.ResponseHeaders['Last-Modified']).ToString('yyyy-MM-dd HH:mm:ss') + + if ($dateExternal -gt $dateLocal) + { + try + { + $wc.DownloadFile($ExternalList, $LocalList) } - } - catch { - try { - $content = $wc.DownloadString("$ExternalList") - if ($null -ne $content -and $content -match "\w\.\w") { - $wc.DownloadFile($ExternalList, $LocalList) - return $true - } - else { - $Script:ReachNoPath = $True - return $False - } + catch + { + $Script:ReachNoPath = $True + return $False } - catch { - $Script:ReachNoPath = $True - return $False + return $True + } + } + catch + { + try + { + $content = $wc.DownloadString(('{0}' -f $ExternalList)) + + if ($null -ne $content -and $content -match '\w\.\w') + { + $wc.DownloadFile($ExternalList, $LocalList) + return $True } - } - } - # If path is UNC or local - else { - if (Test-Path -Path $ExternalList) { - try { - $dateExternal = (Get-Item "$ExternalList").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") + else + { + $Script:ReachNoPath = $True + return $False } - catch { - $Script:ReachNoPath = $True - return $False - } - if ($dateExternal -gt $dateLocal) { - try { - Copy-Item $ExternalList -Destination $LocalList -Force - } - catch { - $Script:ReachNoPath = $True - return $False - } - return $True - } - } - else { + } + catch + { $Script:ReachNoPath = $True - } - return $False - } + return $False + } + } + } + else + { + # If path is UNC or local + if (Test-Path -Path $ExternalList) + { + try + { + $dateExternal = (Get-Item -Path ('{0}' -f $ExternalList)).LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') + } + catch + { + $Script:ReachNoPath = $True + return $False + } + + if ($dateExternal -gt $dateLocal) + { + try + { + Copy-Item -Path $ExternalList -Destination $LocalList -Force + } + catch + { + $Script:ReachNoPath = $True + return $False + } + return $True + } + } + else + { + $Script:ReachNoPath = $True + } + + return $False + } } diff --git a/Winget-AutoUpdate/functions/Test-Mods.ps1 b/Winget-AutoUpdate/functions/Test-Mods.ps1 index f46d4da..81bf593 100644 --- a/Winget-AutoUpdate/functions/Test-Mods.ps1 +++ b/Winget-AutoUpdate/functions/Test-Mods.ps1 @@ -1,34 +1,50 @@ -#Function to check if modification exists within 'mods' directory +# Function to check if modification exists within 'mods' directory -function Test-Mods ($app) { +function Test-Mods +{ + # Takes care of a null situation + [CmdletBinding()] + param + ( + [string] + $app + ) - #Takes care of a null situation - $ModsPreInstall = $null - $ModsOverride = $null - $ModsUpgrade = $null - $ModsInstall = $null - $ModsInstalled = $null + $ModsPreInstall = $null + $ModsOverride = $null + $ModsUpgrade = $null + $ModsInstall = $null + $ModsInstalled = $null + $Mods = ('{0}\mods' -f $WorkingDir) - $Mods = "$WorkingDir\mods" - if (Test-Path "$Mods\$app-*") { - if (Test-Path "$Mods\$app-preinstall.ps1") { - $ModsPreInstall = "$Mods\$app-preinstall.ps1" - } - if (Test-Path "$Mods\$app-override.txt") { - $ModsOverride = Get-Content "$Mods\$app-override.txt" -Raw - } - if (Test-Path "$Mods\$app-install.ps1") { - $ModsInstall = "$Mods\$app-install.ps1" - $ModsUpgrade = "$Mods\$app-install.ps1" - } - if (Test-Path "$Mods\$app-upgrade.ps1") { - $ModsUpgrade = "$Mods\$app-upgrade.ps1" - } - if (Test-Path "$Mods\$app-installed.ps1") { - $ModsInstalled = "$Mods\$app-installed.ps1" - } - } + if (Test-Path -Path ('{0}\{1}-*' -f $Mods, $app) -ErrorAction SilentlyContinue) + { + if (Test-Path -Path ('{0}\{1}-preinstall.ps1' -f $Mods, $app) -ErrorAction SilentlyContinue) + { + $ModsPreInstall = ('{0}\{1}-preinstall.ps1' -f $Mods, $app) + } - return $ModsPreInstall, $ModsOverride, $ModsUpgrade, $ModsInstall, $ModsInstalled + if (Test-Path -Path ('{0}\{1}-override.txt' -f $Mods, $app) -ErrorAction SilentlyContinue) + { + $ModsOverride = Get-Content -Path ('{0}\{1}-override.txt' -f $Mods, $app) -Raw + } + if (Test-Path -Path ('{0}\{1}-install.ps1' -f $Mods, $app) -ErrorAction SilentlyContinue) + { + $ModsInstall = ('{0}\{1}-install.ps1' -f $Mods, $app) + $ModsUpgrade = ('{0}\{1}-install.ps1' -f $Mods, $app) + } + + if (Test-Path -Path ('{0}\{1}-upgrade.ps1' -f $Mods, $app) -ErrorAction SilentlyContinue) + { + $ModsUpgrade = ('{0}\{1}-upgrade.ps1' -f $Mods, $app) + } + + if (Test-Path -Path ('{0}\{1}-installed.ps1' -f $Mods, $app) -ErrorAction SilentlyContinue) + { + $ModsInstalled = ('{0}\{1}-installed.ps1' -f $Mods, $app) + } + } + + return $ModsPreInstall, $ModsOverride, $ModsUpgrade, $ModsInstall, $ModsInstalled } diff --git a/Winget-AutoUpdate/functions/Test-ModsPath.ps1 b/Winget-AutoUpdate/functions/Test-ModsPath.ps1 index 9f468b1..6385d84 100644 --- a/Winget-AutoUpdate/functions/Test-ModsPath.ps1 +++ b/Winget-AutoUpdate/functions/Test-ModsPath.ps1 @@ -1,233 +1,310 @@ #Function to check mods External Path -function Test-ModsPath ($ModsPath, $WingetUpdatePath, $AzureBlobSASURL) { - # URL, UNC or Local Path - # Get local and external Mods paths - $LocalMods = -join ($WingetUpdatePath, "\", "mods") - $ExternalMods = "$ModsPath" +function Test-ModsPath +{ + # URL, UNC or Local Path + # Get local and external Mods paths - #Get File Names Locally - $InternalModsNames = Get-ChildItem -Path $LocalMods -Name -Recurse -Include *.ps1, *.txt - $InternalBinsNames = Get-ChildItem -Path $LocalMods"\bins" -Name -Recurse -Include *.exe + [CmdletBinding()] + param + ( + [string] + $ModsPath, + [string] + $WingetUpdatePath, + [string] + $AzureBlobSASURL + ) + $LocalMods = -join ($WingetUpdatePath, '\', 'mods') + $ExternalMods = $ModsPath - # If path is URL - if ($ExternalMods -like "http*") { - # enable TLS 1.2 and TLS 1.1 protocols - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12, [Net.SecurityProtocolType]::Tls11 - #Get Index of $ExternalMods (or index page with href listing of all the Mods) - try { - $WebResponse = Invoke-WebRequest -Uri $ExternalMods -UseBasicParsing - } - catch { - $Script:ReachNoPath = $True - return $False - } + # Get File Names Locally + $InternalModsNames = (Get-ChildItem -Path $LocalMods -Name -Recurse -Include *.ps1, *.txt -ErrorAction SilentlyContinue) + $InternalBinsNames = (Get-ChildItem -Path $LocalMods"\bins" -Name -Recurse -Include *.exe -ErrorAction SilentlyContinue) - #Check for bins, download if newer. Delete if not external - $ExternalBins = "$ModsPath/bins" - if ($WebResponse -match "bins/") { - $BinResponse = Invoke-WebRequest -Uri $ExternalBins -UseBasicParsing - # Collect the external list of href links - $BinLinks = $BinResponse.Links | Select-Object -ExpandProperty HREF - #If there's a directory path in the HREF:s, delete it (IIS) - $CleanBinLinks = $BinLinks -replace "/.*/", "" - #Modify strings to HREF:s - $index = 0 - foreach ($Bin in $CleanBinLinks) { - if ($Bin) { - $CleanBinLinks[$index] = ' ' + $Bin + '' - } - $index++ - } - #Delete Local Bins that don't exist Externally - $index = 0 - $CleanLinks = $BinLinks -replace "/.*/", "" - foreach ($Bin in $InternalBinsNames) { - If ($CleanLinks -notcontains "$Bin") { - Remove-Item $LocalMods\bins\$Bin -Force -ErrorAction SilentlyContinue | Out-Null - } - $index++ - } - $CleanBinLinks = $BinLinks -replace "/.*/", "" - $Bin = "" - #Loop through all links - $wc = New-Object System.Net.WebClient - $CleanBinLinks | ForEach-Object { - #Check for .exe in listing/HREF:s in an index page pointing to .exe - if ($_ -like "*.exe") { - $dateExternalBin = "" - $dateLocalBin = "" - $wc.OpenRead("$ExternalBins/$_").Close() | Out-Null - $dateExternalBin = ([DateTime]$wc.ResponseHeaders['Last-Modified']).ToString("yyyy-MM-dd HH:mm:ss") - if (Test-Path -Path $LocalMods"\bins\"$_) { - $dateLocalBin = (Get-Item "$LocalMods\bins\$_").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") - } - if ($dateExternalBin -gt $dateLocalBin) { - $SaveBin = Join-Path -Path "$LocalMods\bins" -ChildPath $_ - Invoke-WebRequest -Uri "$ExternalBins/$_" -OutFile $SaveBin.Replace("%20", " ") -UseBasicParsing - } - } - } - } + # If path is URL + if ($ExternalMods -like 'http*') + { + # enable TLS 1.2 and TLS 1.1 protocols + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12, [Net.SecurityProtocolType]::Tls11 + # Get Index of $ExternalMods (or index page with href listing of all the Mods) + try + { + $WebResponse = (Invoke-WebRequest -Uri $ExternalMods -UseBasicParsing) + } + catch + { + $Script:ReachNoPath = $True - # Collect the external list of href links - $ModLinks = $WebResponse.Links | Select-Object -ExpandProperty HREF + return $False + } - #If there's a directory path in the HREF:s, delete it (IIS) - $CleanLinks = $ModLinks -replace "/.*/", "" + # Check for bins, download if newer. Delete if not external + $ExternalBins = ('{0}/bins' -f $ModsPath) - #Modify strings to HREF:s - $index = 0 - foreach ($Mod in $CleanLinks) { - if ($Mod) { - $CleanLinks[$index] = ' ' + $Mod + '' + if ($WebResponse -match 'bins/') + { + $BinResponse = Invoke-WebRequest -Uri $ExternalBins -UseBasicParsing + # Collect the external list of href links + $BinLinks = $BinResponse.Links | Select-Object -ExpandProperty HREF + # If there's a directory path in the HREF:s, delete it (IIS) + $CleanBinLinks = $BinLinks -replace '/.*/', '' + # Modify strings to HREF:s + $index = 0 + + foreach ($Bin in $CleanBinLinks) + { + if ($Bin) + { + $CleanBinLinks[$index] = ' ' + $Bin + '' } $index++ - } + } - #Delete Local Mods that don't exist Externally - $DeletedMods = 0 - $index = 0 - $CleanLinks = $ModLinks -replace "/.*/", "" - foreach ($Mod in $InternalModsNames) { - If ($CleanLinks -notcontains "$Mod") { - Remove-Item $LocalMods\$Mod -Force -ErrorAction SilentlyContinue | Out-Null - $DeletedMods++ + # Delete Local Bins that don't exist Externally + $index = 0 + $CleanLinks = $BinLinks -replace '/.*/', '' + + foreach ($Bin in $InternalBinsNames) + { + if ($CleanLinks -notcontains $Bin) + { + $null = (Remove-Item -Path $LocalMods\bins\$Bin -Force -Confirm:$False -ErrorAction SilentlyContinue) } + $index++ - } + } - $CleanLinks = $ModLinks -replace "/.*/", "" + $CleanBinLinks = $BinLinks -replace '/.*/', '' + $Bin = '' + # Loop through all links + $wc = New-Object -TypeName System.Net.WebClient + $CleanBinLinks | ForEach-Object -Process { + # Check for .exe in listing/HREF:s in an index page pointing to .exe + if ($_ -like '*.exe') + { + $dateExternalBin = '' + $dateLocalBin = '' + $null = $wc.OpenRead(('{0}/{1}' -f $ExternalBins, $_)).Close() + $dateExternalBin = ([DateTime]$wc.ResponseHeaders['Last-Modified']).ToString('yyyy-MM-dd HH:mm:ss') - #Loop through all links - $wc = New-Object System.Net.WebClient - $CleanLinks | ForEach-Object { - #Check for .ps1/.txt in listing/HREF:s in an index page pointing to .ps1/.txt - if (($_ -like "*.ps1") -or ($_ -like "*.txt")) { - try { - $dateExternalMod = "" - $dateLocalMod = "" - $wc.OpenRead("$ExternalMods/$_").Close() | Out-Null - $dateExternalMod = ([DateTime]$wc.ResponseHeaders['Last-Modified']).ToString("yyyy-MM-dd HH:mm:ss") - if (Test-Path -Path $LocalMods"\"$_) { - $dateLocalMod = (Get-Item "$LocalMods\$_").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") - } + if (Test-Path -Path $LocalMods"\bins\"$_) + { + $dateLocalBin = (Get-Item -Path ('{0}\bins\{1}' -f $LocalMods, $_)).LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') + } - if ($dateExternalMod -gt $dateLocalMod) { - try { - $SaveMod = Join-Path -Path "$LocalMods\" -ChildPath $_ - $Mod = '{0}/{1}' -f $ModsPath.TrimEnd('/'), $_ - Invoke-WebRequest -Uri "$Mod" -OutFile $SaveMod -UseBasicParsing - $ModsUpdated++ - } - catch { - $Script:ReachNoPath = $True - } - } - } - catch { - if (($_ -like "*.ps1") -or ($_ -like "*.txt")) { - $Script:ReachNoPath = $True - } - } + if ($dateExternalBin -gt $dateLocalBin) + { + $SaveBin = Join-Path -Path ('{0}\bins' -f $LocalMods) -ChildPath $_ + Invoke-WebRequest -Uri ('{0}/{1}' -f $ExternalBins, $_) -OutFile $SaveBin.Replace('%20', ' ') -UseBasicParsing + } } - } - return $ModsUpdated, $DeletedMods - } - # If Path is Azure Blob - elseif ($ExternalMods -like "AzureBlob") { - Write-ToLog "Azure Blob Storage set as mod source" - Write-ToLog "Checking AZCopy" - Get-AZCopy $WingetUpdatePath - #Safety check to make sure we really do have azcopy.exe and a Blob URL - if ((Test-Path -Path "$WingetUpdatePath\azcopy.exe" -PathType Leaf) -and ($null -ne $AzureBlobSASURL)) { - Write-ToLog "Syncing Blob storage with local storage" + } + } - $AZCopySyncOutput = & $WingetUpdatePath\azcopy.exe sync "$AzureBlobSASURL" "$LocalMods" --from-to BlobLocal --delete-destination=true - $AZCopyOutputLines = $AZCopySyncOutput.Split([Environment]::NewLine) + # Collect the external list of href links + $ModLinks = $WebResponse.Links | Select-Object -ExpandProperty HREF + # If there's a directory path in the HREF:s, delete it (IIS) + $CleanLinks = $ModLinks -replace '/.*/', '' + # Modify strings to HREF:s + $index = 0 - foreach ( $_ in $AZCopyOutputLines) { - $AZCopySyncAdditionsRegex = [regex]::new("(?<=Number of Copy Transfers Completed:\s+)\d+") - $AZCopySyncDeletionsRegex = [regex]::new("(?<=Number of Deletions at Destination:\s+)\d+") - $AZCopySyncErrorRegex = [regex]::new("^Cannot perform sync due to error:") + foreach ($Mod in $CleanLinks) + { + if ($Mod) + { + $CleanLinks[$index] = ' ' + $Mod + '' + } + $index++ + } - $AZCopyAdditions = [int] $AZCopySyncAdditionsRegex.Match($_).Value - $AZCopyDeletions = [int] $AZCopySyncDeletionsRegex.Match($_).Value + # Delete Local Mods that don't exist Externally + $DeletedMods = 0 + $index = 0 + $CleanLinks = $ModLinks -replace '/.*/', '' - if ($AZCopyAdditions -ne 0) { - $ModsUpdated = $AZCopyAdditions - } + foreach ($Mod in $InternalModsNames) + { + if ($CleanLinks -notcontains $Mod) + { + $null = (Remove-Item -Path $LocalMods\$Mod -Force -Confirm:$False -ErrorAction SilentlyContinue) + $DeletedMods++ + } + $index++ + } - if ($AZCopyDeletions -ne 0) { - $DeletedMods = $AZCopyDeletions - } + $CleanLinks = $ModLinks -replace '/.*/', '' - if ($AZCopySyncErrorRegex.Match($_).Value) { - Write-ToLog "AZCopy Sync Error! $_" - } + # Loop through all links + + $CleanLinks | ForEach-Object -Process { + # Check for .ps1/.txt in listing/HREF:s in an index page pointing to .ps1/.txt + if (($_ -like '*.ps1') -or ($_ -like '*.txt')) + { + try + { + $dateExternalMod = '' + $dateLocalMod = '' + $null = $wc.OpenRead(('{0}/{1}' -f $ExternalMods, $_)).Close() + $dateExternalMod = ([DateTime]$wc.ResponseHeaders['Last-Modified']).ToString('yyyy-MM-dd HH:mm:ss') + + if (Test-Path -Path $LocalMods"\"$_) + { + $dateLocalMod = (Get-Item -Path ('{0}\{1}' -f $LocalMods, $_)).LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') + } + + if ($dateExternalMod -gt $dateLocalMod) + { + try + { + $SaveMod = Join-Path -Path ('{0}\' -f $LocalMods) -ChildPath $_ + $Mod = '{0}/{1}' -f $ModsPath.TrimEnd('/'), $_ + $null = (Invoke-WebRequest -Uri $Mod -OutFile $SaveMod -UseBasicParsing) + $ModsUpdated++ + } + catch + { + $Script:ReachNoPath = $True + } + } } - } - else { - Write-ToLog "Error 'azcopy.exe' or SAS Token not found!" - } - - return $ModsUpdated, $DeletedMods - } - # If path is UNC or local - else { - $ExternalBins = "$ModsPath\bins" - if (Test-Path -Path $ExternalBins"\*.exe") { - $ExternalBinsNames = Get-ChildItem -Path $ExternalBins -Name -Recurse -Include *.exe - #Delete Local Bins that don't exist Externally - foreach ($Bin in $InternalBinsNames) { - If ($Bin -notin $ExternalBinsNames ) { - Remove-Item $LocalMods\bins\$Bin -Force -ErrorAction SilentlyContinue | Out-Null - } + catch + { + if (($_ -like '*.ps1') -or ($_ -like '*.txt')) + { + $Script:ReachNoPath = $True + } } - #Copy newer external bins - foreach ($Bin in $ExternalBinsNames) { - $dateExternalBin = "" - $dateLocalBin = "" - if (Test-Path -Path $LocalMods"\bins\"$Bin) { - $dateLocalBin = (Get-Item "$LocalMods\bins\$Bin").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") - } - $dateExternalBin = (Get-Item "$ExternalBins\$Bin").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") - if ($dateExternalBin -gt $dateLocalBin) { - Copy-Item $ExternalBins\$Bin -Destination $LocalMods\bins\$Bin -Force -ErrorAction SilentlyContinue | Out-Null - } - } - } + } + } + return $ModsUpdated, $DeletedMods + } + # If Path is Azure Blob + elseif ($ExternalMods -like 'AzureBlob') + { + Write-ToLog -LogMsg 'Azure Blob Storage set as mod source' + Write-ToLog -LogMsg 'Checking AZCopy' + Get-AZCopy $WingetUpdatePath - if ((Test-Path -Path $ExternalMods"\*.ps1") -or (Test-Path -Path $ExternalMods"\*.txt")) { - #Get File Names Externally - $ExternalModsNames = Get-ChildItem -Path $ExternalMods -Name -Recurse -Include *.ps1, *.txt + # Safety check to make sure we really do have azcopy.exe and a Blob URL + if ((Test-Path -Path ('{0}\azcopy.exe' -f $WingetUpdatePath) -PathType Leaf) -and ($null -ne $AzureBlobSASURL)) + { + Write-ToLog -LogMsg 'Syncing Blob storage with local storage' - #Delete Local Mods that don't exist Externally - $DeletedMods = 0 - foreach ($Mod in $InternalModsNames) { - If ($Mod -notin $ExternalModsNames ) { - Remove-Item $LocalMods\$Mod -Force -ErrorAction SilentlyContinue | Out-Null - $DeletedMods++ - } + $AZCopySyncOutput = & $WingetUpdatePath\azcopy.exe sync $AzureBlobSASURL $LocalMods --from-to BlobLocal --delete-destination=true + $AZCopyOutputLines = $AZCopySyncOutput.Split([Environment]::NewLine) + + foreach ($_ in $AZCopyOutputLines) + { + $AZCopySyncAdditionsRegex = [regex]::new('(?<=Number of Copy Transfers Completed:\s+)\d+') + $AZCopySyncDeletionsRegex = [regex]::new('(?<=Number of Deletions at Destination:\s+)\d+') + $AZCopySyncErrorRegex = [regex]::new('^Cannot perform sync due to error:') + + $AZCopyAdditions = [int]$AZCopySyncAdditionsRegex.Match($_).Value + $AZCopyDeletions = [int]$AZCopySyncDeletionsRegex.Match($_).Value + + if ($AZCopyAdditions -ne 0) + { + $ModsUpdated = $AZCopyAdditions } - #Copy newer external mods - foreach ($Mod in $ExternalModsNames) { - $dateExternalMod = "" - $dateLocalMod = "" - if (Test-Path -Path $LocalMods"\"$Mod) { - $dateLocalMod = (Get-Item "$LocalMods\$Mod").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") - } - $dateExternalMod = (Get-Item "$ExternalMods\$Mod").LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") - if ($dateExternalMod -gt $dateLocalMod) { - Copy-Item $ExternalMods\$Mod -Destination $LocalMods\$Mod -Force -ErrorAction SilentlyContinue | Out-Null - $ModsUpdated++ - } + if ($AZCopyDeletions -ne 0) + { + $DeletedMods = $AZCopyDeletions } - } - else { - $Script:ReachNoPath = $True - } - return $ModsUpdated, $DeletedMods - } + + if ($AZCopySyncErrorRegex.Match($_).Value) + { + Write-ToLog -LogMsg ('AZCopy Sync Error! {0}' -f $_) + } + } + } + else + { + Write-ToLog -LogMsg "Error 'azcopy.exe' or SAS Token not found!" + } + + return $ModsUpdated, $DeletedMods + } + else + { + # If path is UNC or local + $ExternalBins = ('{0}\bins' -f $ModsPath) + + if (Test-Path -Path $ExternalBins"\*.exe") + { + $ExternalBinsNames = (Get-ChildItem -Path $ExternalBins -Name -Recurse -Include *.exe) + + # Delete Local Bins that don't exist Externally + foreach ($Bin in $InternalBinsNames) + { + if ($Bin -notin $ExternalBinsNames) + { + $null = (Remove-Item -Path $LocalMods\bins\$Bin -Force -Confirm:$False -ErrorAction SilentlyContinue) + } + } + + # Copy newer external bins + foreach ($Bin in $ExternalBinsNames) + { + $dateExternalBin = '' + $dateLocalBin = '' + + if (Test-Path -Path $LocalMods"\bins\"$Bin) + { + $dateLocalBin = (Get-Item -Path ('{0}\bins\{1}' -f $LocalMods, $Bin)).LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') + } + + $dateExternalBin = (Get-Item -Path ('{0}\{1}' -f $ExternalBins, $Bin)).LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') + + if ($dateExternalBin -gt $dateLocalBin) + { + $null = Copy-Item -Path $ExternalBins\$Bin -Destination $LocalMods\bins\$Bin -Force -ErrorAction SilentlyContinue + } + } + } + + if ((Test-Path -Path $ExternalMods"\*.ps1") -or (Test-Path -Path $ExternalMods"\*.txt")) + { + # Get File Names Externally + $ExternalModsNames = Get-ChildItem -Path $ExternalMods -Name -Recurse -Include *.ps1, *.txt + + # Delete Local Mods that don't exist Externally + $DeletedMods = 0 + + foreach ($Mod in $InternalModsNames) + { + if ($Mod -notin $ExternalModsNames) + { + $null = Remove-Item -Path $LocalMods\$Mod -Force -ErrorAction SilentlyContinue + $DeletedMods++ + } + } + + # Copy newer external mods + foreach ($Mod in $ExternalModsNames) + { + $dateExternalMod = '' + $dateLocalMod = '' + if (Test-Path -Path $LocalMods"\"$Mod) + { + $dateLocalMod = (Get-Item -Path ('{0}\{1}' -f $LocalMods, $Mod)).LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') + } + + $dateExternalMod = (Get-Item -Path ('{0}\{1}' -f $ExternalMods, $Mod)).LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss') + + if ($dateExternalMod -gt $dateLocalMod) + { + $null = Copy-Item -Path $ExternalMods\$Mod -Destination $LocalMods\$Mod -Force -ErrorAction SilentlyContinue + $ModsUpdated++ + } + } + } + else + { + $Script:ReachNoPath = $True + } + + return $ModsUpdated, $DeletedMods + } } diff --git a/Winget-AutoUpdate/functions/Test-Network.ps1 b/Winget-AutoUpdate/functions/Test-Network.ps1 index 9910d26..22b3877 100644 --- a/Winget-AutoUpdate/functions/Test-Network.ps1 +++ b/Winget-AutoUpdate/functions/Test-Network.ps1 @@ -1,82 +1,77 @@ -#Function to check the connectivity +# Function to check the connectivity -function Test-Network { +function Test-Network +{ + #Init - #Init - $timeout = 0 + $timeout = 0 - #Test connectivity during 30 min then timeout - Write-ToLog "Checking internet connection..." "Yellow" - While ($timeout -lt 1800) { + # Test connectivity during 30 min then timeout + Write-ToLog -LogMsg 'Checking internet connection...' -LogColor 'Yellow' + while ($timeout -lt 1800) + { + $URLtoTest = 'https://raw.githubusercontent.com/Romanitho/Winget-AutoUpdate/main/LICENSE' + $URLcontent = ((Invoke-WebRequest -Uri $URLtoTest -UseBasicParsing).content) - $URLtoTest = "https://raw.githubusercontent.com/Romanitho/Winget-AutoUpdate/main/LICENSE" - $URLcontent = ((Invoke-WebRequest -URI $URLtoTest -UseBasicParsing).content) + if ($URLcontent -like '*MIT License*') + { + Write-ToLog -LogMsg 'Connected !' -LogColor 'Green' - if ($URLcontent -like "*MIT License*") { + # Check for metered connection + $null = (Add-Type -AssemblyName Windows.Networking) + $null = [Windows.Networking.Connectivity.NetworkInformation, Windows, ContentType = WindowsRuntime] + $cost = [Windows.Networking.Connectivity.NetworkInformation]::GetInternetConnectionProfile().GetConnectionCost() - Write-ToLog "Connected !" "Green" - - #Check for metered connection - [void][Windows.Networking.Connectivity.NetworkInformation, Windows, ContentType = WindowsRuntime] - $cost = [Windows.Networking.Connectivity.NetworkInformation]::GetInternetConnectionProfile().GetConnectionCost() - - if ($cost.ApproachingDataLimit -or $cost.OverDataLimit -or $cost.Roaming -or $cost.BackgroundDataUsageRestricted -or ($cost.NetworkCostType -ne "Unrestricted")) { - - Write-ToLog "Metered connection detected." "Yellow" - - if ($WAUConfig.WAU_DoNotRunOnMetered -eq 1) { - - Write-ToLog "WAU is configured to bypass update checking on metered connection" - return $false - - } - else { - - Write-ToLog "WAU is configured to force update checking on metered connection" - return $true - - } + if ($cost.ApproachingDataLimit -or $cost.OverDataLimit -or $cost.Roaming -or $cost.BackgroundDataUsageRestricted -or ($cost.NetworkCostType -ne 'Unrestricted')) + { + Write-ToLog -LogMsg 'Metered connection detected.' -LogColor 'Yellow' + if ($WAUConfig.WAU_DoNotRunOnMetered -eq 1) + { + Write-ToLog -LogMsg 'WAU is configured to bypass update checking on metered connection' + return $false } - else { - - return $true - + else + { + Write-ToLog -LogMsg 'WAU is configured to force update checking on metered connection' + return $true } + } + else + { + return $true + } + } + else + { + Start-Sleep -Seconds 10 + $timeout += 10 - } - else { + # Send Warning Notif if no connection for 5 min + if ($timeout -eq 300) + { + # Log + Write-ToLog -LogMsg "Notify 'No connection' sent." -LogColor 'Yellow' - Start-Sleep 10 - $timeout += 10 + # Notif + $Title = $NotifLocale.local.outputs.output[0].title + $Message = $NotifLocale.local.outputs.output[0].message + $MessageType = 'warning' + $Balise = 'Connection' + Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Balise $Balise + } + } + } - #Send Warning Notif if no connection for 5 min - if ($timeout -eq 300) { - #Log - Write-ToLog "Notify 'No connection' sent." "Yellow" + # Send Timeout Notif if no connection for 30 min + Write-ToLog -LogMsg 'Timeout. No internet connection !' -LogColor 'Red' - #Notif - $Title = $NotifLocale.local.outputs.output[0].title - $Message = $NotifLocale.local.outputs.output[0].message - $MessageType = "warning" - $Balise = "Connection" - Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Balise $Balise - } - - } - - } - - #Send Timeout Notif if no connection for 30 min - Write-ToLog "Timeout. No internet connection !" "Red" - - #Notif - $Title = $NotifLocale.local.outputs.output[1].title - $Message = $NotifLocale.local.outputs.output[1].message - $MessageType = "error" - $Balise = "Connection" - Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Balise $Balise - - return $false + # Notif + $Title = $NotifLocale.local.outputs.output[1].title + $Message = $NotifLocale.local.outputs.output[1].message + $MessageType = 'error' + $Balise = 'Connection' + Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Balise $Balise + return $false } diff --git a/Winget-AutoUpdate/functions/Test-PendingReboot.ps1 b/Winget-AutoUpdate/functions/Test-PendingReboot.ps1 index bb1d52e..0e371f7 100644 --- a/Winget-AutoUpdate/functions/Test-PendingReboot.ps1 +++ b/Winget-AutoUpdate/functions/Test-PendingReboot.ps1 @@ -1,25 +1,34 @@ -#Function to check if there is a Pending Reboot +# Function to check if there is a Pending Reboot -function Test-PendingReboot { +function Test-PendingReboot +{ + $Computer = $env:COMPUTERNAME + $PendingReboot = $false - $Computer = $env:COMPUTERNAME - $PendingReboot = $false + $HKLM = [UInt32] '0x80000002' + $WMI_Reg = [WMIClass] ('\\{0}\root\default:StdRegProv' -f $Computer) - $HKLM = [UInt32] "0x80000002" - $WMI_Reg = [WMIClass] "\\$Computer\root\default:StdRegProv" + if ($WMI_Reg) + { + if (($WMI_Reg.EnumKey($HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\')).sNames -contains 'RebootPending') + { + $PendingReboot = $true + } + if (($WMI_Reg.EnumKey($HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\')).sNames -contains 'RebootRequired') + { + $PendingReboot = $true + } - if ($WMI_Reg) { - if (($WMI_Reg.EnumKey($HKLM, "SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\")).sNames -contains 'RebootPending') { $PendingReboot = $true } - if (($WMI_Reg.EnumKey($HKLM, "SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\")).sNames -contains 'RebootRequired') { $PendingReboot = $true } - - #Checking for SCCM namespace - $SCCM_Namespace = Get-WmiObject -Namespace ROOT\CCM\ClientSDK -List -ComputerName $Computer -ErrorAction Ignore - if ($SCCM_Namespace) { - if (([WmiClass]"\\$Computer\ROOT\CCM\ClientSDK:CCM_ClientUtilities").DetermineIfRebootPending().RebootPending -eq $true) { $PendingReboot = $true } - } - - } - - return $PendingReboot + # Checking for SCCM namespace + $SCCM_Namespace = Get-WmiObject -Namespace ROOT\CCM\ClientSDK -List -ComputerName $Computer -ErrorAction Ignore + if ($SCCM_Namespace) + { + if (([WmiClass]('\\{0}\ROOT\CCM\ClientSDK:CCM_ClientUtilities' -f $Computer)).DetermineIfRebootPending().RebootPending -eq $true) + { + $PendingReboot = $true + } + } + } + return $PendingReboot } diff --git a/Winget-AutoUpdate/functions/Update-App.ps1 b/Winget-AutoUpdate/functions/Update-App.ps1 index 7006b10..d7e0a4c 100644 --- a/Winget-AutoUpdate/functions/Update-App.ps1 +++ b/Winget-AutoUpdate/functions/Update-App.ps1 @@ -1,123 +1,137 @@ -#Function to update an App +# Function to update an App -Function Update-App ($app) { +function Update-App +{ + # Get App Info + [CmdletBinding()] + param + ( + $app + ) + $ReleaseNoteURL = Get-AppInfo $app.Id + if ($ReleaseNoteURL) + { + $Button1Text = $NotifLocale.local.outputs.output[10].message + } - #Get App Info - $ReleaseNoteURL = Get-AppInfo $app.Id - if ($ReleaseNoteURL) { - $Button1Text = $NotifLocale.local.outputs.output[10].message - } + # Send available update notification + Write-ToLog -LogMsg ('Updating {0} from {1} to {2}...' -f $app.Name, $app.Version, $app.AvailableVersion) -LogColor '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 $Title -Message $Message -MessageType $MessageType -Balise $Balise -Button1Action $ReleaseNoteURL -Button1Text $Button1Text - #Send available update notification - Write-ToLog "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 $Title -Message $Message -MessageType $MessageType -Balise $Balise -Button1Action $ReleaseNoteURL -Button1Text $Button1Text + # Check if mods exist for preinstall/install/upgrade + $ModsPreInstall, $ModsOverride, $ModsUpgrade, $ModsInstall, $ModsInstalled = Test-Mods $($app.Id) - #Check if mods exist for preinstall/install/upgrade - $ModsPreInstall, $ModsOverride, $ModsUpgrade, $ModsInstall, $ModsInstalled = Test-Mods $($app.Id) + # Winget upgrade + Write-ToLog -LogMsg ("########## WINGET UPGRADE PROCESS STARTS FOR APPLICATION ID '{0}' ##########" -f $app.Id) -LogColor 'Gray' - #Winget upgrade - Write-ToLog "########## WINGET UPGRADE PROCESS STARTS FOR APPLICATION ID '$($App.Id)' ##########" "Gray" + # If PreInstall script exist + if ($ModsPreInstall) + { + Write-ToLog -LogMsg ('Modifications for {0} before upgrade are being applied...' -f $app.Id) -LogColor 'Yellow' + & "$ModsPreInstall" + } - #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 -LogMsg ('-> Running (overriding default): Winget upgrade --id {0} --accept-package-agreements --accept-source-agreements --override {1}' -f $app.Id, $ModsOverride) + & $Winget upgrade --id $($app.Id) --accept-package-agreements --accept-source-agreements --override $ModsOverride | Tee-Object -FilePath $LogFile -Append + } + else + { + Write-ToLog -LogMsg ('-> Running: Winget upgrade --id {0} --accept-package-agreements --accept-source-agreements -h' -f $app.Id) + & $Winget upgrade --id $($app.Id) --accept-package-agreements --accept-source-agreements -h | Tee-Object -FilePath $LogFile -Append + } - #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 -LogMsg ('Modifications for {0} during upgrade are being applied...' -f $app.Id) -LogColor 'Yellow' + & "$ModsUpgrade" + } - if ($ModsUpgrade) { - Write-ToLog "Modifications for $($app.Id) during upgrade are being applied..." "Yellow" - & "$ModsUpgrade" - } + # Check if application updated properly + $FailedToUpgrade = $false + $ConfirmInstall = Confirm-Installation $($app.Id) $($app.AvailableVersion) - #Check if application updated properly - $FailedToUpgrade = $false - $ConfirmInstall = Confirm-Installation $($app.Id) $($app.AvailableVersion) + if ($ConfirmInstall -ne $true) + { + # Upgrade failed! + # Test for a Pending Reboot (Component Based Servicing/WindowsUpdate/CCM_ClientUtilities) + $PendingReboot = Test-PendingReboot + if ($PendingReboot -eq $true) + { + Write-ToLog -LogMsg ("-> A Pending Reboot lingers and probably prohibited {0} from upgrading...`n-> ...an install for {1} is NOT executed!" -f $app.Name) -LogColor 'Red' + $FailedToUpgrade = $true + break + } - if ($ConfirmInstall -ne $true) { - #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 -LogMsg ('-> An upgrade for {0} failed, now trying an install instead...' -f $app.Name) -LogColor 'Yellow' - #If app failed to upgrade, run Install command - Write-ToLog "-> An upgrade for $($app.Name) failed, now trying an install instead..." "Yellow" + if ($ModsOverride) + { + Write-ToLog -LogMsg ('-> Running (overriding default): Winget install --id {0} --accept-package-agreements --accept-source-agreements --force --override {1}' -f $app.Id, $ModsOverride) + & $Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements --force --override $ModsOverride | Tee-Object -FilePath $LogFile -Append + } + else + { + Write-ToLog -LogMsg ('-> Running: Winget install --id {0} --accept-package-agreements --accept-source-agreements --force -h' -f $app.Id) + & $Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements --force -h | Tee-Object -FilePath $LogFile -Append + } - if ($ModsOverride) { - Write-ToLog "-> Running (overriding default): Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements --force --override $ModsOverride" - & $Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements --force --override $ModsOverride | Tee-Object -file $LogFile -Append - } - else { - Write-ToLog "-> Running: Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements --force -h" - & $Winget install --id $($app.Id) --accept-package-agreements --accept-source-agreements --force -h | Tee-Object -file $LogFile -Append - } + if ($ModsInstall) + { + Write-ToLog -LogMsg ('Modifications for {0} during install are being applied...' -f $app.Id) -LogColor 'Yellow' + & "$ModsInstall" + } - if ($ModsInstall) { - Write-ToLog "Modifications for $($app.Id) during install are being applied..." "Yellow" - & "$ModsInstall" - } + # Check if application installed properly + $ConfirmInstall = Confirm-Installation $($app.Id) $($app.AvailableVersion) + if ($ConfirmInstall -eq $false) + { + $FailedToUpgrade = $true + } + } - #Check if application installed properly - $ConfirmInstall = Confirm-Installation $($app.Id) $($app.AvailableVersion) - if ($ConfirmInstall -eq $false) { - $FailedToUpgrade = $true - } - } + if ($FailedToUpgrade -eq $false) + { + if ($ModsInstalled) + { + Write-ToLog -LogMsg ('Modifications for {0} after upgrade/install are being applied...' -f $app.Id) -LogColor 'Yellow' + & "$ModsInstalled" + } + } - if ($FailedToUpgrade -eq $false) { - if ($ModsInstalled) { - Write-ToLog "Modifications for $($app.Id) after upgrade/install are being applied..." "Yellow" - & "$ModsInstalled" - } - } + Write-ToLog -LogMsg ("########## WINGET UPGRADE PROCESS FINISHED FOR APPLICATION ID '{0}' ##########" -f $app.Id) -LogColor 'Gray' - 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 -LogMsg ('{0} updated to {1} !' -f $app.Name, $app.AvailableVersion) -LogColor 'Green' - #Notify installation - if ($FailedToUpgrade -eq $false) { + # 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 $Title -Message $Message -MessageType $MessageType -Balise $Balise -Button1Action $ReleaseNoteURL -Button1Text $Button1Text + $Script:InstallOK += 1 + } + else + { + # Send failed updated app notification + Write-ToLog -LogMsg ('{0} update failed.' -f $app.Name) -LogColor 'Red' - #Send success updated app notification - Write-ToLog "$($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 $Title -Message $Message -MessageType $MessageType -Balise $Balise -Button1Action $ReleaseNoteURL -Button1Text $Button1Text - - $Script:InstallOK += 1 - - } - else { - - #Send failed updated app notification - Write-ToLog "$($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 $Title -Message $Message -MessageType $MessageType -Balise $Balise -Button1Action $ReleaseNoteURL -Button1Text $Button1Text - - } - -} \ No newline at end of file + # 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 $Title -Message $Message -MessageType $MessageType -Balise $Balise -Button1Action $ReleaseNoteURL -Button1Text $Button1Text + } +} diff --git a/Winget-AutoUpdate/functions/Update-WAU.ps1 b/Winget-AutoUpdate/functions/Update-WAU.ps1 index 123deb9..57c6f49 100644 --- a/Winget-AutoUpdate/functions/Update-WAU.ps1 +++ b/Winget-AutoUpdate/functions/Update-WAU.ps1 @@ -1,77 +1,74 @@ -#Function to update WAU +# Function to update WAU -function Update-WAU { +function Update-WAU +{ + $OnClickAction = 'https://github.com/Romanitho/Winget-AutoUpdate/releases' + $Button1Text = $NotifLocale.local.outputs.output[10].message - $OnClickAction = "https://github.com/Romanitho/Winget-AutoUpdate/releases" - $Button1Text = $NotifLocale.local.outputs.output[10].message + #Send available update notification + $Title = $NotifLocale.local.outputs.output[2].title -f 'Winget-AutoUpdate' + $Message = $NotifLocale.local.outputs.output[2].message -f $WAUCurrentVersion, $WAUAvailableVersion + $MessageType = 'info' + Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Button1Action $OnClickAction -Button1Text $Button1Text - #Send available update notification - $Title = $NotifLocale.local.outputs.output[2].title -f "Winget-AutoUpdate" - $Message = $NotifLocale.local.outputs.output[2].message -f $WAUCurrentVersion, $WAUAvailableVersion - $MessageType = "info" - Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Button1Action $OnClickAction -Button1Text $Button1Text + # Run WAU update + try + { + # Force to create a zip file + $ZipFile = ('{0}\WAU_update.zip' -f $WorkingDir) + $null = New-Item -Path $ZipFile -ItemType File -Force - #Run WAU update - try { + # Download the zip + Write-ToLog -LogMsg ('Downloading the GitHub Repository version {0}' -f $WAUAvailableVersion) -LogColor 'Cyan' + $null = (Invoke-RestMethod -Uri ('https://github.com/Romanitho/Winget-AutoUpdate/releases/download/v{0}/WAU.zip' -f ($WAUAvailableVersion)) -OutFile $ZipFile) - #Force to create a zip file - $ZipFile = "$WorkingDir\WAU_update.zip" - New-Item $ZipFile -ItemType File -Force | Out-Null + # Extract Zip File + Write-ToLog -LogMsg 'Unzipping the WAU Update package' -LogColor 'Cyan' + $location = ('{0}\WAU_update' -f $WorkingDir) + $null = (Expand-Archive -Path $ZipFile -DestinationPath $location -Force) + $null = (Get-ChildItem -Path $location -Recurse | Unblock-File -ErrorAction SilentlyContinue) - #Download the zip - Write-ToLog "Downloading the GitHub Repository version $WAUAvailableVersion" "Cyan" - Invoke-RestMethod -Uri "https://github.com/Romanitho/Winget-AutoUpdate/releases/download/v$($WAUAvailableVersion)/WAU.zip" -OutFile $ZipFile + # Update scritps + Write-ToLog -LogMsg 'Updating WAU...' -LogColor 'Yellow' + $TempPath = (Resolve-Path -Path ('{0}\Winget-AutoUpdate\' -f $location) -ErrorAction SilentlyContinue)[0].Path + if ($TempPath) + { + $null = (Copy-Item -Path ('{0}\*' -f $TempPath) -Destination ('{0}\' -f $WorkingDir) -Exclude 'icons' -Recurse -Force -Confirm:$false) + } - #Extract Zip File - Write-ToLog "Unzipping the WAU Update package" "Cyan" - $location = "$WorkingDir\WAU_update" - Expand-Archive -Path $ZipFile -DestinationPath $location -Force - Get-ChildItem -Path $location -Recurse | Unblock-File + # Remove update zip file and update temp folder + Write-ToLog -LogMsg 'Done. Cleaning temp files...' -LogColor 'Cyan' + $null = (Remove-Item -Path $ZipFile -Force -Confirm:$false -ErrorAction SilentlyContinue) + $null = (Remove-Item -Path $location -Recurse -Force -Confirm:$false -ErrorAction SilentlyContinue) - #Update scritps - Write-ToLog "Updating WAU..." "Yellow" - $TempPath = (Resolve-Path "$location\Winget-AutoUpdate\")[0].Path - if ($TempPath) { - Copy-Item -Path "$TempPath\*" -Destination "$WorkingDir\" -Exclude "icons" -Recurse -Force - } + # Set new version to registry + $WAUConfig | New-ItemProperty -Name DisplayVersion -Value $WAUAvailableVersion -Force + $WAUConfig | New-ItemProperty -Name VersionMajor -Value ([version]$WAUAvailableVersion.Replace('-', '.')).Major -Force + $WAUConfig | New-ItemProperty -Name VersionMinor -Value ([version]$WAUAvailableVersion.Replace('-', '.')).Minor -Force - #Remove update zip file and update temp folder - Write-ToLog "Done. Cleaning temp files..." "Cyan" - Remove-Item -Path $ZipFile -Force -ErrorAction SilentlyContinue - Remove-Item -Path $location -Recurse -Force -ErrorAction SilentlyContinue + # Set Post Update actions to 1 + $WAUConfig | New-ItemProperty -Name WAU_PostUpdateActions -Value 1 -Force - #Set new version to registry - $WAUConfig | New-ItemProperty -Name DisplayVersion -Value $WAUAvailableVersion -Force - $WAUConfig | New-ItemProperty -Name VersionMajor -Value ([version]$WAUAvailableVersion.Replace("-", ".")).Major -Force - $WAUConfig | New-ItemProperty -Name VersionMinor -Value ([version]$WAUAvailableVersion.Replace("-", ".")).Minor -Force + # Send success Notif + Write-ToLog -LogMsg 'WAU Update completed.' -LogColor 'Green' + $Title = $NotifLocale.local.outputs.output[3].title -f 'Winget-AutoUpdate' + $Message = $NotifLocale.local.outputs.output[3].message -f $WAUAvailableVersion + $MessageType = 'success' + Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Button1Action $OnClickAction -Button1Text $Button1Text - #Set Post Update actions to 1 - $WAUConfig | New-ItemProperty -Name WAU_PostUpdateActions -Value 1 -Force + # Rerun with newer version + Write-ToLog -LogMsg 'Re-run WAU' + Start-Process -FilePath powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command `"$WorkingDir\winget-upgrade.ps1`"" - #Send success Notif - Write-ToLog "WAU Update completed." "Green" - $Title = $NotifLocale.local.outputs.output[3].title -f "Winget-AutoUpdate" - $Message = $NotifLocale.local.outputs.output[3].message -f $WAUAvailableVersion - $MessageType = "success" - Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Button1Action $OnClickAction -Button1Text $Button1Text - - #Rerun with newer version - Write-ToLog "Re-run WAU" - Start-Process powershell -ArgumentList "-NoProfile -ExecutionPolicy Bypass -Command `"$WorkingDir\winget-upgrade.ps1`"" - - exit - - } - - catch { - - #Send Error Notif - $Title = $NotifLocale.local.outputs.output[4].title -f "Winget-AutoUpdate" - $Message = $NotifLocale.local.outputs.output[4].message - $MessageType = "error" - Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Button1Action $OnClickAction -Button1Text $Button1Text - Write-ToLog "WAU Update failed" "Red" - - } - -} \ No newline at end of file + exit + } + catch + { + # Send Error Notif + $Title = $NotifLocale.local.outputs.output[4].title -f 'Winget-AutoUpdate' + $Message = $NotifLocale.local.outputs.output[4].message + $MessageType = 'error' + Start-NotifTask -Title $Title -Message $Message -MessageType $MessageType -Button1Action $OnClickAction -Button1Text $Button1Text + Write-ToLog -LogMsg 'WAU Update failed' -LogColor 'Red' + } +} diff --git a/Winget-AutoUpdate/functions/Write-ToLog.ps1 b/Winget-AutoUpdate/functions/Write-ToLog.ps1 index db1116e..772c437 100644 --- a/Winget-AutoUpdate/functions/Write-ToLog.ps1 +++ b/Winget-AutoUpdate/functions/Write-ToLog.ps1 @@ -1,14 +1,22 @@ -#Write to Log Function +# Write to Log Function -function Write-ToLog ($LogMsg, $LogColor = "White") { +function Write-ToLog +{ + # Get log + [CmdletBinding()] + param + ( + [string] + $LogMsg, + [string] + $LogColor = 'White' + ) - #Get log - $Log = "$(Get-Date -UFormat "%T") - $LogMsg" + $Log = ('{0} - {1}' -f (Get-Date -UFormat '%T'), $LogMsg) - #Echo log - $Log | Write-host -ForegroundColor $LogColor - - #Write log to file - $Log | Out-File -FilePath $LogFile -Append + #Echo log + $Log | Write-Host -ForegroundColor $LogColor + #Write log to file + $Log | Out-File -FilePath $LogFile -Append -Force -Confirm:$false }