Skip to content

Commit 85b3f51

Browse files
committed
fix: v1.0.7 — -Global scope fix, Get-ImportedModuleCommand rewrite, docs refresh
- Import-PersonalModules: added -Global to Import-Module so submodules load into the session scope instead of UserAdminModule's private scope - Get-ImportedModuleCommand: fixed \ scope (now resolved via Get-Module UserAdminModule); reads config.json directly instead of calling private Get-UserAdminModuleConfig; fixed -Submodule filter operator precedence bug; excluded UserAdminModule root from submodule detection - docs: custom just-the-docs colour scheme matching HTML app palette - docs: -UseSharedProfile documented in reference.md and getting-started.md - docs: stable install command (removed -AllowPrerelease) - docs: Set-DisplayIsAdmin -> Set-TitleisAdmin in README - docs: corrected New-PSM1Module syntax in getting-functions.md - psd1: version bumped to 1.0.7, all v1.0.3-1.0.6 release notes restored
1 parent 8b19327 commit 85b3f51

10 files changed

Lines changed: 258 additions & 39 deletions

File tree

‎Public/Import-PersonalModules.ps1‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ function Import-PersonalModules {
161161
if ($PSCmdlet.ShouldProcess($modulePath, 'Import-Module')) {
162162
$start = Get-Date
163163
Write-Verbose "Importing '$($cat)' from: $($modulePath)"
164-
Import-Module -Name $modulePath -Force -DisableNameChecking -ErrorAction SilentlyContinue
164+
Import-Module -Name $modulePath -Force -DisableNameChecking -Global
165165
$duration = (Get-Date) - $start
166166
$timingResults += [PSCustomObject]@{
167167
Category = $cat

‎README.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ No hardcoded category lists. No `.psd1` maintenance per function. Works on any m
7373
### From PowerShell Gallery (Recommended)
7474

7575
```powershell
76-
# Install the module (current release is a preview)
77-
Install-Module UserAdminModule -AllowPrerelease -Scope CurrentUser
76+
# Install the module
77+
Install-Module UserAdminModule -Scope CurrentUser
7878
7979
# Option A — Minimal setup (Import-Module only)
8080
Initialize-UserAdminModule -Path 'C:\MyModules' -UpdateProfile
@@ -200,7 +200,7 @@ The bundled **Shell** submodule adds 16 UX functions including:
200200
| Function | Description |
201201
|---|---|
202202
| `Set-PromptisAdmin` | Colours the prompt red/green based on admin status |
203-
| `Set-DisplayIsAdmin` | Sets the console window title with username, privilege level, and current path |
203+
| `Set-TitleisAdmin` | Sets the console window title with username, privilege level, and current path |
204204
| `Show-IsAdminOrNot` | Writes whether the current session is running as administrator |
205205
| `Set-ConsoleConfig` | Sets console window and buffer dimensions |
206206
| `Get-ConsoleConfig` | Retrieves the current console window and buffer sizes |

‎Shell/Public/Get-ImportedModuleCommand.ps1‎

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,34 @@ function Get-ImportedModuleCommand {
109109

110110
Write-Verbose 'Retrieving loaded UserAdminModule submodules'
111111

112-
# Discover UserAdminModule root and custom modules path
113-
if (-not $Script:UAMModuleRoot) {
114-
Write-Verbose '[DIAG] $Script:UAMModuleRoot was not set. Initializing from $PSScriptRoot.'
115-
$Script:UAMModuleRoot = Split-Path $PSScriptRoot -Parent
112+
# Discover UserAdminModule root.
113+
# $Script:UAMModuleRoot is set by UserAdminModule.psm1 but lives in that module's
114+
# scope — not visible here in Shell's scope. Use (Get-Module UserAdminModule).ModuleBase
115+
# as the authoritative source; fall back to two levels up from $PSScriptRoot
116+
# (Shell\Public -> Shell -> module root) only if the module is not loaded.
117+
$_uamRoot = (Get-Module UserAdminModule -ErrorAction SilentlyContinue |
118+
Select-Object -First 1).ModuleBase
119+
if (-not $_uamRoot) {
120+
Write-Verbose 'UserAdminModule module not loaded in session — falling back to PSScriptRoot parent chain.'
121+
$_uamRoot = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent
116122
}
117-
$_uamRoot = $Script:UAMModuleRoot
118-
$cfg = if (Get-Command Get-UserAdminModuleConfig -ErrorAction SilentlyContinue) {
119-
Get-UserAdminModuleConfig -ErrorAction SilentlyContinue
123+
Write-Verbose "UAMModuleRoot: $_uamRoot"
124+
125+
# Read CustomModulesPath directly from config.json.
126+
# Get-UserAdminModuleConfig is private to UserAdminModule's module scope and is
127+
# not reachable from Shell — read the JSON directly here.
128+
$customPath = $null
129+
$configPath = Join-Path $env:APPDATA 'UserAdminModule\config.json'
130+
if (Test-Path $configPath) {
131+
trap { Write-Verbose "Could not read config.json: $_"; continue }
132+
$cfgRaw = Get-Content $configPath -Raw -ErrorAction SilentlyContinue
133+
if ($cfgRaw) {
134+
$cfgObj = $cfgRaw | ConvertFrom-Json -ErrorAction SilentlyContinue
135+
if ($cfgObj -and $cfgObj.CustomModulesPath -and (Test-Path $cfgObj.CustomModulesPath)) {
136+
$customPath = $cfgObj.CustomModulesPath
137+
}
138+
}
120139
}
121-
$customPath = if ($cfg -and $cfg.CustomModulesPath -and (Test-Path $cfg.CustomModulesPath)) { $cfg.CustomModulesPath } else { $null }
122140

123141
function Normalize-Path([string]$path) {
124142
if (-not $path) { return $null }
@@ -127,33 +145,26 @@ function Get-ImportedModuleCommand {
127145
$_uamRoot = Normalize-Path $_uamRoot
128146
$customPath = Normalize-Path $customPath
129147

130-
Write-Verbose "[DIAG] UAMModuleRoot: $_uamRoot"
131-
Write-Verbose "[DIAG] CustomModulesPath: $customPath"
148+
Write-Verbose "CustomModulesPath: $($customPath ?? '(none)')"
132149

133150
function Test-IsUAMSubmodule($mod) {
134151
if (-not $mod.ModuleBase -or -not $mod.Name) { return $false }
135152
$psm1 = Join-Path $mod.ModuleBase ("$($mod.Name).psm1")
136153
$modBase = Normalize-Path $mod.ModuleBase
137154
$hasPsm1 = Test-Path $psm1
138-
$inUAMRoot = ($null -ne $_uamRoot -and $modBase.StartsWith($_uamRoot, [System.StringComparison]::OrdinalIgnoreCase))
155+
# Must be a child directory of UAMRoot or CustomPath — not the root itself
156+
$inUAMRoot = ($null -ne $_uamRoot -and
157+
$modBase.StartsWith($_uamRoot, [System.StringComparison]::OrdinalIgnoreCase) -and
158+
$modBase -ne $_uamRoot)
139159
$inCustomPath = ($null -ne $customPath -and $modBase.StartsWith($customPath, [System.StringComparison]::OrdinalIgnoreCase))
140-
if ($mod.Name -eq 'CustomShellCommands') {
141-
Write-Verbose "[DIAG] --- Checking CustomShellCommands ---"
142-
Write-Verbose "[DIAG] ModuleBase: $modBase"
143-
Write-Verbose "[DIAG] .psm1 exists: $hasPsm1"
144-
Write-Verbose "[DIAG] In UAMRoot: $inUAMRoot"
145-
Write-Verbose "[DIAG] In CustomPath: $inCustomPath"
146-
}
147160
if (-not $hasPsm1) { return $false }
148161
return ($inUAMRoot -or $inCustomPath)
149162
}
150163

151164
$loadedModules = Get-Module |
152165
Where-Object {
153-
if ($_.Name -eq 'CustomShellCommands') {
154-
Write-Verbose "[DIAG] Found loaded module: $($_.Name) at $($_.ModuleBase)"
155-
}
156-
Test-IsUAMSubmodule $_ -and $_.Name -like $Submodule
166+
# Wrap in () so -and is a boolean operator, not an argument to Test-IsUAMSubmodule
167+
(Test-IsUAMSubmodule $_) -and ($_.Name -like $Submodule)
157168
}
158169
}
159170

‎UserAdminModule.psd1‎

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@{
22
RootModule = 'UserAdminModule.psm1'
3-
ModuleVersion = '1.0.2'
3+
ModuleVersion = '1.0.7'
44
GUID = 'c080b18e-78ca-453a-8f6b-6a86c9390267'
55
Author = 'Luke Leigh'
66
CompanyName = 'Banter Studio'
@@ -43,6 +43,54 @@ Quick start:
4343
ProjectUri = 'https://useradminmodule.lukeleigh.com/'
4444
LicenseUri = 'https://github.com/BanterBoy/UserAdminModule/blob/main/LICENSE'
4545
ReleaseNotes = @'
46+
v1.0.7 — Fix submodule scope (Import-PersonalModules -Global)
47+
- Root cause of all "Import-PersonalModules imports nothing" reports: Import-Module
48+
was called without -Global, so submodules were loaded into UserAdminModule's private
49+
scope instead of the session scope — Get-Command -Module Weather returned nothing
50+
- Fix: added -Global to Import-Module in Import-PersonalModules
51+
- Removed -ErrorAction SilentlyContinue so errors from #requires failures (e.g.
52+
ADFunctions needing ActiveDirectory RSAT) surface through the trap handler instead
53+
of being silently swallowed
54+
- This fix supersedes the incorrectly documented v1.0.3/v1.0.4 entries below —
55+
-Global was described in those release notes but was never actually committed
56+
v1.0.6 — Fix -UseSharedProfile profile write (root cause: Add-Content silent failure)
57+
- Root cause of v1.0.5 bug: (Get-Module UserAdminModule).ModuleBase returned an
58+
array when two module instances were loaded, producing a concatenated path string
59+
- Root cause of profile write failure: Add-Content silently swallowed errors then
60+
set ProfileUpdated=True regardless — profile was empty after the run
61+
- Fix 1: resolve shared profile path via $Script:UAMModuleRoot (set in psm1 at
62+
load time — always a single string, immune to multi-instance loading)
63+
- Fix 2: store resolved path in config.json as SharedProfilePath
64+
- Fix 3: profile block reads config.json at session startup (no PSModulePath needed)
65+
- Fix 4: replaced Add-Content with [System.IO.File]::WriteAllText + explicit
66+
read-back verification. If verification fails, backup is restored and a Warning
67+
is emitted instead of silently returning ProfileUpdated=True
68+
- Tested end-to-end in a real admin session — profile correctly written and verified
69+
v1.0.5 — Add -UseSharedProfile to Initialize-UserAdminModule
70+
- New -UseSharedProfile switch: when combined with -UpdateProfile, writes a
71+
dot-source line for the bundled shared profile instead of a bare Import-Module
72+
line. Auto-detects $PSEdition: Desktop (PS 5.1) → SharedWindowsPowershellProfile.ps1;
73+
Core (PS 7+) → SharedPowershellProfile.ps1
74+
- Duplicate-detection now covers both the Import-Module pattern and the
75+
SharedPowershellProfile/SharedWindowsPowershellProfile dot-source pattern so
76+
re-running the command is idempotent
77+
- End block nudge: informs users who used -UpdateProfile alone about -UseSharedProfile
78+
- docs/getting-started.md: new 'Profile options' section explaining Option A vs B
79+
- docs/reference.md: -UseSharedProfile added to Initialize-UserAdminModule table
80+
- README.md: quick-start updated with Option A / Option B examples
81+
v1.0.4 — Fix submodule import and command detection (PSGallery regression, re-release)
82+
- 1.0.3 published with incomplete fixes; this supersedes it
83+
- Get-ImportedModuleCommand: rewrote submodule detection using dynamic directory
84+
scan (same logic as Import-PersonalModules). Eliminates the broken
85+
path-comparison approach that caused Normalize-Path and Test-IsUAMSubmodule
86+
to leak into Shell exports and Shell/UserAdminModule to appear as submodules
87+
- Get-ImportedModuleCommand: replaced Get-Help synopsis lookup with AST-based
88+
help extraction to avoid terminating type-resolution errors on functions that
89+
use typed AD parameters ([ADComputer] etc.) when AD module is not loaded
90+
- Get-ImportedModuleCommand: deduplicate results when same module is loaded from
91+
multiple paths (e.g. PSGallery and local dev copy both in session)
92+
v1.0.3 — Fix submodule command detection (PSGallery regression)
93+
- Get-ImportedModuleCommand: rewrote submodule detection using dynamic directory scan
4694
v1.0.2 — Minor fixes and improvements
4795
- New-PSM1Module: added -Force parameter to overwrite existing module folders
4896
- New-PSM1Module: improved error handling for invalid folder paths

‎docs/_config.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ baseurl: ""
77
url: "https://useradminmodule.lukeleigh.com"
88

99
remote_theme: just-the-docs/just-the-docs@v0.10.0
10-
color_scheme: dark
10+
color_scheme: uam
1111

1212
nav_sort: order
1313
search_enabled: true

‎docs/_sass/color_schemes/uam.scss‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// UAM — custom just-the-docs colour scheme
2+
// Mirrors the visual identity of resources/ModuleMenuApp.html
3+
// Built on top of the upstream dark scheme.
4+
5+
@import "./color_schemes/dark";
6+
7+
// ── HTML app CSS variable equivalents ──────────────────────────────────────
8+
// --bg-deep: #0d1117 main page background
9+
// --bg-panel: #161b22 sidebar / header / search bar
10+
// --bg-card: #1c2128 code blocks, tables
11+
// --accent: #58a6ff links, headings, active items
12+
// --accent2: #3fb950 section sub-headings (used in custom.scss)
13+
// --accent3: #d2a8ff inline code tint
14+
// --text: #e6edf3 body text
15+
// --text-muted: #8b949e muted / nav child links
16+
// --border: #30363d borders
17+
18+
// ── Backgrounds ────────────────────────────────────────────────────────────
19+
$body-background-color: #0d1117; // --bg-deep
20+
$sidebar-color: #161b22; // --bg-panel
21+
$feedback-color: #1c2128; // --bg-card (search results / hover)
22+
$code-background-color: #1c2128; // --bg-card
23+
$table-background-color: #161b22; // --bg-panel
24+
$search-background-color: #161b22; // --bg-panel
25+
26+
// ── Text ───────────────────────────────────────────────────────────────────
27+
$body-text-color: #e6edf3; // --text
28+
$body-heading-color: #58a6ff; // --accent (h1–h6 default)
29+
$nav-child-link-color: #8b949e; // --text-muted
30+
$search-result-preview-color: #8b949e; // --text-muted
31+
$code-linenumber-color: #8b949e; // --text-muted
32+
33+
// ── Accent / interactive ────────────────────────────────────────────────────
34+
$link-color: #58a6ff; // --accent
35+
$btn-primary-color: #1f3a5f; // --bg-active (primary button fill)
36+
$base-button-color: #1c2128; // --bg-card (default button fill)
37+
38+
// ── Borders ────────────────────────────────────────────────────────────────
39+
$border-color: #30363d; // --border

‎docs/_sass/custom/custom.scss‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// UAM custom CSS overrides
2+
// Additional visual polish to match resources/ModuleMenuApp.html
3+
4+
// ── Monospace font: match HTML app (Cascadia Code → Consolas fallback) ──────
5+
code, pre, .highlight {
6+
font-family: "Cascadia Code", "Cascadia Mono", Consolas, "SFMono-Regular", monospace !important;
7+
}
8+
9+
// ── Inline code tint: --accent3 (#d2a8ff) ───────────────────────────────────
10+
code:not(.highlight code) {
11+
color: #d2a8ff;
12+
background-color: #1c2128;
13+
border: 1px solid #30363d;
14+
border-radius: 4px;
15+
}
16+
17+
// ── Section headings h2: accent2 green underline, matching HTML .section-title
18+
h2 {
19+
color: #3fb950;
20+
padding-bottom: 0.35em;
21+
border-bottom: 1px solid #30363d;
22+
}
23+
24+
// h3: keep accent blue but slightly smaller
25+
h3 {
26+
color: #58a6ff;
27+
}
28+
29+
// ── Nav sidebar: tighter item height, hover state matches --bg-hover ─────────
30+
.nav-list .nav-list-item .nav-list-link:hover {
31+
background-color: #222d3a;
32+
color: #e6edf3;
33+
}
34+
35+
.nav-list .nav-list-item .nav-list-link.active {
36+
background-color: #1f3a5f;
37+
color: #58a6ff;
38+
border-left: 3px solid #58a6ff;
39+
}
40+
41+
// ── Search input: match HTML app search bar styling ─────────────────────────
42+
.search-input {
43+
background-color: #1c2128;
44+
border: 1px solid #30363d;
45+
color: #e6edf3;
46+
border-radius: 8px;
47+
48+
&:focus {
49+
border-color: #58a6ff;
50+
outline: none;
51+
}
52+
}
53+
54+
// ── Tables: card background + muted header row ───────────────────────────────
55+
table {
56+
border: 1px solid #30363d;
57+
58+
thead {
59+
background-color: #1c2128;
60+
color: #8b949e;
61+
font-size: 0.75rem;
62+
text-transform: uppercase;
63+
letter-spacing: 0.05em;
64+
}
65+
66+
tbody tr:nth-child(odd) {
67+
background-color: #161b22;
68+
}
69+
70+
tbody tr:nth-child(even) {
71+
background-color: #0d1117;
72+
}
73+
74+
td, th {
75+
border-color: #30363d;
76+
}
77+
}
78+
79+
// ── Code blocks: card background, border, radius matching HTML .example-block
80+
.highlight, pre.highlight {
81+
background-color: #1c2128;
82+
border: 1px solid #30363d;
83+
border-radius: 8px;
84+
}
85+
86+
// ── Callout / label colours matching HTML accents ───────────────────────────
87+
.label-blue { background-color: #1f3a5f; color: #58a6ff; }
88+
.label-green { background-color: #1a3a27; color: #3fb950; }
89+
.label-purple { background-color: #2d1f4a; color: #d2a8ff; }
90+
91+
// ── Site header (top bar): match --bg-panel ──────────────────────────────────
92+
.site-header {
93+
background-color: #161b22;
94+
border-bottom: 1px solid #30363d;
95+
}
96+
97+
// ── Footer ───────────────────────────────────────────────────────────────────
98+
.site-footer {
99+
background-color: #161b22;
100+
border-top: 1px solid #30363d;
101+
color: #8b949e;
102+
font-size: 0.8rem;
103+
}

‎docs/getting-functions.md‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,19 @@ Export-ModuleMember -Function $Public.BaseName
7272
UserAdminModule includes `New-PSM1Module` to scaffold a new category folder with the correct structure:
7373

7474
```powershell
75-
New-PSM1Module -Name ADFunctions -Path 'C:\MyModules'
75+
New-PSM1Module -folderPath 'C:\MyModules\ADFunctions'
7676
```
7777

7878
This creates:
7979

8080
```
8181
C:\MyModules\ADFunctions\
8282
├── ADFunctions.psm1
83-
└── Public\
84-
└── .gitkeep
83+
├── Public\
84+
├── Private\
85+
├── Classes\
86+
├── Configuration\
87+
└── Resources\
8588
```
8689

8790
Drop your function `.ps1` files into `Public\` and you're ready to import.

‎docs/getting-started.md‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ description: "Install and configure UserAdminModule in five minutes."
2727
## Install from PSGallery
2828

2929
```powershell
30-
Install-Module UserAdminModule -AllowPrerelease -Scope CurrentUser
30+
Install-Module UserAdminModule -Scope CurrentUser
3131
```
3232

3333
{: .note }
@@ -37,13 +37,23 @@ Install-Module UserAdminModule -AllowPrerelease -Scope CurrentUser
3737

3838
## First-time setup
3939

40-
Run `Initialize-UserAdminModule` once, pointing it at the root of your function library. Pass `-UpdateProfile` to have it add the import line to your `$PROFILE` automatically.
40+
Run `Initialize-UserAdminModule` once, pointing it at the root of your function library.
41+
42+
**Option A — minimal setup** (adds `Import-Module UserAdminModule` to your `$PROFILE`):
4143

4244
```powershell
4345
Initialize-UserAdminModule -Path 'C:\MyModules' -UpdateProfile
4446
```
4547

46-
This writes a `config.json` to `$env:APPDATA\UserAdminModule\` so every UserAdminModule command knows where to find your functions. You only need to run this once per machine.
48+
**Option B — full shell UX** (admin-coloured prompt, greeting, PSReadLine history — recommended):
49+
50+
```powershell
51+
Initialize-UserAdminModule -Path 'C:\MyModules' -UpdateProfile -UseSharedProfile
52+
```
53+
54+
`-UseSharedProfile` automatically picks the right bundled profile for your PowerShell edition: `SharedPowershellProfile.ps1` for PS 7+ or `SharedWindowsPowershellProfile.ps1` for PS 5.1.
55+
56+
Both options write `config.json` to `$env:APPDATA\UserAdminModule\` and make a `.bak` backup of your existing `$PROFILE` first. You only need to run this once per machine.
4757

4858
{: .tip }
4959
> If you already have functions in a folder like `C:\Scripts\AdminFunctions`, point `-Path` there. No restructuring needed yet — see [Bring Your Own Functions]({{ site.baseurl }}/your-functions) for how to make existing libraries compatible.

0 commit comments

Comments
 (0)