Files
SAMY/docs/# samy.functions.ps1

260 lines
8.8 KiB
PowerShell

# samy.functions.ps1 (3-in-1)
This file groups three core categories of functionality used by SAMY:
1. **Bootstrap**: prepares PowerShell package tooling (NuGet provider, PowerShellGet, PackageManagement, PSGallery).
2. **Registry Helpers**: reusable functions to write registry values for current user, default user (future profiles), and existing user profiles.
3. **UI Handlers**: endpoint/task handlers invoked by the web UI (e.g., install 1Password, apply tweaks).
The goal of this file is to provide daily driver functions SAMY needs across onboarding/offboarding workflows.
> Encoding rule: save as **UTF-8 without BOM**.
---
## Contents overview
- Bootstrap
- `Initialize-NuGetProvider`
- Registry helpers
- `Set-RegistryValueInHkuRoot`
- `Set-RegistryValueForCurrentAndAllUsers`
- `Restart-ExplorerIfInteractive`
- UI Handlers (examples included in file)
- `Invoke-Install1Password`
- `Invoke-DisableAnimations`
- `Invoke-EnableNumLock`
- `Invoke-ClassicContextMenu`
---
## Bootstrap
### Initialize-NuGetProvider
**Purpose**
Ensures SAMY can install/update PowerShell modules and providers without interactive prompts (critical for unattended runs and `iwr | iex` style execution).
**Key behaviors**
- Forces TLS 1.2 for network operations.
- Silences progress + confirmation prompts to keep runs unattended.
- Ensures provider folder paths exist:
- Current user provider assemblies path
- All users provider assemblies path (may fail without admin; handled)
- Ensures the **NuGet package provider** is installed at a minimum version.
- Imports NuGet provider after install.
- Imports/updates:
- `PackageManagement`
- `PowerShellGet`
- Optionally marks `PSGallery` as trusted to prevent prompts.
**Why it matters**
Many PowerShell module installs trigger interactive prompts, especially on fresh machines. This function makes module installation reliable for SAMY's automation.
**Common failure modes**
- No internet / proxy blocks PSGallery or NuGet endpoints.
- Running under restricted execution policy or locked-down environment.
- Running without elevation when trying to write to system-wide locations (handled as “warning” for folder creation).
**Logging**
Uses `Write-LogHybrid` with `-LogToEvent` to record bootstrap state and failures.
**Modification notes**
- If you need stricter behavior: choose whether to `throw` in the final catch block (PackageManagement/PowerShellGet setup).
- If you need TLS 1.3+: be careful, many older environments still require TLS 1.2 compatibility.
---
## Registry Helpers
### Set-RegistryValueInHkuRoot
**Purpose**
Writes a registry value relative to a given `HKEY_USERS` hive root.
**Parameters**
- `HkuRoot`: registry root path (e.g. `Registry::HKEY_USERS\S-1-5-21-...`)
- `RelativeKeyPath`: relative key path under the root
- `Name`: value name
- `Type`: value type (String, DWord, etc.)
- `Value`: value data
**Behavior**
- Ensures the key exists.
- Uses `New-ItemProperty` with `-Force` so it can create or overwrite.
**When to use**
When you already have the target user hive loaded and you want a consistent writer.
---
### Set-RegistryValueForCurrentAndAllUsers
**Purpose**
Applies the same registry setting to:
1. **Current user** (HKCU) if meaningful/available
2. **Default user profile hive** (`C:\Users\Default\NTUSER.DAT`) so future users inherit the setting
3. **All existing user profiles** by enumerating ProfileList and mounting each `NTUSER.DAT` as needed
**High-level flow**
1. Try write to HKCU (best-effort; may be skipped under SYSTEM).
2. Default User:
- Loads `C:\Users\Default\NTUSER.DAT` into `HKEY_USERS\SVS_DefaultUser` (if not already loaded)
- Writes the setting
- Unloads the hive (only if this function loaded it)
3. Existing profiles:
- Enumerates `HKLM:\...\ProfileList`
- Identifies user SIDs (`S-1-5-21-...`)
- If hive already loaded under `HKEY_USERS\<SID>`, writes directly
- Otherwise mounts `NTUSER.DAT` to a temporary key, writes, then unloads
**Why it matters**
Many Windows customizations are stored per-user. To make onboarding consistent, SAMY must update:
- the active user (if running interactively)
- the default profile (future logins)
- every existing profile on the machine (shared devices, re-used devices)
**Important safety notes**
- Loading/unloading hives is sensitive:
- A loaded hive can't always be unloaded if something else is holding a handle.
- The function tracks whether it loaded the hive (`$didLoad`) to avoid unloading someone else's mount.
- Profile iteration excludes non-standard SIDs by regex filter.
- Some profiles may not have `NTUSER.DAT` (system profiles, corrupt profiles, etc.). Those are skipped safely.
**Logging**
Uses `Write-LogHybrid` to record default hive load/unload outcomes and per-setting success.
**Modification notes**
- If you add more settings, prefer calling this helper rather than duplicating hive logic.
- If you need to write to HKLM machine-wide instead, do that outside this helper.
- If you ever see “unload failed”, it's usually because something still holds a handle to the loaded hive.
---
### Restart-ExplorerIfInteractive
**Purpose**
Restarts Explorer to apply UI-related registry changes (taskbar, context menu, shell tweaks).
**Behavior**
- Skips restart when running as `SYSTEM` to avoid breaking non-interactive phases.
- Stops `explorer.exe` and restarts it.
**Modification notes**
- If this ever runs during OOBE/Autopilot contexts, you may want stronger checks than `$env:USERNAME -ne 'SYSTEM'`.
---
## UI Handlers
These functions are designed to be invoked by the SAMY web UI through task routing.
Each handler:
- parses optional JSON POST body (e.g., selected options)
- executes the requested action
- logs results via `Write-LogHybrid`
- returns a response to the UI via `Send-Text`
### Invoke-Install1Password
**Purpose**
Installs 1Password desktop app and optionally forces browser extension install for Chrome and/or Edge.
**Inputs**
- Defaults to installing the desktop app if no UI selection is provided.
- If POST JSON contains `checkedValues`, uses that list.
**Actions**
- Desktop app via `winget` (`AgileBits.1Password`)
- Chrome extension by setting policy:
- `HKLM:\SOFTWARE\Policies\Google\Chrome\ExtensionInstallForcelist`
- Edge extension by setting policy:
- `HKLM:\SOFTWARE\Policies\Microsoft\Edge\ExtensionInstallForcelist`
**Notes**
- Forcelist policy requires admin to write HKLM policies.
- Browser extension IDs must remain correct; update if vendor changes.
---
### Invoke-DisableAnimations
**Purpose**
Applies UI reduced motion style tweaks by writing registry values across all users.
**Default selection**
If no options are provided, defaults to enabling all:
- `window`, `taskbar`, `menus`
**Settings applied**
- Window animation: `MinAnimate`
- Taskbar animations: `TaskbarAnimations`
- Menu delay: `MenuShowDelay`
**Post-action**
- Restarts Explorer if taskbar changes were applied.
---
### Invoke-EnableNumLock
**Purpose**
Turns NumLock on by default (affects logon screen + default profile behavior).
**Where it writes**
- `Registry::HKEY_USERS\.DEFAULT\Control Panel\Keyboard`
- `InitialKeyboardIndicators = "2"` (string)
**Notes**
- Uses `.DEFAULT` so it impacts the logon screen and baseline behavior.
- This does not guarantee every vendor keyboard/BIOS setting, but covers the Windows side.
---
### Invoke-ClassicContextMenu
**Purpose**
Enables Windows 11 classic right-click context menu behavior.
**Where it writes**
- `HKCU:\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32`
- Default value set to blank
**Post-action**
- Restarts Explorer to apply immediately.
**Notes**
- This is per-user (HKCU). If you want it for all users, use the registry helpers to apply across profiles.
---
## Logging expectations
All functions log via `Write-LogHybrid` using categories like:
- `Bootstrap`
- `Tweaks`
- `SVSApps`
- `UI`
When `-LogToEvent` is enabled, events are also written to the configured Windows Event Log (e.g., `SVSMSP Events`) using the project's Event Log binding logic.
---
## Common maintenance tasks
### Add a new UI handler
1. Create `Invoke-<TaskName>` function.
2. Parse POST JSON if needed (`checkedValues` pattern).
3. Use `Write-LogHybrid` for logging.
4. Use `Send-Text` for responses.
5. Ensure the router maps a route/task name to this handler.
### Add a new per-user tweak
- Prefer using `Set-RegistryValueForCurrentAndAllUsers` to apply it to:
- current user (HKCU)
- Default User hive
- existing profiles
### Debug “it works the second time” issues
That often means initialization happens after first use (especially Event Logs and provider bootstrap).
Ensure bootstrap/init happens before first call site that depends on it.
---
## Quick troubleshooting commands
### Check Event Log source binding
```powershell
[System.Diagnostics.EventLog]::LogNameFromSourceName('SVMSP_Module','.')