#Requires -Version 5.1 # Firefox Add-on Manager - Maschinenbasierte Bereitstellung # Fuer maschinenweite Deployment-Optionen als Administrator ausfuehren. Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing # ---- Hilfsfunktionen ---- function Find-FirefoxProfile { $appData = [Environment]::GetFolderPath("ApplicationData") $profilesPath = Join-Path $appData "Mozilla\Firefox\Profiles" if (-not (Test-Path $profilesPath)) { return $null } $profiles = Get-ChildItem $profilesPath -Directory | Where-Object { $_.Name -match '\.default' -or $_.Name -match 'default-release' } if ($profiles) { return $profiles[0].FullName } $all = Get-ChildItem $profilesPath -Directory if ($all) { return $all[0].FullName } return $null } function Find-FirefoxInstallDir { $candidates = @( "C:\Program Files\Mozilla Firefox", "C:\Program Files (x86)\Mozilla Firefox" ) foreach ($c in $candidates) { if (Test-Path (Join-Path $c "firefox.exe")) { return $c } } # Suche in Registry try { $reg = Get-ItemProperty "HKLM:\SOFTWARE\Mozilla\Mozilla Firefox" -ErrorAction Stop $installDir = $reg."Install Directory" if ($installDir -and (Test-Path $installDir)) { return $installDir } } catch {} return $null } function Get-InstalledAddons { param([string]$ProfilePath) $extensionsJson = Join-Path $ProfilePath "extensions.json" if (-not (Test-Path $extensionsJson)) { return @() } $json = Get-Content $extensionsJson -Raw | ConvertFrom-Json return $json.addons | Where-Object { $_.type -eq "extension" } | Select-Object id, defaultLocale, version, active } function Install-AddonFromFile { param([string]$ProfilePath, [string]$XpiPath) $extensionsDir = Join-Path $ProfilePath "extensions" if (-not (Test-Path $extensionsDir)) { New-Item -ItemType Directory -Path $extensionsDir | Out-Null } Add-Type -AssemblyName System.IO.Compression.FileSystem $zip = [System.IO.Compression.ZipFile]::OpenRead($XpiPath) try { $manifestEntry = $zip.Entries | Where-Object { $_.Name -eq "manifest.json" } if (-not $manifestEntry) { throw "Kein manifest.json in der XPI-Datei gefunden." } $reader = New-Object System.IO.StreamReader($manifestEntry.Open()) $manifest = $reader.ReadToEnd() | ConvertFrom-Json $reader.Close() $addonId = $null if ($manifest.browser_specific_settings.gecko.id) { $addonId = $manifest.browser_specific_settings.gecko.id } elseif ($manifest.applications.gecko.id) { $addonId = $manifest.applications.gecko.id } else { $addonId = [System.IO.Path]::GetFileNameWithoutExtension($XpiPath) + "@local" } } finally { $zip.Dispose() } $dest = Join-Path $extensionsDir "$addonId.xpi" Copy-Item -Path $XpiPath -Destination $dest -Force return $addonId } function Open-AddonPage { param([string]$Url) Start-Process "firefox" $Url -ErrorAction SilentlyContinue if ($LASTEXITCODE -ne 0) { Start-Process $Url } } function Test-IsAdmin { $id = [System.Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object System.Security.Principal.WindowsPrincipal($id) return $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator) } function Test-IntuneManaged { # Intune schreibt Firefox-Policies unter HKLM\SOFTWARE\Policies\Mozilla\Firefox # Wenn dieser Key existiert und NICHT von uns stammt, verwaltet Intune Firefox $key = "HKLM:\SOFTWARE\Policies\Mozilla\Firefox" if (Test-Path $key) { $props = Get-ItemProperty $key -ErrorAction SilentlyContinue # Intune setzt typischerweise DisableAppUpdate, DontCheckDefaultBrowser o.ae. if ($props) { return $true } } return $false } function Get-ActiveFirefoxPolicies { # Liest alle aktiven Registry-Policies aus $base = "HKLM:\SOFTWARE\Policies\Mozilla\Firefox" $result = @() if (-not (Test-Path $base)) { return $result } function Read-RegTree { param([string]$Path, [string]$Indent = "") $props = Get-ItemProperty $Path -ErrorAction SilentlyContinue if ($props) { foreach ($p in $props.PSObject.Properties) { if ($p.Name -notmatch '^PS') { $result += $Indent + $p.Name + " = " + $p.Value } } } Get-ChildItem $Path -ErrorAction SilentlyContinue | ForEach-Object { $result += $Indent + "[" + $_.PSChildName + "]" Read-RegTree -Path $_.PSPath -Indent ($Indent + " ") } } Read-RegTree -Path $base return $result } function Export-RegFile { param([string]$OutputPath, [array]$Addons) $lines = @() $lines += "Windows Registry Editor Version 5.00" $lines += "" $lines += "; Firefox Add-on Deployment via Intune Custom Policy" $lines += "; Importieren: doppelklick auf .reg oder via Intune > Devices > Configuration > Custom (OMA-URI)" $lines += "" $lines += "[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mozilla\Firefox\ExtensionSettings]" $lines += "" foreach ($a in $Addons) { $url = if ($a.Url -and $a.Url.StartsWith("http")) { $a.Url } else { "https://addons.mozilla.org/firefox/downloads/latest/latest.xpi" } # Registry-Schluessel-Namen muessen Backslashes escapen $escapedId = $a.Id -replace '\\', '\\' $lines += '[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mozilla\Firefox\ExtensionSettings\' + $escapedId + ']' $lines += '"installation_mode"="force_installed"' $lines += '"install_url"="' + ($url -replace '\\', '\\') + '"' $lines += "" } $lines | Out-File -FilePath $OutputPath -Encoding Unicode } # ---- Add-on Datenbank ---- $AllAddons = [System.Collections.Generic.List[PSCustomObject]]::new() $AllAddons.Add([PSCustomObject]@{ Name="uBlock Origin"; Id="uBlock0@raymondhill.net" Url="https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi" StoreUrl="https://addons.mozilla.org/firefox/addon/ublock-origin/" Beschreibung="Effizienter Werbeblocker" }) $AllAddons.Add([PSCustomObject]@{ Name="Privacy Badger"; Id="jid1-MnnxcxisBPnSXQ@jetpack" Url="https://addons.mozilla.org/firefox/downloads/latest/privacy-badger17/latest.xpi" StoreUrl="https://addons.mozilla.org/firefox/addon/privacy-badger17/" Beschreibung="Schutz vor Tracking" }) $AllAddons.Add([PSCustomObject]@{ Name="Bitwarden"; Id="{446900e4-71c2-419f-a6a7-df9c091e268b}" Url="https://addons.mozilla.org/firefox/downloads/latest/bitwarden-password-manager/latest.xpi" StoreUrl="https://addons.mozilla.org/firefox/addon/bitwarden-password-manager/" Beschreibung="Passwort-Manager" }) $AllAddons.Add([PSCustomObject]@{ Name="Dark Reader"; Id="addon@darkreader.org" Url="https://addons.mozilla.org/firefox/downloads/latest/darkreader/latest.xpi" StoreUrl="https://addons.mozilla.org/firefox/addon/darkreader/" Beschreibung="Dunkles Design fuer alle Seiten" }) $AllAddons.Add([PSCustomObject]@{ Name="Cookie AutoDelete"; Id="CookieAutoDelete@kennydo.com" Url="https://addons.mozilla.org/firefox/downloads/latest/cookie-autodelete/latest.xpi" StoreUrl="https://addons.mozilla.org/firefox/addon/cookie-autodelete/" Beschreibung="Cookies automatisch loeschen" }) $AllAddons.Add([PSCustomObject]@{ Name="Ghostery"; Id="firefox@ghostery.com" Url="https://addons.mozilla.org/firefox/downloads/latest/ghostery/latest.xpi" StoreUrl="https://addons.mozilla.org/firefox/addon/ghostery/" Beschreibung="Anti-Tracking und Werbeblocker" }) # ---- GUI ---- $form = New-Object System.Windows.Forms.Form $form.Text = "Firefox Add-on Manager - Maschinenbasierte Bereitstellung" $form.Size = New-Object System.Drawing.Size(900, 680) $form.StartPosition = "CenterScreen" $form.FormBorderStyle = "FixedSingle" $form.MaximizeBox = $false $form.BackColor = [System.Drawing.Color]::FromArgb(245, 245, 250) # Banner $banner = New-Object System.Windows.Forms.Panel $banner.Size = New-Object System.Drawing.Size(900, 60) $banner.Location = New-Object System.Drawing.Point(0, 0) $banner.BackColor = [System.Drawing.Color]::FromArgb(255, 100, 20) $form.Controls.Add($banner) $titleLabel = New-Object System.Windows.Forms.Label $titleLabel.Text = "Firefox Add-on Manager" $titleLabel.Font = New-Object System.Drawing.Font("Segoe UI", 16, [System.Drawing.FontStyle]::Bold) $titleLabel.ForeColor = [System.Drawing.Color]::White $titleLabel.AutoSize = $true $titleLabel.Location = New-Object System.Drawing.Point(15, 10) $banner.Controls.Add($titleLabel) $adminLabel = New-Object System.Windows.Forms.Label if (Test-IsAdmin) { $adminLabel.Text = "Administrator-Modus aktiv" $adminLabel.ForeColor = [System.Drawing.Color]::LightGreen } else { $adminLabel.Text = "KEIN Admin - maschinenweite Bereitstellung eingeschraenkt" $adminLabel.ForeColor = [System.Drawing.Color]::Yellow } $adminLabel.Font = New-Object System.Drawing.Font("Segoe UI", 8) $adminLabel.AutoSize = $true $adminLabel.Location = New-Object System.Drawing.Point(17, 40) $banner.Controls.Add($adminLabel) # TabControl $tabs = New-Object System.Windows.Forms.TabControl $tabs.Location = New-Object System.Drawing.Point(10, 70) $tabs.Size = New-Object System.Drawing.Size(870, 535) $tabs.Font = New-Object System.Drawing.Font("Segoe UI", 10) $form.Controls.Add($tabs) # =========================================================== # TAB 1: Maschinenbasierte Bereitstellung (policies.json) # =========================================================== $tabDeploy = New-Object System.Windows.Forms.TabPage $tabDeploy.Text = "Maschinenweite Bereitstellung" $tabs.Controls.Add($tabDeploy) # Info-Box $pnlInfo = New-Object System.Windows.Forms.Panel $pnlInfo.Location = New-Object System.Drawing.Point(10, 10) $pnlInfo.Size = New-Object System.Drawing.Size(845, 55) $pnlInfo.BackColor = [System.Drawing.Color]::FromArgb(220, 235, 255) $pnlInfo.BorderStyle = "FixedSingle" $tabDeploy.Controls.Add($pnlInfo) $lblInfoText = New-Object System.Windows.Forms.Label $lblInfoText.Text = "Add-ons werden per Firefox Enterprise Policy (policies.json) oder Windows Registry fuer ALLE Benutzer" + " dieser Maschine zwingend installiert. Erfordert Administratorrechte und Firefox-Neustart." $lblInfoText.Font = New-Object System.Drawing.Font("Segoe UI", 8) $lblInfoText.Location = New-Object System.Drawing.Point(5, 5) $lblInfoText.Size = New-Object System.Drawing.Size(833, 44) $pnlInfo.Controls.Add($lblInfoText) # Interne URL Warnung $pnlUrlWarn = New-Object System.Windows.Forms.Panel $pnlUrlWarn.Location = New-Object System.Drawing.Point(10, 75) $pnlUrlWarn.Size = New-Object System.Drawing.Size(845, 28) $pnlUrlWarn.BackColor = [System.Drawing.Color]::FromArgb(255, 240, 200) $pnlUrlWarn.BorderStyle = "FixedSingle" $tabDeploy.Controls.Add($pnlUrlWarn) $lblUrlWarn = New-Object System.Windows.Forms.Label $lblUrlWarn.Text = "Intune/Firmen-Umgebung: addons.mozilla.org ist moeglicherweise blockiert. " + "Bitte XPIs herunterladen, intern hosten und interne URL eintragen (Spalte 'Interne URL')." $lblUrlWarn.Font = New-Object System.Drawing.Font("Segoe UI", 8) $lblUrlWarn.ForeColor = [System.Drawing.Color]::DarkOrange $lblUrlWarn.Location = New-Object System.Drawing.Point(5, 6) $lblUrlWarn.AutoSize = $true $pnlUrlWarn.Controls.Add($lblUrlWarn) # Add-on Auswahl $grpSelect = New-Object System.Windows.Forms.GroupBox $grpSelect.Text = "Add-ons auswaehlen (Doppelklick = interne URL bearbeiten)" $grpSelect.Location = New-Object System.Drawing.Point(10, 110) $grpSelect.Size = New-Object System.Drawing.Size(845, 175) $grpSelect.Font = New-Object System.Drawing.Font("Segoe UI", 9) $tabDeploy.Controls.Add($grpSelect) $lvDeploy = New-Object System.Windows.Forms.ListView $lvDeploy.Location = New-Object System.Drawing.Point(10, 18) $lvDeploy.Size = New-Object System.Drawing.Size(822, 148) $lvDeploy.View = [System.Windows.Forms.View]::Details $lvDeploy.CheckBoxes = $true $lvDeploy.FullRowSelect = $true $lvDeploy.GridLines = $true $lvDeploy.Font = New-Object System.Drawing.Font("Segoe UI", 9) $lvDeploy.Columns.Add("Add-on Name", 160) | Out-Null $lvDeploy.Columns.Add("Add-on ID", 210) | Out-Null $lvDeploy.Columns.Add("Interne URL (leer = AMO)", 420) | Out-Null foreach ($addon in $AllAddons) { $item = New-Object System.Windows.Forms.ListViewItem($addon.Name) $item.SubItems.Add($addon.Id) | Out-Null $item.SubItems.Add("") | Out-Null # Interne URL leer = AMO wird genutzt $item.Tag = $addon $lvDeploy.Items.Add($item) | Out-Null } # Doppelklick: interne URL bearbeiten $lvDeploy.Add_DoubleClick({ if ($lvDeploy.SelectedItems.Count -eq 0) { return } $sel = $lvDeploy.SelectedItems[0] $currentUrl = $sel.SubItems[2].Text $dlg = New-Object System.Windows.Forms.Form $dlg.Text = "Interne URL fuer: " + $sel.Text $dlg.Size = New-Object System.Drawing.Size(620, 130) $dlg.StartPosition = "CenterParent" $dlg.FormBorderStyle = "FixedDialog" $dlg.MaximizeBox = $false; $dlg.MinimizeBox = $false $lbl = New-Object System.Windows.Forms.Label $lbl.Text = "Interne HTTPS-URL zur XPI-Datei (leer lassen = addons.mozilla.org wird verwendet):" $lbl.Location = New-Object System.Drawing.Point(10, 10) $lbl.Size = New-Object System.Drawing.Size(590, 18) $lbl.Font = New-Object System.Drawing.Font("Segoe UI", 8) $dlg.Controls.Add($lbl) $txt = New-Object System.Windows.Forms.TextBox $txt.Location = New-Object System.Drawing.Point(10, 32) $txt.Size = New-Object System.Drawing.Size(590, 23) $txt.Font = New-Object System.Drawing.Font("Segoe UI", 9) $txt.Text = $currentUrl $dlg.Controls.Add($txt) $btnOk = New-Object System.Windows.Forms.Button $btnOk.Text = "OK"; $btnOk.Location = New-Object System.Drawing.Point(440, 62) $btnOk.Size = New-Object System.Drawing.Size(75, 26) $btnOk.DialogResult = "OK" $dlg.Controls.Add($btnOk); $dlg.AcceptButton = $btnOk $btnClear = New-Object System.Windows.Forms.Button $btnClear.Text = "Leeren"; $btnClear.Location = New-Object System.Drawing.Point(520, 62) $btnClear.Size = New-Object System.Drawing.Size(75, 26) $btnClear.Add_Click({ $txt.Text = ""; $dlg.DialogResult = "OK"; $dlg.Close() }) $dlg.Controls.Add($btnClear) if ($dlg.ShowDialog() -eq "OK") { $sel.SubItems[2].Text = $txt.Text.Trim() if ($txt.Text.Trim() -ne "") { $sel.ForeColor = [System.Drawing.Color]::DarkGreen } else { $sel.ForeColor = [System.Drawing.Color]::Black } } }) $grpSelect.Controls.Add($lvDeploy) # XPI herunterladen Button (nebeneinander mit Auswahl) $btnDownloadXpis = New-Object System.Windows.Forms.Button $btnDownloadXpis.Text = "XPIs herunterladen (fuer internes Hosting)" $btnDownloadXpis.Size = New-Object System.Drawing.Size(280, 30) $btnDownloadXpis.Location = New-Object System.Drawing.Point(10, 290) $btnDownloadXpis.BackColor = [System.Drawing.Color]::FromArgb(0, 120, 80) $btnDownloadXpis.ForeColor = [System.Drawing.Color]::White $btnDownloadXpis.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $btnDownloadXpis.FlatStyle = "Flat" $btnDownloadXpis.FlatAppearance.BorderSize = 0 $btnDownloadXpis.Add_Click({ $selected = $lvDeploy.Items | Where-Object { $_.Checked } if ($selected.Count -eq 0) { [System.Windows.Forms.MessageBox]::Show("Bitte mindestens ein Add-on auswaehlen.", "Hinweis", "OK", "Information") return } $fbd = New-Object System.Windows.Forms.FolderBrowserDialog $fbd.Description = "Zielordner fuer XPI-Dateien auswaehlen" if ($fbd.ShowDialog() -ne "OK") { return } $errors = @() foreach ($item in $selected) { $addon = $item.Tag $url = $addon.Url $fileName = $addon.Name -replace '[^\w]', '_' $dest = Join-Path $fbd.SelectedPath ($fileName + ".xpi") try { $wc = New-Object System.Net.WebClient $wc.DownloadFile($url, $dest) # Interne URL vorschlagen $item.SubItems[2].Text = "(XPI gespeichert: $dest - bitte interne URL eintragen)" $item.ForeColor = [System.Drawing.Color]::DarkBlue } catch { $errors += $addon.Name + ": " + $_ } } if ($errors.Count -gt 0) { [System.Windows.Forms.MessageBox]::Show( "Fehler beim Herunterladen:`n" + ($errors -join "`n"), "Fehler", "OK", "Error") } else { [System.Windows.Forms.MessageBox]::Show( "XPI-Dateien gespeichert in:`n" + $fbd.SelectedPath + "`n`nNaechste Schritte:`n" + "1. Dateien auf internen Webserver / SharePoint / Azure Blob hochladen`n" + "2. HTTPS-URL per Doppelklick in der Liste eintragen`n" + "3. Bereitstellung ausfuehren", "Download abgeschlossen", "OK", "Information") } }) $tabDeploy.Controls.Add($btnDownloadXpis) # Eigene Add-on ID hinzufuegen $grpCustom = New-Object System.Windows.Forms.GroupBox $grpCustom.Text = "Eigene Add-on ID hinzufuegen (z.B. aus eigenem Add-on)" $grpCustom.Location = New-Object System.Drawing.Point(10, 283) $grpCustom.Size = New-Object System.Drawing.Size(845, 72) $grpCustom.Font = New-Object System.Drawing.Font("Segoe UI", 9) $tabDeploy.Controls.Add($grpCustom) $lblCustomIdHint = New-Object System.Windows.Forms.Label $lblCustomIdHint.Text = "Add-on ID (z.B. myaddon@firma.de):" $lblCustomIdHint.Font = New-Object System.Drawing.Font("Segoe UI", 8) $lblCustomIdHint.ForeColor = [System.Drawing.Color]::Gray $lblCustomIdHint.Location = New-Object System.Drawing.Point(10, 8) $lblCustomIdHint.AutoSize = $true $grpCustom.Controls.Add($lblCustomIdHint) $txtCustomId = New-Object System.Windows.Forms.TextBox $txtCustomId.Location = New-Object System.Drawing.Point(10, 25) $txtCustomId.Size = New-Object System.Drawing.Size(380, 23) $txtCustomId.Font = New-Object System.Drawing.Font("Segoe UI", 9) $grpCustom.Controls.Add($txtCustomId) $lblCustomUrlHint = New-Object System.Windows.Forms.Label $lblCustomUrlHint.Text = "Download-URL der XPI (optional):" $lblCustomUrlHint.Font = New-Object System.Drawing.Font("Segoe UI", 8) $lblCustomUrlHint.ForeColor = [System.Drawing.Color]::Gray $lblCustomUrlHint.Location = New-Object System.Drawing.Point(400, 8) $lblCustomUrlHint.AutoSize = $true $grpCustom.Controls.Add($lblCustomUrlHint) $txtCustomUrl = New-Object System.Windows.Forms.TextBox $txtCustomUrl.Location = New-Object System.Drawing.Point(400, 25) $txtCustomUrl.Size = New-Object System.Drawing.Size(318, 23) $txtCustomUrl.Font = New-Object System.Drawing.Font("Segoe UI", 9) $grpCustom.Controls.Add($txtCustomUrl) $btnAddCustom = New-Object System.Windows.Forms.Button $btnAddCustom.Text = "+ Hinzufuegen" $btnAddCustom.Location = New-Object System.Drawing.Point(728, 34) $btnAddCustom.Size = New-Object System.Drawing.Size(108, 27) $btnAddCustom.Add_Click({ if ($txtCustomId.Text.Trim() -eq "") { [System.Windows.Forms.MessageBox]::Show("Bitte Add-on ID eingeben.", "Hinweis", "OK", "Information") return } $newItem = New-Object System.Windows.Forms.ListViewItem("[Eigene] " + $txtCustomId.Text.Trim()) $newItem.SubItems.Add("Eigenes Add-on") | Out-Null $newItem.SubItems.Add($txtCustomId.Text.Trim()) | Out-Null $customAddon = [PSCustomObject]@{ Name="[Eigene] " + $txtCustomId.Text.Trim() Id=$txtCustomId.Text.Trim() Url=$txtCustomUrl.Text.Trim() Beschreibung="Eigenes Add-on" } $newItem.Tag = $customAddon $newItem.Checked = $true $lvDeploy.Items.Add($newItem) | Out-Null $txtCustomId.Text = "" $txtCustomUrl.Text = "" }) $grpCustom.Controls.Add($btnAddCustom) # Bereitstellungs-Optionen $grpMethod = New-Object System.Windows.Forms.GroupBox $grpMethod.Text = "Bereitstellungs-Methode" $grpMethod.Location = New-Object System.Drawing.Point(10, 352) $grpMethod.Size = New-Object System.Drawing.Size(845, 70) $grpMethod.Font = New-Object System.Drawing.Font("Segoe UI", 9) $tabDeploy.Controls.Add($grpMethod) $rbPoliciesJson = New-Object System.Windows.Forms.RadioButton $rbPoliciesJson.Text = "policies.json (direkt in Firefox-Installationsordner - empfohlen)" $rbPoliciesJson.Location = New-Object System.Drawing.Point(10, 20) $rbPoliciesJson.AutoSize = $true $rbPoliciesJson.Checked = $true $rbPoliciesJson.Font = New-Object System.Drawing.Font("Segoe UI", 9) $grpMethod.Controls.Add($rbPoliciesJson) $rbRegistry = New-Object System.Windows.Forms.RadioButton $rbRegistry.Text = "Windows Registry (HKLM - GPO-kompatibel, fuer Gruppenrichtlinien-Umgebungen)" $rbRegistry.Location = New-Object System.Drawing.Point(10, 42) $rbRegistry.AutoSize = $true $rbRegistry.Font = New-Object System.Drawing.Font("Segoe UI", 9) $grpMethod.Controls.Add($rbRegistry) # Aktions-Buttons $btnDeploy = New-Object System.Windows.Forms.Button $btnDeploy.Text = "Jetzt bereitstellen (diese Maschine)" $btnDeploy.Size = New-Object System.Drawing.Size(260, 40) $btnDeploy.Location = New-Object System.Drawing.Point(10, 435) $btnDeploy.BackColor = [System.Drawing.Color]::FromArgb(255, 100, 20) $btnDeploy.ForeColor = [System.Drawing.Color]::White $btnDeploy.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold) $btnDeploy.FlatStyle = "Flat" $btnDeploy.FlatAppearance.BorderSize = 0 $btnDeploy.Add_Click({ $selected = $lvDeploy.Items | Where-Object { $_.Checked } if ($selected.Count -eq 0) { [System.Windows.Forms.MessageBox]::Show( "Bitte mindestens ein Add-on auswaehlen.", "Hinweis", "OK", "Information") return } if (-not (Test-IsAdmin)) { [System.Windows.Forms.MessageBox]::Show( "Maschinenweite Bereitstellung erfordert Administratorrechte.`n" + "Bitte das Skript als Administrator ausfuehren.", "Kein Administrator", "OK", "Warning") return } # Interne URL aus ListView-Spalte 2 uebernehmen (per Doppelklick eingetragen) $addonsToInstall = $selected | ForEach-Object { $clone = [PSCustomObject]@{ Name = $_.Tag.Name Id = $_.Tag.Id Url = $_.Tag.Url Beschreibung= $_.Tag.Beschreibung } $internalUrl = $_.SubItems[2].Text.Trim() if ($internalUrl -ne "" -and $internalUrl.StartsWith("http")) { $clone.Url = $internalUrl } $clone } if ($rbPoliciesJson.Checked) { # --- policies.json Methode --- $ffDir = Find-FirefoxInstallDir if (-not $ffDir) { [System.Windows.Forms.MessageBox]::Show( "Firefox-Installationsverzeichnis nicht gefunden.`n" + "Bitte Firefox installieren oder den Pfad pruefen.", "Fehler", "OK", "Error") return } $distributionDir = Join-Path $ffDir "distribution" if (-not (Test-Path $distributionDir)) { New-Item -ItemType Directory -Path $distributionDir | Out-Null } $policiesFile = Join-Path $distributionDir "policies.json" # Vorhandene policies.json einlesen oder neu erstellen if (Test-Path $policiesFile) { $existingJson = Get-Content $policiesFile -Raw | ConvertFrom-Json } else { $existingJson = [PSCustomObject]@{ policies = [PSCustomObject]@{} } } if (-not $existingJson.policies.PSObject.Properties["ExtensionSettings"]) { $existingJson.policies | Add-Member -NotePropertyName "ExtensionSettings" ` -NotePropertyValue ([PSCustomObject]@{}) -Force } foreach ($a in $addonsToInstall) { $setting = [PSCustomObject]@{ installation_mode = "force_installed" } if ($a.Url -and $a.Url.StartsWith("http")) { $setting | Add-Member -NotePropertyName "install_url" -NotePropertyValue $a.Url } $existingJson.policies.ExtensionSettings | Add-Member -NotePropertyName $a.Id -NotePropertyValue $setting -Force } $existingJson | ConvertTo-Json -Depth 10 | Set-Content $policiesFile -Encoding UTF8 [System.Windows.Forms.MessageBox]::Show( "policies.json erfolgreich geschrieben:`n$policiesFile`n`n" + "Die folgenden Add-ons werden beim naechsten Firefox-Start automatisch fuer alle Benutzer installiert:`n" + ($addonsToInstall | ForEach-Object { " - " + $_.Name } | Out-String), "Bereitstellung erfolgreich", "OK", "Information") } else { # --- Registry Methode (korrekte ExtensionSettings-Struktur) --- # Firefox liest: HKLM\SOFTWARE\Policies\Mozilla\Firefox\ExtensionSettings\ # Werte: installation_mode (REG_SZ) und install_url (REG_SZ) $regBase = "HKLM:\SOFTWARE\Policies\Mozilla\Firefox\ExtensionSettings" try { if (-not (Test-Path $regBase)) { New-Item -Path $regBase -Force | Out-Null } $written = @() foreach ($a in $addonsToInstall) { $addonKey = Join-Path $regBase $a.Id if (-not (Test-Path $addonKey)) { New-Item -Path $addonKey -Force | Out-Null } Set-ItemProperty -Path $addonKey -Name "installation_mode" ` -Value "force_installed" -Type String $url = if ($a.Url -and $a.Url.StartsWith("http")) { $a.Url } else { "https://addons.mozilla.org/firefox/downloads/latest/latest.xpi" } Set-ItemProperty -Path $addonKey -Name "install_url" -Value $url -Type String # Verifizieren $verify = Get-ItemProperty -Path $addonKey -ErrorAction SilentlyContinue if ($verify.installation_mode -eq "force_installed") { $written += $a.Name + " [OK] -> " + $addonKey } else { $written += $a.Name + " [FEHLER - Eintrag nicht verifiziert]" } } $summary = $written | Out-String [System.Windows.Forms.MessageBox]::Show( "Registry-Eintraege gesetzt unter:`n$regBase\`n`n" + "Ergebnis:`n" + $summary + "`nFirefox beim naechsten Start installiert die Add-ons automatisch fuer alle Benutzer.", "Bereitstellung erfolgreich", "OK", "Information") } catch { [System.Windows.Forms.MessageBox]::Show( "Registry-Fehler: $_`n`nBitte als Administrator ausfuehren.", "Fehler", "OK", "Error") } } }) $tabDeploy.Controls.Add($btnDeploy) $btnExportScript = New-Object System.Windows.Forms.Button $btnExportScript.Text = "Deployment-Skript exportieren" $btnExportScript.Size = New-Object System.Drawing.Size(240, 40) $btnExportScript.Location = New-Object System.Drawing.Point(280, 435) $btnExportScript.BackColor = [System.Drawing.Color]::FromArgb(70, 130, 180) $btnExportScript.ForeColor = [System.Drawing.Color]::White $btnExportScript.Font = New-Object System.Drawing.Font("Segoe UI", 10) $btnExportScript.FlatStyle = "Flat" $btnExportScript.FlatAppearance.BorderSize = 0 $btnExportScript.Add_Click({ $selected = $lvDeploy.Items | Where-Object { $_.Checked } if ($selected.Count -eq 0) { [System.Windows.Forms.MessageBox]::Show( "Bitte mindestens ein Add-on auswaehlen.", "Hinweis", "OK", "Information") return } $sfd = New-Object System.Windows.Forms.SaveFileDialog $sfd.Filter = "PowerShell-Skript (*.ps1)|*.ps1" $sfd.FileName = "Deploy-FirefoxAddons.ps1" if ($sfd.ShowDialog() -ne "OK") { return } $addonsToInstall = $selected | ForEach-Object { $clone = [PSCustomObject]@{ Name = $_.Tag.Name Id = $_.Tag.Id Url = $_.Tag.Url Beschreibung= $_.Tag.Beschreibung } $internalUrl = $_.SubItems[2].Text.Trim() if ($internalUrl -ne "" -and $internalUrl.StartsWith("http")) { $clone.Url = $internalUrl } $clone } $lines = @() $lines += "#Requires -RunAsAdministrator" $lines += "# Automatisch generiertes Firefox Add-on Deployment-Skript" $lines += "# Erstellt mit Firefox Add-on Manager" $lines += "" $lines += '$ffDir = "C:\Program Files\Mozilla Firefox"' $lines += '$distributionDir = Join-Path $ffDir "distribution"' $lines += 'if (-not (Test-Path $distributionDir)) { New-Item -ItemType Directory -Path $distributionDir | Out-Null }' $lines += '$policiesFile = Join-Path $distributionDir "policies.json"' $lines += "" if ($rbPoliciesJson.Checked) { $lines += "# policies.json erstellen" $lines += '$policies = @{' $lines += ' policies = @{' $lines += ' ExtensionSettings = @{' foreach ($a in $addonsToInstall) { $lines += ' "' + $a.Id + '" = @{' $lines += ' installation_mode = "force_installed"' if ($a.Url -and $a.Url.StartsWith("http")) { $lines += ' install_url = "' + $a.Url + '"' } $lines += ' }' } $lines += ' }' $lines += ' }' $lines += '}' $lines += '$policies | ConvertTo-Json -Depth 10 | Set-Content $policiesFile -Encoding UTF8' $lines += 'Write-Host "Deployment abgeschlossen. Firefox neu starten." -ForegroundColor Green' } else { $lines += "# Registry ExtensionSettings setzen" $lines += '# Firefox liest: HKLM\SOFTWARE\Policies\Mozilla\Firefox\ExtensionSettings\' $lines += '$regBase = "HKLM:\SOFTWARE\Policies\Mozilla\Firefox\ExtensionSettings"' $lines += 'if (-not (Test-Path $regBase)) { New-Item -Path $regBase -Force | Out-Null }' foreach ($a in $addonsToInstall) { $url = if ($a.Url -and $a.Url.StartsWith("http")) { $a.Url } else { "https://addons.mozilla.org/firefox/downloads/latest/latest.xpi" } $lines += "" $lines += "# " + $a.Name $lines += '$addonKey = "' + ('HKLM:\SOFTWARE\Policies\Mozilla\Firefox\ExtensionSettings\' + $a.Id) + '"' $lines += 'New-Item -Path $addonKey -Force | Out-Null' $lines += 'Set-ItemProperty -Path $addonKey -Name "installation_mode" -Value "force_installed" -Type String' $lines += 'Set-ItemProperty -Path $addonKey -Name "install_url" -Value "' + $url + '" -Type String' } $lines += "" $lines += 'Write-Host "Registry-Eintraege gesetzt. Firefox neu starten." -ForegroundColor Green' } $lines | Out-File -FilePath $sfd.FileName -Encoding UTF8 [System.Windows.Forms.MessageBox]::Show( "Skript exportiert:`n" + $sfd.FileName, "Export erfolgreich", "OK", "Information") }) $tabDeploy.Controls.Add($btnExportScript) $btnShowCurrent = New-Object System.Windows.Forms.Button $btnShowCurrent.Text = "Aktuelle policies.json anzeigen" $btnShowCurrent.Size = New-Object System.Drawing.Size(240, 40) $btnShowCurrent.Location = New-Object System.Drawing.Point(530, 435) $btnShowCurrent.BackColor = [System.Drawing.Color]::FromArgb(100, 100, 100) $btnShowCurrent.ForeColor = [System.Drawing.Color]::White $btnShowCurrent.Font = New-Object System.Drawing.Font("Segoe UI", 10) $btnShowCurrent.FlatStyle = "Flat" $btnShowCurrent.FlatAppearance.BorderSize = 0 $btnShowCurrent.Add_Click({ $ffDir = Find-FirefoxInstallDir if (-not $ffDir) { [System.Windows.Forms.MessageBox]::Show("Firefox-Installationsverzeichnis nicht gefunden.", "Hinweis", "OK", "Information") return } $pf = Join-Path $ffDir "distribution\policies.json" if (Test-Path $pf) { $content = Get-Content $pf -Raw $dlg = New-Object System.Windows.Forms.Form $dlg.Text = "policies.json - " + $pf $dlg.Size = New-Object System.Drawing.Size(700, 500) $dlg.StartPosition = "CenterParent" $tb = New-Object System.Windows.Forms.TextBox $tb.Multiline = $true; $tb.ScrollBars = "Both"; $tb.ReadOnly = $true $tb.Dock = "Fill"; $tb.Font = New-Object System.Drawing.Font("Consolas", 9) $tb.Text = $content $dlg.Controls.Add($tb) $dlg.ShowDialog() | Out-Null } else { [System.Windows.Forms.MessageBox]::Show( "Keine policies.json gefunden unter:`n" + (Join-Path $ffDir "distribution"), "Nicht gefunden", "OK", "Information") } }) $tabDeploy.Controls.Add($btnShowCurrent) # =========================================================== # TAB 2: Beliebte Add-ons (Benutzer-Store) # =========================================================== $tabPopular = New-Object System.Windows.Forms.TabPage $tabPopular.Text = "Store - Einzelinstallation" $tabs.Controls.Add($tabPopular) $lblPopInfo = New-Object System.Windows.Forms.Label $lblPopInfo.Text = "Add-on auswaehlen und per Firefox Store installieren (nur fuer aktuellen Benutzer)." $lblPopInfo.Font = New-Object System.Drawing.Font("Segoe UI", 9) $lblPopInfo.ForeColor = [System.Drawing.Color]::Gray $lblPopInfo.Location = New-Object System.Drawing.Point(10, 10) $lblPopInfo.AutoSize = $true $tabPopular.Controls.Add($lblPopInfo) $lvPopular = New-Object System.Windows.Forms.ListView $lvPopular.Location = New-Object System.Drawing.Point(10, 35) $lvPopular.Size = New-Object System.Drawing.Size(845, 390) $lvPopular.View = [System.Windows.Forms.View]::Details $lvPopular.FullRowSelect = $true $lvPopular.GridLines = $true $lvPopular.Font = New-Object System.Drawing.Font("Segoe UI", 9) $lvPopular.Columns.Add("Add-on Name", 200) | Out-Null $lvPopular.Columns.Add("Beschreibung", 450) | Out-Null $lvPopular.Columns.Add("Quelle", 160) | Out-Null foreach ($addon in $AllAddons) { $item = New-Object System.Windows.Forms.ListViewItem($addon.Name) $item.SubItems.Add($addon.Beschreibung) | Out-Null $item.SubItems.Add("Mozilla Store") | Out-Null $item.Tag = $addon $lvPopular.Items.Add($item) | Out-Null } $tabPopular.Controls.Add($lvPopular) $btnInstallPopular = New-Object System.Windows.Forms.Button $btnInstallPopular.Text = "Im Firefox Store oeffnen" $btnInstallPopular.Size = New-Object System.Drawing.Size(220, 35) $btnInstallPopular.Location = New-Object System.Drawing.Point(10, 440) $btnInstallPopular.BackColor = [System.Drawing.Color]::FromArgb(255, 100, 20) $btnInstallPopular.ForeColor = [System.Drawing.Color]::White $btnInstallPopular.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold) $btnInstallPopular.FlatStyle = "Flat" $btnInstallPopular.FlatAppearance.BorderSize = 0 $btnInstallPopular.Add_Click({ if ($lvPopular.SelectedItems.Count -eq 0) { [System.Windows.Forms.MessageBox]::Show("Bitte zuerst ein Add-on auswaehlen.", "Hinweis", "OK", "Information") return } $addon = $lvPopular.SelectedItems[0].Tag $url = if ($addon.StoreUrl) { $addon.StoreUrl } else { $addon.Url } Open-AddonPage -Url $url }) $tabPopular.Controls.Add($btnInstallPopular) $btnOpenAMO = New-Object System.Windows.Forms.Button $btnOpenAMO.Text = "Alle Add-ons durchsuchen" $btnOpenAMO.Size = New-Object System.Drawing.Size(220, 35) $btnOpenAMO.Location = New-Object System.Drawing.Point(240, 440) $btnOpenAMO.BackColor = [System.Drawing.Color]::FromArgb(70, 130, 180) $btnOpenAMO.ForeColor = [System.Drawing.Color]::White $btnOpenAMO.Font = New-Object System.Drawing.Font("Segoe UI", 10) $btnOpenAMO.FlatStyle = "Flat" $btnOpenAMO.FlatAppearance.BorderSize = 0 $btnOpenAMO.Add_Click({ Open-AddonPage -Url "https://addons.mozilla.org/de/firefox/" }) $tabPopular.Controls.Add($btnOpenAMO) # =========================================================== # TAB 3: XPI direkt installieren # =========================================================== $tabXpi = New-Object System.Windows.Forms.TabPage $tabXpi.Text = "XPI-Datei installieren" $tabs.Controls.Add($tabXpi) $lblXpiInfo = New-Object System.Windows.Forms.Label $lblXpiInfo.Text = "Installiere ein Add-on direkt aus einer lokalen .xpi-Datei in ein Firefox-Profil." $lblXpiInfo.Font = New-Object System.Drawing.Font("Segoe UI", 9) $lblXpiInfo.ForeColor = [System.Drawing.Color]::Gray $lblXpiInfo.Location = New-Object System.Drawing.Point(10, 10) $lblXpiInfo.AutoSize = $true $tabXpi.Controls.Add($lblXpiInfo) $lblXpiPath = New-Object System.Windows.Forms.Label $lblXpiPath.Text = "XPI-Datei:"; $lblXpiPath.Location = New-Object System.Drawing.Point(10, 50) $lblXpiPath.AutoSize = $true; $tabXpi.Controls.Add($lblXpiPath) $txtXpiPath = New-Object System.Windows.Forms.TextBox $txtXpiPath.Location = New-Object System.Drawing.Point(10, 70) $txtXpiPath.Size = New-Object System.Drawing.Size(650, 25) $txtXpiPath.Font = New-Object System.Drawing.Font("Segoe UI", 9) $tabXpi.Controls.Add($txtXpiPath) $btnBrowseXpi = New-Object System.Windows.Forms.Button $btnBrowseXpi.Text = "Durchsuchen..."; $btnBrowseXpi.Location = New-Object System.Drawing.Point(670, 68) $btnBrowseXpi.Size = New-Object System.Drawing.Size(160, 28) $btnBrowseXpi.Add_Click({ $ofd = New-Object System.Windows.Forms.OpenFileDialog $ofd.Filter = "Firefox Add-on (*.xpi)|*.xpi" if ($ofd.ShowDialog() -eq "OK") { $txtXpiPath.Text = $ofd.FileName } }) $tabXpi.Controls.Add($btnBrowseXpi) $lblProfile = New-Object System.Windows.Forms.Label $lblProfile.Text = "Firefox-Profil:"; $lblProfile.Location = New-Object System.Drawing.Point(10, 110) $lblProfile.AutoSize = $true; $tabXpi.Controls.Add($lblProfile) $txtProfile = New-Object System.Windows.Forms.TextBox $txtProfile.Location = New-Object System.Drawing.Point(10, 130) $txtProfile.Size = New-Object System.Drawing.Size(650, 25) $txtProfile.Font = New-Object System.Drawing.Font("Segoe UI", 9) $dp = Find-FirefoxProfile if ($dp) { $txtProfile.Text = $dp } $tabXpi.Controls.Add($txtProfile) $btnBrowseProfile = New-Object System.Windows.Forms.Button $btnBrowseProfile.Text = "Profil waehlen..."; $btnBrowseProfile.Location = New-Object System.Drawing.Point(670, 128) $btnBrowseProfile.Size = New-Object System.Drawing.Size(160, 28) $btnBrowseProfile.Add_Click({ $fbd = New-Object System.Windows.Forms.FolderBrowserDialog if ($fbd.ShowDialog() -eq "OK") { $txtProfile.Text = $fbd.SelectedPath } }) $tabXpi.Controls.Add($btnBrowseProfile) $btnInstallXpi = New-Object System.Windows.Forms.Button $btnInstallXpi.Text = "Add-on installieren" $btnInstallXpi.Size = New-Object System.Drawing.Size(200, 40) $btnInstallXpi.Location = New-Object System.Drawing.Point(10, 180) $btnInstallXpi.BackColor = [System.Drawing.Color]::FromArgb(255, 100, 20) $btnInstallXpi.ForeColor = [System.Drawing.Color]::White $btnInstallXpi.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold) $btnInstallXpi.FlatStyle = "Flat"; $btnInstallXpi.FlatAppearance.BorderSize = 0 $btnInstallXpi.Add_Click({ if (-not (Test-Path $txtXpiPath.Text)) { [System.Windows.Forms.MessageBox]::Show("XPI-Datei nicht gefunden.", "Fehler", "OK", "Error"); return } if (-not (Test-Path $txtProfile.Text)) { [System.Windows.Forms.MessageBox]::Show("Profilordner nicht gefunden.", "Fehler", "OK", "Error"); return } $ff = Get-Process -Name "firefox" -ErrorAction SilentlyContinue if ($ff) { $ans = [System.Windows.Forms.MessageBox]::Show( "Firefox ist geoeffnet. Jetzt beenden?", "Firefox beenden", "YesNo", "Warning") if ($ans -eq "Yes") { $ff | Stop-Process -Force; Start-Sleep 2 } else { return } } try { $id = Install-AddonFromFile -ProfilePath $txtProfile.Text -XpiPath $txtXpiPath.Text [System.Windows.Forms.MessageBox]::Show( "Installiert! ID: $id`nFirefox neu starten.", "Erfolg", "OK", "Information") $txtXpiPath.Text = "" } catch { [System.Windows.Forms.MessageBox]::Show("Fehler: $_", "Fehler", "OK", "Error") } }) $tabXpi.Controls.Add($btnInstallXpi) # =========================================================== # TAB 4: Installierte Add-ons # =========================================================== $tabInstalled = New-Object System.Windows.Forms.TabPage $tabInstalled.Text = "Installierte Add-ons" $tabs.Controls.Add($tabInstalled) $lvInstalled = New-Object System.Windows.Forms.ListView $lvInstalled.Location = New-Object System.Drawing.Point(10, 10) $lvInstalled.Size = New-Object System.Drawing.Size(845, 420) $lvInstalled.View = [System.Windows.Forms.View]::Details $lvInstalled.FullRowSelect = $true; $lvInstalled.GridLines = $true $lvInstalled.Font = New-Object System.Drawing.Font("Segoe UI", 9) $lvInstalled.Columns.Add("Name", 220) | Out-Null $lvInstalled.Columns.Add("Version", 80) | Out-Null $lvInstalled.Columns.Add("Aktiv", 60) | Out-Null $lvInstalled.Columns.Add("ID", 460) | Out-Null $tabInstalled.Controls.Add($lvInstalled) $btnRefresh = New-Object System.Windows.Forms.Button $btnRefresh.Text = "Aktualisieren"; $btnRefresh.Size = New-Object System.Drawing.Size(160, 35) $btnRefresh.Location = New-Object System.Drawing.Point(10, 445) $btnRefresh.BackColor = [System.Drawing.Color]::FromArgb(70, 130, 180) $btnRefresh.ForeColor = [System.Drawing.Color]::White $btnRefresh.Font = New-Object System.Drawing.Font("Segoe UI", 10) $btnRefresh.FlatStyle = "Flat"; $btnRefresh.FlatAppearance.BorderSize = 0 $btnRefresh.Add_Click({ $lvInstalled.Items.Clear() $profilePath = Find-FirefoxProfile if (-not $profilePath) { [System.Windows.Forms.MessageBox]::Show("Kein Firefox-Profil gefunden.", "Hinweis", "OK", "Information") return } $addons = Get-InstalledAddons -ProfilePath $profilePath foreach ($a in $addons) { $name = if ($a.defaultLocale.name) { $a.defaultLocale.name } else { $a.id } $item = New-Object System.Windows.Forms.ListViewItem($name) $item.SubItems.Add($a.version) | Out-Null $item.SubItems.Add($(if ($a.active) { "Ja" } else { "Nein" })) | Out-Null $item.SubItems.Add($a.id) | Out-Null if (-not $a.active) { $item.ForeColor = [System.Drawing.Color]::Gray } $lvInstalled.Items.Add($item) | Out-Null } if ($lvInstalled.Items.Count -eq 0) { $lvInstalled.Items.Add( (New-Object System.Windows.Forms.ListViewItem("Keine Add-ons gefunden."))) | Out-Null } }) $tabInstalled.Controls.Add($btnRefresh) # =========================================================== # TAB 5: Diagnose & Intune # =========================================================== $tabDiag = New-Object System.Windows.Forms.TabPage $tabDiag.Text = "Diagnose / Intune" $tabs.Controls.Add($tabDiag) # Intune-Warnung $pnlIntune = New-Object System.Windows.Forms.Panel $pnlIntune.Location = New-Object System.Drawing.Point(10, 8) $pnlIntune.Size = New-Object System.Drawing.Size(845, 28) $pnlIntune.BorderStyle = "FixedSingle" $tabDiag.Controls.Add($pnlIntune) $lblIntuneStatus = New-Object System.Windows.Forms.Label $lblIntuneStatus.Font = New-Object System.Drawing.Font("Segoe UI", 8, [System.Drawing.FontStyle]::Bold) $lblIntuneStatus.Location = New-Object System.Drawing.Point(6, 6) $lblIntuneStatus.Size = New-Object System.Drawing.Size(830, 18) if (Test-IntuneManaged) { $pnlIntune.BackColor = [System.Drawing.Color]::FromArgb(255, 240, 200) $lblIntuneStatus.Text = "INTUNE erkannt - Firefox wird via Intune verwaltet. policies.json wird ignoriert. Registry-Methode oder .reg-Export verwenden." $lblIntuneStatus.ForeColor = [System.Drawing.Color]::DarkOrange } else { $pnlIntune.BackColor = [System.Drawing.Color]::FromArgb(220, 255, 220) $lblIntuneStatus.Text = "Kein Intune-Management erkannt. policies.json und Registry-Methode sollten funktionieren." $lblIntuneStatus.ForeColor = [System.Drawing.Color]::DarkGreen } $pnlIntune.Controls.Add($lblIntuneStatus) # Policy-Konflikt-Checker $grpCheck = New-Object System.Windows.Forms.GroupBox $grpCheck.Text = "Policy-Konflikt-Pruefung - moegliche Gruende warum Add-ons nicht installiert werden" $grpCheck.Location = New-Object System.Drawing.Point(10, 44) $grpCheck.Size = New-Object System.Drawing.Size(845, 220) $grpCheck.Font = New-Object System.Drawing.Font("Segoe UI", 9) $tabDiag.Controls.Add($grpCheck) $lvChecks = New-Object System.Windows.Forms.ListView $lvChecks.Location = New-Object System.Drawing.Point(10, 18) $lvChecks.Size = New-Object System.Drawing.Size(822, 192) $lvChecks.View = [System.Windows.Forms.View]::Details $lvChecks.FullRowSelect = $true $lvChecks.GridLines = $true $lvChecks.Font = New-Object System.Drawing.Font("Segoe UI", 9) $lvChecks.Columns.Add("Status", 55) | Out-Null $lvChecks.Columns.Add("Policy / Einstellung", 240) | Out-Null $lvChecks.Columns.Add("Aktueller Wert", 200) | Out-Null $lvChecks.Columns.Add("Auswirkung / Loesung", 300) | Out-Null $grpCheck.Controls.Add($lvChecks) function Invoke-PolicyCheck { $lvChecks.Items.Clear() $base = "HKLM:\SOFTWARE\Policies\Mozilla\Firefox" # Hilfsfunktion: Eintrag hinzufuegen function Add-CheckItem { param([string]$Status, [string]$Policy, [string]$Value, [string]$Info, [string]$Color) $item = New-Object System.Windows.Forms.ListViewItem($Status) $item.SubItems.Add($Policy) | Out-Null $item.SubItems.Add($Value) | Out-Null $item.SubItems.Add($Info) | Out-Null switch ($Color) { "red" { $item.BackColor = [System.Drawing.Color]::FromArgb(255, 210, 210) } "yellow" { $item.BackColor = [System.Drawing.Color]::FromArgb(255, 245, 200) } "green" { $item.BackColor = [System.Drawing.Color]::FromArgb(210, 255, 210) } } $lvChecks.Items.Add($item) | Out-Null } # 1. BlockAboutAddons - sperrt about:addons komplett $val = (Get-ItemProperty "$base" -Name "BlockAboutAddons" -ErrorAction SilentlyContinue).BlockAboutAddons if ($val -eq 1) { Add-CheckItem "FEHLER" "BlockAboutAddons" "1 (aktiv)" "Sperrt Add-on-Manager komplett. Auf 0 setzen oder entfernen." "red" } else { Add-CheckItem "OK" "BlockAboutAddons" "(nicht gesetzt)" "Kein Problem." "green" } # 2. InstallAddonsPermission - steuert wer Add-ons installieren darf $allowKey = "$base\InstallAddonsPermission\Allow" $blockKey = "$base\InstallAddonsPermission\Block" $hasAllow = Test-Path $allowKey $hasBlock = Test-Path $blockKey if ($hasBlock) { $blockVals = (Get-ItemProperty $blockKey -ErrorAction SilentlyContinue).PSObject.Properties | Where-Object { $_.Name -notmatch '^PS' } | ForEach-Object { $_.Value } if ($blockVals -contains "" -or $blockVals -contains "*") { Add-CheckItem "FEHLER" "InstallAddonsPermission\Block" "" "Alle Installationen geblockt! Eintrag entfernen." "red" } else { Add-CheckItem "WARN" "InstallAddonsPermission\Block" ($blockVals -join ", ") "Bestimmte Quellen geblockt. Pruefen ob AMO/interne URL betroffen." "yellow" } } else { Add-CheckItem "OK" "InstallAddonsPermission" "(keine Block-Regel)" "Kein Problem." "green" } # 3. ExtensionSettings - ist force_installed korrekt gesetzt? $extKey = "$base\ExtensionSettings" if (Test-Path $extKey) { $subkeys = Get-ChildItem $extKey -ErrorAction SilentlyContinue if ($subkeys) { foreach ($sk in $subkeys) { $mode = (Get-ItemProperty $sk.PSPath -Name "installation_mode" -ErrorAction SilentlyContinue).installation_mode $url = (Get-ItemProperty $sk.PSPath -Name "install_url" -ErrorAction SilentlyContinue).install_url if ($mode -eq "force_installed") { if ($url) { Add-CheckItem "OK" ("ExtensionSettings\" + $sk.PSChildName) "force_installed" "install_url: $url" "green" } else { Add-CheckItem "WARN" ("ExtensionSettings\" + $sk.PSChildName) "force_installed" "Keine install_url - Firefox muss AMO erreichen koennen." "yellow" } } elseif ($mode -eq "blocked") { Add-CheckItem "FEHLER" ("ExtensionSettings\" + $sk.PSChildName) "blocked" "Dieses Add-on ist explizit geblockt!" "red" } elseif ($mode) { Add-CheckItem "WARN" ("ExtensionSettings\" + $sk.PSChildName) $mode "Modus ist nicht force_installed." "yellow" } } # Wildcard-Eintrag pruefen (blockiert alle nicht explizit erlaubten) $wildcard = Get-ItemProperty (Join-Path $extKey "*") -ErrorAction SilentlyContinue if ($wildcard) { $wMode = $wildcard.installation_mode if ($wMode -eq "blocked") { Add-CheckItem "FEHLER" 'ExtensionSettings\* (Wildcard)' "blocked" "Alle Add-ons ausser explizit force_installed sind geblockt. Kann force_installed verhindern wenn Reihenfolge falsch." "red" } elseif ($wMode) { Add-CheckItem "WARN" 'ExtensionSettings\* (Wildcard)' $wMode "Wildcard-Regel aktiv - pruefen ob sie force_installed ueberschreibt." "yellow" } } } else { Add-CheckItem "WARN" "ExtensionSettings" "(leer)" "Kein Add-on als force_installed eingetragen." "yellow" } } else { Add-CheckItem "WARN" "ExtensionSettings" "(nicht vorhanden)" "Noch keine Extension-Policy gesetzt." "yellow" } # 4. DisabledCiphers / WebsiteFilter die AMO blockieren koennten $proxyKey = Get-ItemProperty "$base\Proxy" -ErrorAction SilentlyContinue if ($proxyKey) { Add-CheckItem "INFO" "Proxy-Policy aktiv" ($proxyKey | Out-String).Trim().Split("`n")[0] "Proxy kann AMO-Download blockieren - interne URL empfohlen." "yellow" } # 5. AppAutoUpdate - verhindert nicht Installation, aber Info $upd = (Get-ItemProperty "$base" -Name "DisableAppUpdate" -ErrorAction SilentlyContinue).DisableAppUpdate if ($upd -eq 1) { Add-CheckItem "INFO" "DisableAppUpdate" "1 (aktiv)" "Kein Problem fuer Add-ons, aber Firefox-Updates deaktiviert." "yellow" } # 6. ExtensionUpdate deaktiviert? $extUpd = (Get-ItemProperty "$base" -Name "ExtensionUpdate" -ErrorAction SilentlyContinue).ExtensionUpdate if ($extUpd -eq 0) { Add-CheckItem "WARN" "ExtensionUpdate" "0 (deaktiviert)" "Add-on-Updates deaktiviert. Erstinstallation via force_installed funktioniert trotzdem." "yellow" } if ($lvChecks.Items.Count -eq 0) { Add-CheckItem "INFO" "(keine Policies gefunden)" "" "HKLM\SOFTWARE\Policies\Mozilla\Firefox existiert nicht." "yellow" } } $btnRunCheck = New-Object System.Windows.Forms.Button $btnRunCheck.Text = "Policy-Check ausfuehren" $btnRunCheck.Size = New-Object System.Drawing.Size(200, 30) $btnRunCheck.Location = New-Object System.Drawing.Point(10, 272) $btnRunCheck.BackColor = [System.Drawing.Color]::FromArgb(180, 0, 0) $btnRunCheck.ForeColor = [System.Drawing.Color]::White $btnRunCheck.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $btnRunCheck.FlatStyle = "Flat" $btnRunCheck.FlatAppearance.BorderSize = 0 $btnRunCheck.Add_Click({ Invoke-PolicyCheck }) $tabDiag.Controls.Add($btnRunCheck) $btnFixSelected = New-Object System.Windows.Forms.Button $btnFixSelected.Text = "Markierten FEHLER beheben" $btnFixSelected.Size = New-Object System.Drawing.Size(210, 30) $btnFixSelected.Location = New-Object System.Drawing.Point(220, 272) $btnFixSelected.BackColor = [System.Drawing.Color]::FromArgb(140, 0, 0) $btnFixSelected.ForeColor = [System.Drawing.Color]::White $btnFixSelected.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $btnFixSelected.FlatStyle = "Flat" $btnFixSelected.FlatAppearance.BorderSize = 0 $btnFixSelected.Add_Click({ if ($lvChecks.SelectedItems.Count -eq 0) { [System.Windows.Forms.MessageBox]::Show( "Bitte zuerst einen FEHLER-Eintrag in der Liste auswaehlen.", "Hinweis", "OK", "Information") return } if (-not (Test-IsAdmin)) { [System.Windows.Forms.MessageBox]::Show( "Administratorrechte erforderlich.", "Kein Admin", "OK", "Warning"); return } $sel = $lvChecks.SelectedItems[0] $status = $sel.SubItems[0].Text $policy = $sel.SubItems[1].Text $curVal = $sel.SubItems[2].Text $extBase = "HKLM:\SOFTWARE\Policies\Mozilla\Firefox\ExtensionSettings" # Fall 1: Explizit geblocktes Add-on (z.B. uBlock0@raymondhill.net -> blocked) if ($status -eq "FEHLER" -and $policy -match "^ExtensionSettings\\(.+)$" -and $Matches[1] -ne "*" -and $curVal -eq "blocked") { $addonId = $Matches[1] $addonKey = Join-Path $extBase $addonId $ans = [System.Windows.Forms.MessageBox]::Show( "Add-on '$addonId' ist explizit geblockt.`n`n" + "Was soll gemacht werden?`n" + "[Ja] Auf 'force_installed' aendern (Add-on wird zwingend installiert)`n" + "[Nein] Block-Eintrag komplett loeschen (Add-on wird nicht mehr explizit geblockt)", "Blocked-Eintrag beheben", "YesNo", "Question") if ($ans -eq "Yes") { if (-not (Test-Path $addonKey)) { New-Item -Path $addonKey -Force | Out-Null } Set-ItemProperty -Path $addonKey -Name "installation_mode" -Value "force_installed" -Type String # install_url setzen falls bekannt $known = $AllAddons | Where-Object { $_.Id -eq $addonId } if ($known -and $known.Url) { Set-ItemProperty -Path $addonKey -Name "install_url" -Value $known.Url -Type String [System.Windows.Forms.MessageBox]::Show( "Geaendert: '$addonId'`nModus: force_installed`nURL: $($known.Url)`n`nFirefox neu starten.", "Behoben", "OK", "Information") } else { [System.Windows.Forms.MessageBox]::Show( "Geaendert: '$addonId' -> force_installed`nHinweis: install_url nicht bekannt - bitte manuell eintragen oder AMO muss erreichbar sein.`n`nFirefox neu starten.", "Behoben", "OK", "Information") } } else { if (Test-Path $addonKey) { Remove-Item -Path $addonKey -Recurse -Force [System.Windows.Forms.MessageBox]::Show( "Block-Eintrag fuer '$addonId' geloescht.`n`nFirefox neu starten.", "Geloescht", "OK", "Information") } } } # Fall 2: Wildcard geblockt elseif ($status -eq "FEHLER" -and $policy -match "\*") { $wildcardKey = Join-Path $extBase "*" $ans = [System.Windows.Forms.MessageBox]::Show( "Wildcard (*) ist auf 'blocked' gesetzt.`n`n" + "[Ja] Wildcard-Eintrag loeschen (empfohlen wenn Intune force_installed nicht respektiert)`n" + "[Nein] Wildcard auf 'allowed' aendern (alle Add-ons erlaubt, weniger sicher)", "Wildcard beheben", "YesNo", "Question") if ($ans -eq "Yes") { if (Test-Path $wildcardKey) { Remove-Item -Path $wildcardKey -Recurse -Force } [System.Windows.Forms.MessageBox]::Show( "Wildcard-Eintrag geloescht.`nFirefox neu starten.", "Geloescht", "OK", "Information") } else { if (-not (Test-Path $wildcardKey)) { New-Item -Path $wildcardKey -Force | Out-Null } Set-ItemProperty -Path $wildcardKey -Name "installation_mode" -Value "allowed" -Type String [System.Windows.Forms.MessageBox]::Show( "Wildcard auf 'allowed' gesetzt.`nFirefox neu starten.", "Geaendert", "OK", "Information") } } else { [System.Windows.Forms.MessageBox]::Show( "Fuer diesen Eintrag ist keine automatische Korrektur verfuegbar.`nBitte manuell pruefen.", "Hinweis", "OK", "Information") } Invoke-PolicyCheck }) $tabDiag.Controls.Add($btnFixSelected) $btnFixWildcard = New-Object System.Windows.Forms.Button $btnFixWildcard.Text = "Alle FEHLERs beheben" $btnFixWildcard.Size = New-Object System.Drawing.Size(185, 30) $btnFixWildcard.Location = New-Object System.Drawing.Point(440, 272) $btnFixWildcard.BackColor = [System.Drawing.Color]::FromArgb(180, 80, 0) $btnFixWildcard.ForeColor = [System.Drawing.Color]::White $btnFixWildcard.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $btnFixWildcard.FlatStyle = "Flat" $btnFixWildcard.FlatAppearance.BorderSize = 0 $btnFixWildcard.Add_Click({ if (-not (Test-IsAdmin)) { [System.Windows.Forms.MessageBox]::Show( "Administratorrechte erforderlich.", "Kein Admin", "OK", "Warning"); return } $errors = $lvChecks.Items | Where-Object { $_.SubItems[0].Text -eq "FEHLER" } if ($errors.Count -eq 0) { [System.Windows.Forms.MessageBox]::Show("Keine FEHLER-Eintraege gefunden.", "Hinweis", "OK", "Information") return } $report = @() $extBase = "HKLM:\SOFTWARE\Policies\Mozilla\Firefox\ExtensionSettings" foreach ($err in $errors) { $policy = $err.SubItems[1].Text # Explizit geblocktes Add-on -> auf force_installed setzen if ($policy -match "^ExtensionSettings\\(.+)$" -and $Matches[1] -ne "*" -and $err.SubItems[2].Text -eq "blocked") { $addonId = $Matches[1] $addonKey = Join-Path $extBase $addonId if (-not (Test-Path $addonKey)) { New-Item -Path $addonKey -Force | Out-Null } Set-ItemProperty -Path $addonKey -Name "installation_mode" -Value "force_installed" -Type String $known = $AllAddons | Where-Object { $_.Id -eq $addonId } if ($known -and $known.Url) { Set-ItemProperty -Path $addonKey -Name "install_url" -Value $known.Url -Type String } $report += "force_installed gesetzt: $addonId" } # Wildcard -> loeschen elseif ($policy -match "\*") { $wildcardKey = Join-Path $extBase "*" if (Test-Path $wildcardKey) { Remove-Item -Path $wildcardKey -Recurse -Force } $report += "Wildcard (*) entfernt" } } [System.Windows.Forms.MessageBox]::Show( "Automatische Korrektur abgeschlossen:`n`n" + ($report -join "`n") + "`n`nFirefox neu starten.", "Alle Fehler behoben", "OK", "Information") Invoke-PolicyCheck }) $tabDiag.Controls.Add($btnFixWildcard) # Aktive Policies (Rohansicht) $grpPolicies = New-Object System.Windows.Forms.GroupBox $grpPolicies.Text = "Registry-Rohansicht (HKLM\SOFTWARE\Policies\Mozilla\Firefox)" $grpPolicies.Location = New-Object System.Drawing.Point(10, 310) $grpPolicies.Size = New-Object System.Drawing.Size(845, 120) $grpPolicies.Font = New-Object System.Drawing.Font("Segoe UI", 9) $tabDiag.Controls.Add($grpPolicies) $txtPolicies = New-Object System.Windows.Forms.TextBox $txtPolicies.Multiline = $true $txtPolicies.ScrollBars = "Both" $txtPolicies.ReadOnly = $true $txtPolicies.Location = New-Object System.Drawing.Point(10, 18) $txtPolicies.Size = New-Object System.Drawing.Size(822, 92) $txtPolicies.Font = New-Object System.Drawing.Font("Consolas", 8) $txtPolicies.WordWrap = $false $grpPolicies.Controls.Add($txtPolicies) # Buttons $btnOpenAboutPolicies = New-Object System.Windows.Forms.Button $btnOpenAboutPolicies.Text = "about:policies oeffnen" $btnOpenAboutPolicies.Size = New-Object System.Drawing.Size(190, 32) $btnOpenAboutPolicies.Location = New-Object System.Drawing.Point(10, 438) $btnOpenAboutPolicies.BackColor = [System.Drawing.Color]::FromArgb(255, 100, 20) $btnOpenAboutPolicies.ForeColor = [System.Drawing.Color]::White $btnOpenAboutPolicies.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $btnOpenAboutPolicies.FlatStyle = "Flat"; $btnOpenAboutPolicies.FlatAppearance.BorderSize = 0 $btnOpenAboutPolicies.Add_Click({ try { Start-Process "firefox" "about:policies" } catch { [System.Windows.Forms.MessageBox]::Show("Fehler: $_", "Fehler", "OK", "Error") } }) $tabDiag.Controls.Add($btnOpenAboutPolicies) $btnRefreshPolicies = New-Object System.Windows.Forms.Button $btnRefreshPolicies.Text = "Rohansicht laden" $btnRefreshPolicies.Size = New-Object System.Drawing.Size(160, 32) $btnRefreshPolicies.Location = New-Object System.Drawing.Point(210, 438) $btnRefreshPolicies.BackColor = [System.Drawing.Color]::FromArgb(70, 130, 180) $btnRefreshPolicies.ForeColor = [System.Drawing.Color]::White $btnRefreshPolicies.Font = New-Object System.Drawing.Font("Segoe UI", 9) $btnRefreshPolicies.FlatStyle = "Flat"; $btnRefreshPolicies.FlatAppearance.BorderSize = 0 $btnRefreshPolicies.Add_Click({ $lines = Get-ActiveFirefoxPolicies $txtPolicies.Text = if ($lines.Count -eq 0) { "(Keine Registry-Policies gefunden)" } else { $lines -join "`r`n" } }) $tabDiag.Controls.Add($btnRefreshPolicies) $btnExportReg = New-Object System.Windows.Forms.Button $btnExportReg.Text = ".reg fuer Intune exportieren" $btnExportReg.Size = New-Object System.Drawing.Size(210, 32) $btnExportReg.Location = New-Object System.Drawing.Point(380, 438) $btnExportReg.BackColor = [System.Drawing.Color]::FromArgb(0, 120, 80) $btnExportReg.ForeColor = [System.Drawing.Color]::White $btnExportReg.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $btnExportReg.FlatStyle = "Flat"; $btnExportReg.FlatAppearance.BorderSize = 0 $btnExportReg.Add_Click({ $selected = $lvDeploy.Items | Where-Object { $_.Checked } if ($selected.Count -eq 0) { [System.Windows.Forms.MessageBox]::Show( "Bitte zuerst im Tab 'Maschinenweite Bereitstellung' Add-ons auswaehlen.", "Hinweis", "OK", "Information"); return } $sfd = New-Object System.Windows.Forms.SaveFileDialog $sfd.Filter = "Registry-Datei (*.reg)|*.reg" $sfd.FileName = "Firefox-Addons-Intune.reg" if ($sfd.ShowDialog() -ne "OK") { return } $addonsToExport = $selected | ForEach-Object { $clone = [PSCustomObject]@{ Name=$_.Tag.Name; Id=$_.Tag.Id; Url=$_.Tag.Url; Beschreibung=$_.Tag.Beschreibung } $internalUrl = $_.SubItems[2].Text.Trim() if ($internalUrl -ne "" -and $internalUrl.StartsWith("http")) { $clone.Url = $internalUrl } $clone } Export-RegFile -OutputPath $sfd.FileName -Addons $addonsToExport [System.Windows.Forms.MessageBox]::Show( "Exportiert: $($sfd.FileName)`n`nIntune OMA-URI:`n./Device/Vendor/MSFT/Policy/Config/Firefox~Policy~mozilla_firefox~Extensions/ExtensionSettings`n`nAlternativ: .reg via Intune PowerShell-Skript importieren:`n reg import `"Firefox-Addons-Intune.reg`"", "Export erfolgreich", "OK", "Information") }) $tabDiag.Controls.Add($btnExportReg) $btnImportReg = New-Object System.Windows.Forms.Button $btnImportReg.Text = "REG-Datei einlesen & anwenden" $btnImportReg.Size = New-Object System.Drawing.Size(240, 32) $btnImportReg.Location = New-Object System.Drawing.Point(600, 438) $btnImportReg.BackColor = [System.Drawing.Color]::FromArgb(60, 90, 160) $btnImportReg.ForeColor = [System.Drawing.Color]::White $btnImportReg.Font = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Bold) $btnImportReg.FlatStyle = "Flat" $btnImportReg.FlatAppearance.BorderSize = 0 $btnImportReg.Add_Click({ if (-not (Test-IsAdmin)) { [System.Windows.Forms.MessageBox]::Show( "Administratorrechte erforderlich.", "Kein Admin", "OK", "Warning"); return } $ofd = New-Object System.Windows.Forms.OpenFileDialog $ofd.Filter = "Registry-Datei (*.reg)|*.reg" $ofd.Title = "REG-Datei fuer Intune-Policy auswaehlen" if ($ofd.ShowDialog() -ne "OK") { return } # REG-Datei parsen $lines = Get-Content $ofd.FileName -Encoding Unicode -ErrorAction SilentlyContinue if (-not $lines) { $lines = Get-Content $ofd.FileName -Encoding UTF8 -ErrorAction SilentlyContinue } if (-not $lines) { [System.Windows.Forms.MessageBox]::Show("Datei konnte nicht gelesen werden.", "Fehler", "OK", "Error") return } $currentKey = $null $applied = @() $skipped = @() $errors = @() foreach ($line in $lines) { $line = $line.Trim() if ($line -eq "" -or $line.StartsWith(";")) { continue } if ($line.StartsWith("Windows Registry Editor")) { continue } # Schluessel-Zeile: [HKEY_LOCAL_MACHINE\...] if ($line -match '^\[(.+)\]$') { $rawKey = $Matches[1] # Nur Firefox-Policy-Keys erlauben if ($rawKey -match 'SOFTWARE\\Policies\\Mozilla\\Firefox') { # HKEY_LOCAL_MACHINE -> HKLM: $psKey = $rawKey ` -replace '^HKEY_LOCAL_MACHINE', 'HKLM:' ` -replace '^HKEY_CURRENT_USER', 'HKCU:' $currentKey = $psKey } else { $currentKey = $null $skipped += "Uebersprungen (nicht Firefox-Policy): $rawKey" } continue } # Wert-Zeile nur verarbeiten wenn Key erlaubt if (-not $currentKey) { continue } # Wert parsen: "Name"="Wert" oder "Name"=dword:00000001 if ($line -match '^"(.+)"=(dword|hex|qword):(.+)$') { $name = $Matches[1] $type = $Matches[2] $value = $Matches[3] try { if (-not (Test-Path $currentKey)) { New-Item -Path $currentKey -Force | Out-Null } switch ($type) { "dword" { $int = [Convert]::ToInt32($value, 16) Set-ItemProperty -Path $currentKey -Name $name -Value $int -Type DWord } default { Set-ItemProperty -Path $currentKey -Name $name -Value $value -Type String } } $applied += "$currentKey -> $name = [$type] $value" } catch { $errors += "Fehler bei $currentKey -> $name : $_" } } elseif ($line -match '^"(.+)"="(.*)"$') { $name = $Matches[1] $value = $Matches[2] -replace '\\"', '"' try { if (-not (Test-Path $currentKey)) { New-Item -Path $currentKey -Force | Out-Null } Set-ItemProperty -Path $currentKey -Name $name -Value $value -Type String $applied += "$currentKey -> $name = $value" } catch { $errors += "Fehler bei $currentKey -> $name : $_" } } elseif ($line -match '^@="(.*)"$') { # Standard-Wert $value = $Matches[1] try { if (-not (Test-Path $currentKey)) { New-Item -Path $currentKey -Force | Out-Null } Set-ItemProperty -Path $currentKey -Name "(Default)" -Value $value -Type String $applied += "$currentKey -> (Default) = $value" } catch { $errors += "Fehler bei $currentKey -> Default : $_" } } elseif ($line -match '^"-(.+)"$') { # Wert loeschen $name = $Matches[1] try { Remove-ItemProperty -Path $currentKey -Name $name -ErrorAction SilentlyContinue $applied += "Geloescht: $currentKey -> $name" } catch { $errors += "Loeschen fehlgeschlagen: $currentKey -> $name" } } elseif ($line -match '^\[-(.+)\]$') { # Schluessel loeschen $delKey = $Matches[1] -replace '^HKEY_LOCAL_MACHINE', 'HKLM:' if (Test-Path $delKey) { Remove-Item -Path $delKey -Recurse -Force -ErrorAction SilentlyContinue $applied += "Schluessel geloescht: $delKey" } } } # Ergebnisbericht $dlg = New-Object System.Windows.Forms.Form $dlg.Text = "Import-Ergebnis: " + [System.IO.Path]::GetFileName($ofd.FileName) $dlg.Size = New-Object System.Drawing.Size(750, 500) $dlg.StartPosition = "CenterParent" $tbResult = New-Object System.Windows.Forms.TextBox $tbResult.Multiline = $true; $tbResult.ScrollBars = "Both" $tbResult.ReadOnly = $true; $tbResult.Dock = "Fill" $tbResult.Font = New-Object System.Drawing.Font("Consolas", 8) $tbResult.WordWrap = $false $summary = "" if ($applied.Count -gt 0) { $summary += "=== ANGEWENDET ($($applied.Count)) ===`r`n" $summary += ($applied -join "`r`n") + "`r`n`r`n" } if ($skipped.Count -gt 0) { $summary += "=== UEBERSPRUNGEN ($($skipped.Count)) ===`r`n" $summary += ($skipped -join "`r`n") + "`r`n`r`n" } if ($errors.Count -gt 0) { $summary += "=== FEHLER ($($errors.Count)) ===`r`n" $summary += ($errors -join "`r`n") + "`r`n`r`n" } $summary += "`r`nFirefox neu starten damit die Aenderungen wirksam werden." $tbResult.Text = $summary $dlg.Controls.Add($tbResult) $dlg.ShowDialog() | Out-Null Invoke-PolicyCheck $btnRefreshPolicies.PerformClick() }) $tabDiag.Controls.Add($btnImportReg) $lblOmaUri = New-Object System.Windows.Forms.Label $lblOmaUri.Text = "OMA-URI: ./Device/Vendor/MSFT/Policy/Config/Firefox~Policy~mozilla_firefox~Extensions/ExtensionSettings" $lblOmaUri.Font = New-Object System.Drawing.Font("Consolas", 7) $lblOmaUri.ForeColor = [System.Drawing.Color]::DarkBlue $lblOmaUri.Location = New-Object System.Drawing.Point(10, 478) $lblOmaUri.Size = New-Object System.Drawing.Size(845, 14) $tabDiag.Controls.Add($lblOmaUri) # Statusleiste $statusBar = New-Object System.Windows.Forms.StatusStrip $statusLabel = New-Object System.Windows.Forms.ToolStripStatusLabel $statusLabel2 = New-Object System.Windows.Forms.ToolStripStatusLabel $statusLabel3 = New-Object System.Windows.Forms.ToolStripStatusLabel $ffInstallDir = Find-FirefoxInstallDir if ($ffInstallDir) { $statusLabel.Text = "Firefox: $ffInstallDir" } else { $statusLabel.Text = "Firefox-Installation nicht gefunden" $statusLabel.ForeColor = [System.Drawing.Color]::Red } $statusLabel2.Text = " | " + $(if (Test-IsAdmin) { "Admin: Ja" } else { "Admin: Nein" }) $statusLabel3.Text = " | " + $(if (Test-IntuneManaged) { "Intune: erkannt" } else { "Intune: nicht erkannt" }) $statusBar.Items.Add($statusLabel) | Out-Null $statusBar.Items.Add($statusLabel2) | Out-Null $statusBar.Items.Add($statusLabel3) | Out-Null $form.Controls.Add($statusBar) $tabs.add_SelectedIndexChanged({ if ($tabs.SelectedIndex -eq 3) { $btnRefresh.PerformClick() } if ($tabs.SelectedIndex -eq 4) { Invoke-PolicyCheck $btnRefreshPolicies.PerformClick() } }) [void]$form.ShowDialog()