Configure Edge and Brave too, not just Chrome
They are Chromium: same CRX, same update manifest, same policy — only the registry vendor key differs. The script now defaults to every one of the three it finds installed, which is what the Linux counterpart already did. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
b9da419ebc
commit
b820168afa
@@ -3,12 +3,16 @@
|
||||
Install the AutoFirmer extension from our own update server, via policy.
|
||||
|
||||
.DESCRIPTION
|
||||
Chrome will not side-load an extension on Windows — dropping a CRX on
|
||||
chrome://extensions is refused — and it will not update an unpacked one. The
|
||||
supported way to run an extension you host yourself is a policy:
|
||||
Chrome will not side-load a CRX on Windows — dropping one on
|
||||
chrome://extensions is refused — and it will not update an unpacked folder.
|
||||
The supported way to run an extension you host yourself is a 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.
|
||||
from then on the browser installs it, keeps it updated on its own schedule,
|
||||
and re-installs it if it goes missing.
|
||||
|
||||
Edge and Brave are Chromium too: same CRX, same policy, same update
|
||||
manifest, only a different registry vendor key. By default this configures
|
||||
every one of the three that is actually installed.
|
||||
|
||||
Defaults to the current user's policy hive, which needs no elevation.
|
||||
-Scope Machine writes to HKLM instead, for every account on the box; that
|
||||
@@ -16,8 +20,8 @@
|
||||
|
||||
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".
|
||||
now, and the browser will not load both.
|
||||
* Restart the browser, or open chrome://policy and press "Reload policies".
|
||||
* A force-installed extension cannot be disabled or removed from the
|
||||
extensions page. Re-run with -Remove to take it off.
|
||||
|
||||
@@ -25,12 +29,12 @@
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\install-extension-policy.ps1
|
||||
|
||||
.EXAMPLE
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\install-extension-policy.ps1 -Scope Machine -Browser Edge
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File scripts\install-extension-policy.ps1 -Browser Edge -Scope Machine
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[ValidateSet('Chrome', 'Edge', 'Brave')]
|
||||
[string]$Browser = 'Chrome',
|
||||
[ValidateSet('All', 'Chrome', 'Edge', 'Brave')]
|
||||
[string]$Browser = 'All',
|
||||
|
||||
[ValidateSet('User', 'Machine')]
|
||||
[string]$Scope = 'User',
|
||||
@@ -45,11 +49,28 @@ param(
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# Vendor key under SOFTWARE\Policies, and the executable each one registers.
|
||||
$vendors = @{
|
||||
Chrome = 'Google\Chrome'
|
||||
Edge = 'Microsoft\Edge'
|
||||
Brave = 'BraveSoftware\Brave'
|
||||
}
|
||||
$exes = @{
|
||||
Chrome = 'chrome.exe'
|
||||
Edge = 'msedge.exe'
|
||||
Brave = 'brave.exe'
|
||||
}
|
||||
|
||||
function Test-BrowserInstalled([string]$Name) {
|
||||
# App Paths is where every one of these registers itself, per-machine or
|
||||
# per-user depending on how it was installed.
|
||||
foreach ($hive in @('HKLM:', 'HKCU:')) {
|
||||
if (Test-Path "$hive\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\$($exes[$Name])") {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
$hive = if ($Scope -eq 'Machine') { 'HKLM:' } else { 'HKCU:' }
|
||||
|
||||
@@ -61,55 +82,76 @@ if ($Scope -eq 'Machine') {
|
||||
}
|
||||
}
|
||||
|
||||
$key = "$hive\SOFTWARE\Policies\$($vendors[$Browser])\ExtensionInstallForcelist"
|
||||
$targets = if ($Browser -eq 'All') {
|
||||
@('Chrome', 'Edge', 'Brave') | Where-Object { Test-BrowserInstalled $_ }
|
||||
} else {
|
||||
@($Browser)
|
||||
}
|
||||
|
||||
if (-not $targets) {
|
||||
throw 'Found no Chrome, Edge or Brave installation. Name one with -Browser if it is installed somewhere unusual.'
|
||||
}
|
||||
|
||||
$entry = "$Id;$UpdateUrl"
|
||||
|
||||
if ($Remove) {
|
||||
if (-not (Test-Path $key)) { Write-Host "Nothing to remove — no $Scope 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
|
||||
foreach ($target in $targets) {
|
||||
$key = "$hive\SOFTWARE\Policies\$($vendors[$target])\ExtensionInstallForcelist"
|
||||
|
||||
if ($Remove) {
|
||||
if (-not (Test-Path $key)) {
|
||||
Write-Host "$target : nothing to remove — no $Scope forcelist."
|
||||
continue
|
||||
}
|
||||
$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 "$target : removed entry $name ($($props.$name))"
|
||||
$found = $true
|
||||
}
|
||||
}
|
||||
if (-not $found) { Write-Host "$target : nothing to remove — $Id was not in the $Scope forcelist." }
|
||||
continue
|
||||
}
|
||||
if (-not $found) { Write-Host "Nothing to remove — $Id was not in the $Browser $Scope forcelist." }
|
||||
Write-Host "`nRestart $Browser to let the change take effect."
|
||||
|
||||
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 "$target : updated $Scope 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 "$target : added $Scope forcelist entry $slot"
|
||||
}
|
||||
Write-Host " $key"
|
||||
}
|
||||
|
||||
if ($Remove) {
|
||||
Write-Host "`nRestart the 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 the $Browser $Scope 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 $Scope forcelist entry ${slot}:"
|
||||
}
|
||||
|
||||
Write-Host " $key"
|
||||
Write-Host " $entry"
|
||||
Write-Host @"
|
||||
|
||||
$entry
|
||||
|
||||
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".
|
||||
2. Restart the browser, or open its chrome://policy page and press "Reload policies".
|
||||
3. The card should read "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.
|
||||
From here the 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 the browser's own cycle.
|
||||
"@
|
||||
|
||||
Reference in New Issue
Block a user