Classes/RegeditManager.ps1
|
class RegeditManager { [LibraryContext]$Context [string]$DefaultKey RegeditManager([LibraryContext]$context) { $this.Context = $context $this.DefaultKey = "SOFTWARE\Kittl-Partner\Intune\$($context.Meta['InstanceName'])" } # Simple setter [void] SetRegeditKey([string]$path, [string]$keyName, [object]$value) { $this.Context.LogManager.Log("Setting '$path\$keyName' = '$value'") $views = @( [Microsoft.Win32.RegistryView]::Registry64 #[Microsoft.Win32.RegistryView]::Registry32 #=> ignore 32bit regedit! ) foreach ($view in $views) { try { $this.Context.LogManager.Log("Processing '$path' in $view") # Split the root and subkey (e.g., HKLM:\Software\MyApp) $parts = $path -split ":", 2 $hiveName = $parts[0] $subKey = $parts[1].TrimStart('\') # Map root key string to RegistryHive enum $hive = $null switch -Regex ($hiveName) { '^HKLM' { $hive = [Microsoft.Win32.RegistryHive]::LocalMachine } '^HKCU' { $hive = [Microsoft.Win32.RegistryHive]::CurrentUser } '^HKCR' { $hive = [Microsoft.Win32.RegistryHive]::ClassesRoot } '^HKU' { $hive = [Microsoft.Win32.RegistryHive]::Users } '^HKCC' { $hive = [Microsoft.Win32.RegistryHive]::CurrentConfig } default { throw "Unknown registry hive: $hiveName" } } # Open or create key in the correct registry view $baseKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey($hive, $view) $regKey = $baseKey.CreateSubKey($subKey, $true) if ($null -ne $keyName -and '' -ne $keyName) { if ($regKey.GetValueNames() -contains $keyName) { # Get the existing type $kind = $regKey.GetValueKind($keyName) Write-Host "'$path\$keyName' already exists and has type $kind" } else { $kind, $value = $this.GetValueKindAndCoercedValue($value) } $regKey.SetValue($keyName, $value, $kind) $this.Context.LogManager.Log("Set '$path\$keyName' = '$value' [${kind}] in $view") } else { $this.Context.LogManager.Log("Empty key name => No setting empty default for '$path' in $view") $regKey.SetValue('', '', [Microsoft.Win32.RegistryValueKind]::String) } $regKey.Close() $baseKey.Close() } catch { $this.Context.LogManager.Log("Error processing '$path' in ${view}: $_", "ERROR") } } } # Write Intune Flag [void] WriteIntuneFlag([string]$KeyPath, [hashtable]$Data, [bool]$AddLastRun) { if (-not $KeyPath) { $KeyPath = $this.DefaultKey } if (-not $Data) { throw "Data hashtable cannot be null or empty." } if ($this.Context.Meta.RunContext -eq "User") { $hiveStr = "HKEY_CURRENT_USER" } else { $hiveStr = "HKEY_LOCAL_MACHINE" } $this.Context.LogManager.Log("Writing intune regedit entries to $hiveStr\$KeyPath") $views = @( 'Registry64' #'Registry32' #=> ignore 32bit regedit! ) foreach ($view in $views) { $base = $null $rk = $null try { if ($this.Context.Meta.RunContext -eq "User") { $hive = [Microsoft.Win32.RegistryHive]::CurrentUser } else { $hive = [Microsoft.Win32.RegistryHive]::LocalMachine } $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey($hive, [Microsoft.Win32.RegistryView]::$view) $rk = $base.CreateSubKey($KeyPath) foreach ($name in $Data.Keys) { $value = $Data[$name] if ($null -eq $value) { # Treat $null as "remove this value" to avoid writing invalid data try { $rk.DeleteValue($name, $true) } catch {} continue } $kind, $out = $this.GetValueKindAndCoercedValue($value) $this.Context.LogManager.Log("-> Setting ${name} = ${out} [${kind}] in ${view}") $rk.SetValue($name, $out, $kind) } if ($AddLastRun) { $rk.SetValue('LastRun', (Get-Date).ToString('s'), [Microsoft.Win32.RegistryValueKind]::String) } } finally { if ($rk) { $rk.Close() } if ($base) { $base.Close() } } } $this.Context.LogManager.Log("Wrote intune regedit entries to $hiveStr\$KeyPath") } # Private helper (can be placed in the class as a hidden method or outside as a local function) hidden [object[]] GetValueKindAndCoercedValue([object] $Value) { if ($Value -is [int] -or $Value -is [int32]) { return ([object[]]@([Microsoft.Win32.RegistryValueKind]::DWord, [int]$Value)) } elseif ($Value -is [long] -or $Value -is [int64]) { return ([object[]]@([Microsoft.Win32.RegistryValueKind]::QWord, [long]$Value)) } elseif ($Value -is [byte[]]) { return ([object[]]@([Microsoft.Win32.RegistryValueKind]::Binary, [byte[]]$Value)) } elseif ($Value -is [string[]]) { return ([object[]]@([Microsoft.Win32.RegistryValueKind]::MultiString, [string[]]$Value)) } elseif ($Value -is [bool]) { return ([object[]]@([Microsoft.Win32.RegistryValueKind]::DWord, [int]([bool]$Value))) } elseif ($Value -is [datetime]) { return ([object[]]@([Microsoft.Win32.RegistryValueKind]::String, ($Value).ToString('s'))) } elseif ($Value -is [System.Collections.IEnumerable] -and -not ($Value -is [string])) { $tmp = foreach ($i in $Value) { [string]$i } if ($null -eq $tmp) { $tmp = @() } $asStrings = [string[]]$tmp # <<< wichtiger Cast return ([object[]]@([Microsoft.Win32.RegistryValueKind]::MultiString, $asStrings)) } else { return ([object[]]@([Microsoft.Win32.RegistryValueKind]::String, $Value.ToString())) } } # Remove Intune Flag (entire key) [void] RemoveIntuneFlag([string]$KeyPath) { if (-not $KeyPath) { $KeyPath = $this.DefaultKey } # Normalize to a subkey path relative to HKLM (no HKLM:\ prefix) etc. if ($this.Context.Meta.RunContext -eq "User") { $hiveStr = "HKEY_CURRENT_USER" $normalized = $KeyPath -replace '^(?i:HKCU:\\|HKEY_CURRENT_USER\\)', '' } else { $hiveStr = "HKEY_LOCAL_MACHINE" $normalized = $KeyPath -replace '^(?i:HKLM:\\|HKEY_LOCAL_MACHINE\\)', '' } $views = @( 'Registry64' #'Registry32' #=> ignore 32bit regedit! ) foreach ($view in $views) { $base = $null try { if ($this.Context.Meta.RunContext -eq "User") { $hive = [Microsoft.Win32.RegistryHive]::CurrentUser } else { $hive = [Microsoft.Win32.RegistryHive]::LocalMachine } $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey($hive, [Microsoft.Win32.RegistryView]::$view) # Check if it exists first (purely for clearer logging) $existing = $base.OpenSubKey($normalized) if ($existing) { $existing.Close() } if ($existing) { # Delete entire key tree; do not throw if it vanished between check and delete $base.DeleteSubKeyTree($normalized, $false) # Sanity check $post = $base.OpenSubKey($normalized) if ($post) { $post.Close() $this.Context.LogManager.Log("'$hiveStr\$normalized' still present after delete in $view.", "ERROR") } else { $this.Context.LogManager.Log("Deleted registry key '$hiveStr\$normalized' in $view.") } } else { $this.Context.LogManager.Log("Key '$hiveStr\$normalized' not found in $view; nothing to delete.", "ERROR") } } finally { if ($base) { $base.Close() } } } $this.Context.LogManager.Log("Processed deletion for intune regedit '$hiveStr\$normalized' in both views.") } } |