Files
SAMY/docs/samy.functions.md

8.8 KiB

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

[System.Diagnostics.EventLog]::LogNameFromSourceName('SVMSP_Module','.')