260 lines
8.8 KiB
PowerShell
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','.')
|