<# .SYNOPSIS Install the AutoFirmer extension from our own update server, via policy. .DESCRIPTION Chrome will not side-load an extension on Windows, and it will not update an unpacked one. The supported way to run an extension you host yourself is an enterprise policy: ExtensionInstallForcelist names the extension id and the update manifest, and from then on Chrome installs it, keeps it updated on its own schedule, and re-installs it if it goes missing. Needs an elevated PowerShell — the policy lives under HKLM. After this runs: * Remove the unpacked copy from chrome://extensions. It has the same id now, and Chrome will not load both. * Restart Chrome, or open chrome://policy and press "Reload policies". * A force-installed extension cannot be disabled or removed from the extensions page. Re-run this with -Remove to take it off. .EXAMPLE powershell -NoProfile -ExecutionPolicy Bypass -File scripts\install-extension-policy.ps1 #> [CmdletBinding()] param( [ValidateSet('Chrome', 'Edge', 'Brave')] [string]$Browser = 'Chrome', # Derived from the signing key on the droplet. It only changes if the key does. [string]$Id = 'lkjbblagjjbldlkeaaffhiopdlhniaan', [string]$UpdateUrl = 'https://ext.juicerroom.com/updates.xml', [switch]$Remove ) $ErrorActionPreference = 'Stop' $roots = @{ Chrome = 'HKLM:\SOFTWARE\Policies\Google\Chrome' Edge = 'HKLM:\SOFTWARE\Policies\Microsoft\Edge' Brave = 'HKLM:\SOFTWARE\Policies\BraveSoftware\Brave' } $identity = [Security.Principal.WindowsIdentity]::GetCurrent() if (-not ([Security.Principal.WindowsPrincipal]$identity).IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'Run this from an elevated PowerShell — the policy key is under HKLM.' } $key = Join-Path $roots[$Browser] 'ExtensionInstallForcelist' $entry = "$Id;$UpdateUrl" if ($Remove) { if (-not (Test-Path $key)) { Write-Host "Nothing to remove — no forcelist for $Browser."; exit 0 } $props = Get-ItemProperty $key $found = $false foreach ($name in ($props.PSObject.Properties.Name | Where-Object { $_ -notlike 'PS*' })) { if ($props.$name -like "$Id;*") { Remove-ItemProperty -Path $key -Name $name Write-Host "Removed $name ($($props.$name))" $found = $true } } if (-not $found) { Write-Host "Nothing to remove — $Id was not in the $Browser forcelist." } Write-Host "`nRestart $Browser to let the change take effect." exit 0 } if (-not (Test-Path $key)) { New-Item -Path $key -Force | Out-Null } # The forcelist is a list expressed as numbered values, so adding to it means # finding a free number rather than overwriting whatever is already there — # another extension may well be in the list. $props = Get-ItemProperty $key $existing = $props.PSObject.Properties | Where-Object { $_.Name -notlike 'PS*' -and $_.Value -like "$Id;*" } if ($existing) { Set-ItemProperty -Path $key -Name $existing.Name -Value $entry Write-Host "Updated $Browser forcelist entry $($existing.Name):" } else { $used = $props.PSObject.Properties.Name | Where-Object { $_ -match '^\d+$' } | ForEach-Object { [int]$_ } $slot = if ($used) { (($used | Measure-Object -Maximum).Maximum + 1) } else { 1 } New-ItemProperty -Path $key -Name "$slot" -Value $entry -PropertyType String -Force | Out-Null Write-Host "Added $Browser forcelist entry ${slot}:" } Write-Host " $entry" Write-Host @" Next: 1. Remove the unpacked copy from chrome://extensions (same id — both cannot load). 2. Restart $Browser, or open chrome://policy and press "Reload policies". 3. Check chrome://extensions: the card should say "Installed by enterprise policy". From here $Browser updates it on its own. The extension also asks for a check as soon as the dashboard reports a newer version, so a release normally lands in seconds rather than waiting out Chrome's own cycle. "@