Merge pull request #176 from Romanitho/User-run-fix

Added support for user profile installed apps 🥳
pull/177/head
Romain 2022-10-11 10:29:49 +02:00 committed by GitHub
commit 356df630fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 145 additions and 52 deletions

View File

@ -46,6 +46,9 @@ Specify the time of the update interval execution time. Default 6AM
.PARAMETER RunOnMetered .PARAMETER RunOnMetered
Run WAU on metered connection. Default No. Run WAU on metered connection. Default No.
.PARAMETER BypassListForUsers
Configure WAU to bypass the Black/White list when run in user context
.EXAMPLE .EXAMPLE
.\winget-install-and-update.ps1 -Silent -DoNotUpdate .\winget-install-and-update.ps1 -Silent -DoNotUpdate
@ -77,7 +80,8 @@ param(
[Parameter(Mandatory = $False)] [ValidateSet("Full", "SuccessOnly", "None")] [String] $NotificationLevel = "Full", [Parameter(Mandatory = $False)] [ValidateSet("Full", "SuccessOnly", "None")] [String] $NotificationLevel = "Full",
[Parameter(Mandatory = $False)] [Switch] $UpdatesAtLogon = $false, [Parameter(Mandatory = $False)] [Switch] $UpdatesAtLogon = $false,
[Parameter(Mandatory = $False)] [ValidateSet("Daily", "Weekly", "BiWeekly", "Monthly", "Never")] [String] $UpdatesInterval = "Daily", [Parameter(Mandatory = $False)] [ValidateSet("Daily", "Weekly", "BiWeekly", "Monthly", "Never")] [String] $UpdatesInterval = "Daily",
[Parameter(Mandatory = $False)] [DateTime] $UpdatesAtTime = ("06am") [Parameter(Mandatory = $False)] [DateTime] $UpdatesAtTime = ("06am"),
[Parameter(Mandatory = $False)] [Switch] $BypassListForUsers = $false
) )
<# APP INFO #> <# APP INFO #>
@ -265,6 +269,15 @@ function Install-WingetAutoUpdate {
$task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings -Trigger $taskTriggers $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings -Trigger $taskTriggers
Register-ScheduledTask -TaskName 'Winget-AutoUpdate' -InputObject $task -Force | Out-Null Register-ScheduledTask -TaskName 'Winget-AutoUpdate' -InputObject $task -Force | Out-Null
# 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
# 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
# Settings for the scheduled task for Notifications # 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`"`"" $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 $taskUserPrincipal = New-ScheduledTaskPrincipal -GroupId S-1-5-11
@ -274,6 +287,14 @@ function Install-WingetAutoUpdate {
$task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings $task = New-ScheduledTask -Action $taskAction -Principal $taskUserPrincipal -Settings $taskSettings
Register-ScheduledTask -TaskName 'Winget-AutoUpdate-Notify' -InputObject $task -Force | Out-Null Register-ScheduledTask -TaskName 'Winget-AutoUpdate-Notify' -InputObject $task -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)
# Configure Reg Key # Configure Reg Key
$regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" $regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate"
New-Item $regPath -Force | Out-Null New-Item $regPath -Force | Out-Null
@ -304,6 +325,9 @@ function Install-WingetAutoUpdate {
if ($ListPath){ if ($ListPath){
New-ItemProperty $regPath -Name ListPath -Value $ListPath -Force | Out-Null New-ItemProperty $regPath -Name ListPath -Value $ListPath -Force | Out-Null
} }
if ($BypassListForUsers){
New-ItemProperty $regPath -Name WAU_BypassListForUsers -Value 1 -PropertyType DWord -Force | Out-Null
}
Write-host "WAU Installation succeeded!" -ForegroundColor Green Write-host "WAU Installation succeeded!" -ForegroundColor Green
Start-sleep 1 Start-sleep 1
@ -338,6 +362,7 @@ function Uninstall-WingetAutoUpdate {
} }
Get-ScheduledTask -TaskName "Winget-AutoUpdate" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False 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-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 "HKCR\AppUserModelId\Windows.SystemToast.Winget.Notification" /f | Out-Null
& reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" /f | Out-Null & reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" /f | Out-Null
@ -420,10 +445,4 @@ else {
} }
Write-host "`nEnd of process." -ForegroundColor Cyan Write-host "`nEnd of process." -ForegroundColor Cyan
Start-Sleep 3
if (!$Silent) {
Timeout 10
}
else {
Start-Sleep 1
}

View File

@ -49,6 +49,7 @@ try {
} }
Get-ScheduledTask -TaskName "Winget-AutoUpdate" -ErrorAction SilentlyContinue | Unregister-ScheduledTask -Confirm:$False 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-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 "HKCR\AppUserModelId\Windows.SystemToast.Winget.Notification" /f | Out-Null
& reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" /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") { if (Test-Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate") {

View File

@ -14,11 +14,7 @@ Function Get-WingetCmd {
if ($WingetCmd) { if ($WingetCmd) {
$Script:Winget = $WingetCmd.Source $Script:Winget = $WingetCmd.Source
} }
#Get Winget Location in System context (WinGet < 1.17) #Get Winget Location in System context
elseif (Test-Path "$WingetPath\AppInstallerCLI.exe") {
$Script:Winget = "$WingetPath\AppInstallerCLI.exe"
}
#Get Winget Location in System context (WinGet > 1.17)
elseif (Test-Path "$WingetPath\winget.exe") { elseif (Test-Path "$WingetPath\winget.exe") {
$Script:Winget = "$WingetPath\winget.exe" $Script:Winget = "$WingetPath\winget.exe"
} }
@ -28,7 +24,7 @@ Function Get-WingetCmd {
} }
#Run winget to list apps and accept source agrements (necessary on first run) #Run winget to list apps and accept source agrements (necessary on first run)
& $Winget list --accept-source-agreements | Out-Null & $Winget list --accept-source-agreements -s winget | Out-Null
#Log Winget installed version #Log Winget installed version
$WingetVer = & $Winget --version $WingetVer = & $Winget --version

View File

@ -52,5 +52,11 @@ function Get-WingetOutdatedApps {
} }
} }
#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}
}
return $upgradeList | Sort-Object {Get-Random} return $upgradeList | Sort-Object {Get-Random}
} }

View File

@ -0,0 +1,15 @@
function Get-WingetSystemApps {
#Json File where to export system installed apps
$jsonFile = "$WorkingDir\winget_system_apps.txt"
#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 $jsonFile | ConvertFrom-Json
#Return app list
Set-Content $InstalledApps.Sources.Packages.PackageIdentifier -Path $jsonFile
}

View File

@ -87,6 +87,36 @@ function Invoke-PostUpdateActions {
} }
} }
#Set new User Context task and Set system task readable/runnable for all users
$UserTask = Get-ScheduledTask -TaskName "Winget-AutoUpdate-UserContext" -ErrorAction SilentlyContinue
if (!$UserTask){
# Settings for the scheduled task in User context
$taskAction = New-ScheduledTaskAction -Execute "wscript.exe" -Argument "`"$($WorkingDir)\Invisible.vbs`" `"powershell.exe -NoProfile -ExecutionPolicy Bypass -File `"`"`"$($WorkingDir)\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
Register-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -InputObject $task -Force | Out-Null
#Set System task runnable for 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 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
#Reset WAU_UpdatePostActions Value #Reset WAU_UpdatePostActions Value
$WAUConfig | New-ItemProperty -Name WAU_PostUpdateActions -Value 0 -Force $WAUConfig | New-ItemProperty -Name WAU_PostUpdateActions -Value 0 -Force

View File

@ -9,33 +9,25 @@ function Start-Init {
$Log = "`n##################################################`n# CHECK FOR APP UPDATES - $(Get-Date -Format (Get-culture).DateTimeFormat.ShortDatePattern)`n##################################################" $Log = "`n##################################################`n# CHECK FOR APP UPDATES - $(Get-Date -Format (Get-culture).DateTimeFormat.ShortDatePattern)`n##################################################"
$Log | Write-host $Log | Write-host
#Logs initialisation if admin #Logs initialisation
try { $Script:LogFile = "$WorkingDir\logs\updates.log"
$LogPath = "$WorkingDir\logs" if (!(Test-Path $LogFile)) {
#Create file if doesn't exist
if (!(Test-Path $LogPath)) { New-Item -ItemType File -Path $LogFile -Force
New-Item -ItemType Directory -Force -Path $LogPath
}
#Log file
$Script:LogFile = "$LogPath\updates.log"
$Log | out-file -filepath $LogFile -Append
#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
} }
#Logs initialisation if non-admin
catch {
$LogPath = "$env:USERPROFILE\Winget-AutoUpdate\logs" #Log file
$Log | out-file -filepath $LogFile -Append
if (!(Test-Path $LogPath)) {
New-Item -ItemType Directory -Force -Path $LogPath
}
#Log file
$Script:LogFile = "$LogPath\updates.log"
$Log | out-file -filepath $LogFile -Append
}
} }

View File

@ -23,11 +23,8 @@ function Start-NotifTask ($Title, $Message, $MessageType, $Balise, $OnClickActio
</toast> </toast>
"@ "@
#Check if running account is system or interactive logon
$currentPrincipal = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-4")
#if not "Interactive" user, run as system #if not "Interactive" user, run as system
if ($currentPrincipal -eq $false) { if ($IsSystem) {
#Save XML to File #Save XML to File
$ToastTemplateLocation = "$env:ProgramData\Winget-AutoUpdate\config\" $ToastTemplateLocation = "$env:ProgramData\Winget-AutoUpdate\config\"

View File

@ -18,10 +18,6 @@ function Test-PendingReboot {
if (([WmiClass]"\\$Computer\ROOT\CCM\ClientSDK:CCM_ClientUtilities").DetermineIfRebootPending().RebootPending -eq $true) {$PendingReboot = $true} if (([WmiClass]"\\$Computer\ROOT\CCM\ClientSDK:CCM_ClientUtilities").DetermineIfRebootPending().RebootPending -eq $true) {$PendingReboot = $true}
} }
# [PSCustomObject]@{
# ComputerName = $Computer.ToUpper()
# PendingReboot = $PendingReboot
# }
} }
return $PendingReboot return $PendingReboot

View File

@ -8,9 +8,20 @@ Get-ChildItem "$WorkingDir\functions" | ForEach-Object { . $_.FullName }
<# MAIN #> <# MAIN #>
#Check if running account is system or interactive logon
$Script:IsSystem = [System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem
#Run log initialisation function #Run log initialisation function
Start-Init Start-Init
#Log running context
if ($IsSystem) {
Write-Log "Running in System context"
}
else{
Write-Log "Running in User context"
}
#Get WAU Configurations #Get WAU Configurations
$Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate" $Script:WAUConfig = Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Winget-AutoUpdate"
@ -20,7 +31,7 @@ if (!($WAUConfig.WAU_PostUpdateActions -eq 0)) {
} }
#Run Scope Machine funtion if run as system #Run Scope Machine funtion if run as system
if ([System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem) { if ($IsSystem) {
$SettingsPath = "$Env:windir\system32\config\systemprofile\AppData\Local\Microsoft\WinGet\Settings\defaultState\settings.json" $SettingsPath = "$Env:windir\system32\config\systemprofile\AppData\Local\Microsoft\WinGet\Settings\defaultState\settings.json"
Add-ScopeMachine $SettingsPath Add-ScopeMachine $SettingsPath
} }
@ -51,7 +62,12 @@ if (Test-Network) {
if ([version]$WAUAvailableVersion -gt [version]$WAUCurrentVersion) { if ([version]$WAUAvailableVersion -gt [version]$WAUCurrentVersion) {
#If new version is available, update it #If new version is available, update it
Write-Log "WAU Available version: $WAUAvailableVersion" "Yellow" Write-Log "WAU Available version: $WAUAvailableVersion" "Yellow"
Update-WAU if ($IsSystem) {
Update-WAU
}
else{
Write-Log "WAU Needs to run as system to update" "Yellow"
}
} }
else { else {
Write-Log "WAU is up to date." "Green" Write-Log "WAU is up to date." "Green"
@ -95,6 +111,13 @@ if (Test-Network) {
#Count good update installations #Count good update installations
$Script:InstallOK = 0 $Script:InstallOK = 0
#Trick under user context when -BypassListForUsers is used
if ($IsSystem -eq $false -and $WAUConfig.WAU_BypassListForUsers -eq $true){
Write-Log "Bypass system list in user context is Enabled."
$UseWhiteList = $false
$toSkip = $null
}
#If White List #If White List
if ($UseWhiteList) { if ($UseWhiteList) {
#For each app, notify and update #For each app, notify and update
@ -139,6 +162,24 @@ if (Test-Network) {
} }
} }
#Run WAU in user context if currently as system
if ($IsSystem) {
#Get Winget system apps to excape them befor running user context
Get-WingetSystemApps
#Run user context scheduled task
$UserScheduledTask = Get-ScheduledTask -TaskName "Winget-AutoUpdate-UserContext" -ErrorAction SilentlyContinue
if ($UserScheduledTask){
Write-Log "Starting WAU in User context"
Start-ScheduledTask $UserScheduledTask.TaskName -ErrorAction SilentlyContinue
Exit 0
}
else {
Write-Log "User context execution not installed"
}
}
#End #End
Write-Log "End of process!" "Cyan" Write-Log "End of process!" "Cyan"
Start-Sleep 3 Start-Sleep 3