Skip to content

Commit

Permalink
Merge pull request #789 from AndrewDemski-ad-gmail-com/main
Browse files Browse the repository at this point in the history
Step towards experimental group of settings in ADMX Policies
  • Loading branch information
Romanitho authored Jan 24, 2025
2 parents f731208 + 050d176 commit dbffc74
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 95 deletions.
15 changes: 14 additions & 1 deletion Sources/Policies/ADMX/WAU.admx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@
<definitions>
<definition name="SUPPORTED_WAU_1_16_0" displayName="$(string.SUPPORTED_WAU_1_16_0)"/>
<definition name="SUPPORTED_WAU_1_16_5" displayName="$(string.SUPPORTED_WAU_1_16_5)"/>
<definition name="SUPPORTED_WAU_EXPERIMENTAL" displayName="$(string.SUPPORTED_WAU_EXPERIMENTAL)"/>
</definitions>
</supportedOn>
<categories><category displayName="$(string.WAU)" name="WAU"/></categories>
<categories>
<category displayName="$(string.WAU)" name="WAU"/>
<category name="Experimental" displayName="$(string.WAUEX)">
<parentCategory ref="WAU" />
</category>
</categories>
<policies>
<policy name="ActivateGPOManagement_Enable" class="Machine" displayName="$(string.ActivateGPOManagement_Name)" explainText="$(string.ActivateGPOManagement_Explain)" key="Software\Policies\Romanitho\Winget-AutoUpdate" valueName="WAU_ActivateGPOManagement">
<parentCategory ref="WAU"/>
Expand Down Expand Up @@ -349,6 +355,13 @@
<elements>
<text id="MaxLogSize" valueName="WAU_MaxLogSize" />
</elements>
</policy>
<policy name="WingetSourceCustom_Enable" class="Machine" displayName="$(string.WingetSourceCustom_Name)" explainText="$(string.WingetSourceCustom_Explain)" key="Software\Policies\Romanitho\Winget-AutoUpdate" presentation="$(presentation.WingetSourceCustom)" >
<parentCategory ref="Experimental"/>
<supportedOn ref="WAU:SUPPORTED_WAU_EXPERIMENTAL"/>
<elements>
<text id="WingetSourceCustom" valueName="WAU_WingetSourceCustom" />
</elements>
</policy>
</policies>
</policyDefinitions>
14 changes: 14 additions & 0 deletions Sources/Policies/ADMX/en-US/WAU.adml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
<resources >
<stringTable >
<string id="WAU">Winget-AutoUpdate</string>
<string id="WAUEX">Experimental</string>
<string id="SUPPORTED_WAU_1_16_0">Winget-AutoUpdate version 1.16.0 or later</string>
<string id="SUPPORTED_WAU_1_16_5">Winget-AutoUpdate version 1.16.5 or later</string>
<string id="SUPPORTED_WAU_EXPERIMENTAL">Winget-AutoUpdate Experimental, subject to change, do not use on PROD</string>
<string id="ActivateGPOManagement_Name">Activate WAU GPO Management</string>
<string id="ActivateGPOManagement_Explain">This policy setting is an overriding toggle for GPO Management of Winget-AutoUpdate.</string>
<string id="BypassListForUsers_Name">Bypass Black/White list for User</string>
Expand Down Expand Up @@ -140,6 +142,13 @@ If this policy is disabled or not configured, the default number is used.</strin
Default size is 1048576 = 1 MB

If this policy is disabled or not configured, the default size is used.</string>
<string id="WingetSourceCustom_Name">Use custom Winget Source repository</string>
<string id="WingetSourceCustom_Explain">This policy setting specifies whether to use winget tool with custom repository or not:
(WAU - Check for updated Apps)

If this policy is enabled, WAU will TRY to use a custom repo instead of the built-in/default one called winget.

If this policy is disabled or not configured, the default is always the built-in winget.</string>
</stringTable>
<presentationTable>
<presentation id="BlackList">
Expand Down Expand Up @@ -182,6 +191,11 @@ If this policy is disabled or not configured, the default size is used.</string>
<label>Size of the log file:</label>
</textBox>
</presentation>
<presentation id="WingetSourceCustom">
<textBox refId="WingetSourceCustom">
<label>Name of custom winget source:</label>
</textBox>
</presentation>
</presentationTable>
</resources>
</policyDefinitionResources>
192 changes: 118 additions & 74 deletions Sources/Winget-AutoUpdate/Winget-Upgrade.ps1
Original file line number Diff line number Diff line change
@@ -1,46 +1,84 @@
<# LOAD FUNCTIONS #>

#Get the Working Dir
$Script:WorkingDir = $PSScriptRoot
#Get Functions
Get-ChildItem "$WorkingDir\functions" -File -Filter "*.ps1" -Depth 0 | ForEach-Object { . $_.FullName }
#region LOAD FUNCTIONS
# Get the Working Dir
[string]$Script:WorkingDir = $PSScriptRoot;

# Get Functions
Get-ChildItem -Path "$($Script:WorkingDir)\functions" -File -Filter "*.ps1" -Depth 0 | ForEach-Object { . $_.FullName; }
#endregion LOAD FUNCTIONS

<# MAIN #>

#Config console output encoding
$null = cmd /c ''
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$Script:ProgressPreference = 'SilentlyContinue'
# Config console output encoding
$null = cmd /c '';
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8;
$Script:ProgressPreference = [System.Management.Automation.ActionPreference]::SilentlyContinue;

# Set GitHub Repo
[string]$Script:GitHub_Repo = "Winget-AutoUpdate";

# Log initialization
[string]$LogFile = [System.IO.Path]::Combine($Script:WorkingDir, 'logs', 'updates.log');

#region Get settings and Domain/Local Policies (GPO) if activated.
Write-ToLog "Reading WAUConfig";
$Script:WAUConfig = Get-WAUConfig;

if ($WAUConfig.WAU_ActivateGPOManagement -eq 1) {
Write-ToLog "WAU Policies management Enabled.";
}
#endregion Get settings and Domain/Local Policies (GPO) if activated.

#region Winget Source Custom
# Default name of winget repository used within this script
[string]$DefaultWingetRepoName = 'winget';

#Set GitHub Repo
$Script:GitHub_Repo = "Winget-AutoUpdate"
# Defining custom repository for winget tool (only if GPO management is active)
if($Script:WAUConfig.WAU_ActivateGPOManagement) {
if($null -eq $Script:WAUConfig.WAU_WingetSourceCustom) {
[string]$Script:WingetSourceCustom = $DefaultWingetRepoName;
}
else {
[string]$Script:WingetSourceCustom = $Script:WAUConfig.WAU_WingetSourceCustom.Trim();
}
Write-ToLog "Selecting winget repository named '$($Script:WingetSourceCustom)'";
}
#endregion Winget Source Custom

#Log initialization
$LogFile = "$WorkingDir\logs\updates.log"
#region Checking execution context
# Check if running account is system or interactive logon System(default) otherwise User
[bool]$Script:IsSystem = [System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem;

# Check for current session ID (O = system without ServiceUI)
[Int32]$Script:SessionID = [System.Diagnostics.Process]::GetCurrentProcess().SessionId;
#endregion

#Check if running account is system or interactive logon
$Script:IsSystem = [System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem
#Check for current session ID (O = system without ServiceUI)
$Script:SessionID = [System.Diagnostics.Process]::GetCurrentProcess().SessionId
# Preparation to run in current context
if ($true -eq $IsSystem) {

#Check if running as system
if ($IsSystem) {
#If log file doesn't exist, force create it
if (!(Test-Path -Path $LogFile)) {
Write-ToLog "New log file created"
Write-ToLog "New log file created";
}

# paths
[string]$IntuneLogsDir = "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs";
[string]$fp0 = [System.IO.Path]::Combine($IntuneLogsDir, 'WAU-updates.log');
[string]$fp1 = [System.IO.Path]::Combine($Script:WorkingDir, 'logs', 'install.log');
[string]$fp2 = [System.IO.Path]::Combine($IntuneLogsDir, 'WAU-install.log');

# Check if Intune Management Extension Logs folder exists
if ((Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs" -ErrorAction SilentlyContinue)) {
if (Test-Path -Path $IntuneLogsDir -PathType Container -ErrorAction SilentlyContinue) {

# Check if symlink WAU-updates.log exists, make symlink (doesn't work under ServiceUI)
if (!(Test-Path -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -ErrorAction SilentlyContinue)) {
$null = New-Item -Path "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-updates.log" -ItemType SymbolicLink -Value $LogFile -Force -ErrorAction SilentlyContinue
Write-ToLog "SymLink for 'update' log file created in Intune Management Extension log folder"
if (!(Test-Path -Path $fp0 -ErrorAction SilentlyContinue)) {
New-Item -Path $fp0 -ItemType SymbolicLink -Value $LogFile -Force -ErrorAction SilentlyContinue | Out-Null;
Write-ToLog "SymLink for 'update' log file created in in $($IntuneLogsDir) folder";
}

# Check if install.log and symlink WAU-install.log exists, make symlink (doesn't work under ServiceUI)
if ((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)) {
$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 "SymLink for 'install' log file created in Intune Management Extension log folder"
if ( (Test-Path -Path $fp1 -ErrorAction SilentlyContinue) -and !(Test-Path -Path $fp2 -ErrorAction SilentlyContinue) ) {
New-Item -Path $fp2 -ItemType SymbolicLink -Value $fp1 -Force -Confirm:$False -ErrorAction SilentlyContinue | Out-Null;
Write-ToLog "SymLink for 'install' log file created in $($IntuneLogsDir) folder"
}
# Check if user install.log and symlink WAU-install-username.log exists, make symlink (doesn't work under ServiceUI)
# Get all user directories from C:\Users (excluding default/system profiles)
Expand All @@ -65,18 +103,23 @@ if ($IsSystem) {
}
}
}

#Check if running with session ID 0
if ($SessionID -eq 0) {
#Check if ServiceUI exists
$ServiceUI = Test-Path "$WorkingDir\ServiceUI.exe"
if ($ServiceUI) {
[string]$fp3 = [System.IO.Path]::Combine($Script:WorkingDir, 'ServiceUI.exe');
[bool]$ServiceUI = Test-Path $fp3 -PathType Leaf;
if ($true -eq $ServiceUI) {
#Check if any connected user
$explorerprocesses = @(Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue)
$explorerprocesses = @(Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue);
if ($explorerprocesses.Count -gt 0) {
#Rerun WAU in system context with ServiceUI
Start-Process "ServiceUI.exe" -ArgumentList "-process:explorer.exe $env:windir\System32\conhost.exe --headless powershell.exe -NoProfile -ExecutionPolicy Bypass -File winget-upgrade.ps1" -WorkingDirectory $WorkingDir
Wait-Process "ServiceUI" -ErrorAction SilentlyContinue
Exit 0
Write-ToLog "Rerun WAU in system context with ServiceUI";
Start-Process `
-FilePath $fp3 `
-ArgumentList "-process:explorer.exe $env:windir\System32\conhost.exe --headless powershell.exe -NoProfile -ExecutionPolicy Bypass -File winget-upgrade.ps1" `
-WorkingDirectory $WorkingDir;
Wait-Process "ServiceUI" -ErrorAction SilentlyContinue;
Exit 0;
}
else {
Write-ToLog -LogMsg "CHECK FOR APP UPDATES (System context)" -IsHeader
Expand All @@ -94,90 +137,91 @@ else {
Write-ToLog -LogMsg "CHECK FOR APP UPDATES (User context)" -IsHeader
}

#Get settings and Domain/Local Policies (GPO) if activated.
$Script:WAUConfig = Get-WAUConfig
if ($($WAUConfig.WAU_ActivateGPOManagement -eq 1)) {
Write-ToLog "WAU Policies management Enabled."
}

#Log running context and more...
if ($IsSystem) {
#region Log running context
if ($true -eq $IsSystem) {

# 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
[int32]$MaxLogFiles = 3;
}
else {
[int32] $MaxLogFiles = $MaxLogFiles
[int32]$MaxLogFiles = $MaxLogFiles;
}

# Maximum size of log file.
$MaxLogSize = $WAUConfig.WAU_MaxLogSize
$MaxLogSize = $WAUConfig.WAU_MaxLogSize;
if (!$MaxLogSize) {
[int64] $MaxLogSize = 1048576 # in bytes, default is 1048576 = 1 MB
[int64]$MaxLogSize = [int64]1MB; # in bytes, default is 1 MB = 1048576
}
else {
[int64] $MaxLogSize = $MaxLogSize
[int64]$MaxLogSize = $MaxLogSize;
}

#LogRotation if System
$LogRotate = Invoke-LogRotation $LogFile $MaxLogFiles $MaxLogSize
if ($LogRotate -eq $False) {
[bool]$LogRotate = Invoke-LogRotation $LogFile $MaxLogFiles $MaxLogSize;
if ($false -eq $LogRotate) {
Write-ToLog "An Exception occurred during Log Rotation..."
}
}
#endregion Log running context

#Run Scope Machine function if run as System
Add-ScopeMachine
#region Run Scope Machine function if run as System
if ($true -eq $IsSystem) {
Add-ScopeMachine;
}
#endregion Run Scope Machine function if run as System

#Get Notif Locale function
$LocaleDisplayName = Get-NotifLocale
Write-ToLog "Notification Level: $($WAUConfig.WAU_NotificationLevel). Notification Language: $LocaleDisplayName" "Cyan"
#region Get Notif Locale function
[string]$LocaleDisplayName = Get-NotifLocale;
Write-ToLog "Notification Level: $($WAUConfig.WAU_NotificationLevel). Notification Language: $LocaleDisplayName" "Cyan";
#endregion

#Check network connectivity
if (Test-Network) {

#Check prerequisites
if ($IsSystem) {
Install-Prerequisites
if ($true -eq $IsSystem) {
Install-Prerequisites;
}

#Check if Winget is installed and get Winget cmd
$Script:Winget = Get-WingetCmd
[string]$Script:Winget = Get-WingetCmd;
Write-ToLog "Selected winget instance: $($Script:Winget)";

if ($Winget) {
if ($Script:Winget) {

if ($IsSystem) {
if ($true -eq $IsSystem) {

#Get Current Version
$WAUCurrentVersion = $WAUConfig.ProductVersion
Write-ToLog "WAU current version: $WAUCurrentVersion"
$WAUCurrentVersion = $WAUConfig.ProductVersion;
Write-ToLog "WAU current version: $WAUCurrentVersion";

#Check if WAU update feature is enabled or not if run as System
$WAUDisableAutoUpdate = $WAUConfig.WAU_DisableAutoUpdate
$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"
Write-ToLog "WAU AutoUpdate is Disabled." "Gray";
}
else {
Write-ToLog "WAU AutoUpdate is Enabled." "Green"
Write-ToLog "WAU AutoUpdate is Enabled." "Green";
#Get Available Version
$Script:WAUAvailableVersion = Get-WAUAvailableVersion
$Script:WAUAvailableVersion = Get-WAUAvailableVersion;
#Compare
if ([version]$WAUAvailableVersion.replace("-n", "") -gt [version]$WAUCurrentVersion.replace("-n", "")) {
#If new version is available, update it
Write-ToLog "WAU Available version: $WAUAvailableVersion" "Yellow"
Update-WAU
Write-ToLog "WAU Available version: $WAUAvailableVersion" "Yellow";
Update-WAU;
}
else {
Write-ToLog "WAU is up to date." "Green"
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
[string]$fp4 = [System.IO.Path]::Combine($Script:WorkingDir, 'logs', 'error.txt');
if (Test-Path $fp4) {
Remove-Item $fp4 -Force;
}

#Get External ListPath if run as System
Expand Down Expand Up @@ -307,8 +351,8 @@ if (Test-Network) {
}

#Get outdated Winget packages
Write-ToLog "Checking application updates on Winget Repository..." "yellow"
$outdated = Get-WingetOutdatedApps
Write-ToLog "Checking application updates on Winget Repository named '$($Script:WingetSourceCustom)' .." "yellow"
$outdated = Get-WingetOutdatedApps -src $Script:WingetSourceCustom;

#If something unusual happened or no update found
if ($outdated -like "No update found.*") {
Expand Down Expand Up @@ -401,7 +445,7 @@ if (Test-Network) {
Else {
#Get Winget system apps to escape them before running user context
Write-ToLog "User logged on, get a list of installed Winget apps in System context..."
Get-WingetSystemApps
Get-WingetSystemApps -src $Script:WingetSourceCustom;

#Run user context scheduled task
Write-ToLog "Starting WAU in User context..."
Expand Down
22 changes: 13 additions & 9 deletions Sources/Winget-AutoUpdate/functions/Get-WingetCmd.ps1
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
#Function to get the winget command regarding execution context (User, System...)

Function Get-WingetCmd {

$WingetCmd = $null
[OutputType([String])]
$WingetCmd = [string]::Empty;

#Get WinGet Path
# default winget path (in system context)
[string]$ps = "$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller_*_8wekyb3d8bbwe\winget.exe";

#default winget path (in user context)
[string]$pu = "$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe";

try {
#Get Admin Context Winget Location
$WingetInfo = (Get-Item "$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller_*_8wekyb3d8bbwe\winget.exe").VersionInfo | Sort-Object -Property FileVersionRaw
$WingetInfo = (Get-Item -Path $ps).VersionInfo | Sort-Object -Property FileVersionRaw -Descending | Select-Object -First 1;
#If multiple versions, pick most recent one
$WingetCmd = $WingetInfo[-1].FileName
$WingetCmd = $WingetInfo.FileName;
}
catch {
#Get User context Winget Location
if (Test-Path "$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe") {
$WingetCmd = "$env:LocalAppData\Microsoft\WindowsApps\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\winget.exe"
if (Test-Path -Path $pu -PathType Leaf) {
$WingetCmd = $pu;
}
}

return $WingetCmd

return $WingetCmd;
}
Loading

0 comments on commit dbffc74

Please sign in to comment.