Skip to content

test(rules): the in-box module table is held against the Windows client the tests run on - #21

Merged
fadwen merged 2 commits into
feat/repair-mechanical-fixesfrom
test/inbox-modules-against-host
Oct 6, 2026
Merged

fadwen merged 2 commits into
feat/repair-mechanical-fixesfrom
test/inbox-modules-against-host

Conversation

@fadwen

@fadwen fadwen commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

Summary

Get-IslInboxModule, the list IslModuleDependency reports from, was captured as SYSTEM on the lab device and never checked afterwards: a misspelt name, or a module Windows drops, would have made the rule wrong without a test noticing, as the PowerShell 7-only tables were before #12 gave them one. This adds the equivalent test for the module table, and re-captures the table on the device.

Stacked on #20 (base branch); the diff is this change only. Merge #16 through #20, then this.

What was measured

  • VM 125 as SYSTEM, 2026-10-06, Windows 11 Enterprise LTSC 24H2 (build 26100), x64: Get-Module -ListAvailable under the two system module paths gives the same 90 modules the table lists (the 91st, Microsoft.PowerShell.Core, is the engine module and has no folder). The table is unchanged.
  • A Windows 11 Home ARM64 24H2 host: 84 of the 90, without AppLocker, AppvClient, AssignedAccess, BranchCache, ConfigCI, iSCSI and UEV (Pro and Enterprise features), and with HostNetworkingService besides, which the Enterprise x64 device does not have.
  • Import-Module Microsoft.PowerShell.Core by name fails on Windows PowerShell 5.1 and PowerShell 7.6 alike ("no valid module file was found"), although every session has its commands. The help says so now; what the rule should say about a script that imports it is an open question, since "not in-box" would be the wrong message.

Changes

  • Tests/Unit/Private/Get-IslInboxModule.Tests.ps1 (new). Asks the host's powershell.exe as a child process for the modules under System32\WindowsPowerShell\v1.0\Modules and Program Files\WindowsPowerShell\Modules, the paths a SYSTEM session reads (REM-PSMODULEPATH). Every listed module must be there, except the engine module and the seven Home lacks; the engine module's commands must be present without a folder; nothing may be under the Windows module folder, System32\WindowsPowerShell\v1.0\Modules, that the table does not name or the test does not account for. The Program Files folder is left out of that last check: a GitHub runner has fifty installed modules there, Graph, AWS, SQL and the rest, and so may any managed device; it is where software and the Gallery's AllUsers scope install to. Hyper-V, HgsClient, HgsDiagnostics, HostComputeService and HostNetworkingService are allowed as features a host may have turned on; the ARM64 runner has the first four. Runs on a Windows client (ProductType 1), skipped on a server, whose set differs; the ARM64 CI runner is a Windows 11 client and runs it.
  • Private/Get-IslInboxModule.ps1. Help records the re-capture, the engine module's import failure and the Home and ARM64 differences. The list is unchanged.
  • Findings and changelog. The re-capture and the Home ARM64 figures under the module path row.

Verification

  • The new test passes on PowerShell 7.6.6 and Windows PowerShell 5.1 on a Windows 11 Home ARM64 host (4 of 4 each), where the Home and ARM64 allowances are what make it pass. Unit and integration suites pass on PowerShell 7.6.6. PSScriptAnalyzer (Error and Warning) is clean; no line over 115 characters.
  • VM 125 was started for the capture and shut down afterwards.

Notes

  • A new module in a Windows release, or a feature module on a CI host, fails the third assertion by design: the decision is then whether it belongs in the table (a plain device has it) or in the test's FeatureModules list (a feature of that host). The first dispatched CI run did exactly that for the ARM64 runner, which is how the Program Files exclusion and the four Hyper-V family entries got here.

@fadwen fadwen left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notes on the lines whose reason the diff does not show.

# Listed, and rightly, but not a folder Get-Module -ListAvailable finds: the engine's own module
$script:EngineModule = 'Microsoft.PowerShell.Core'
# Pro and Enterprise features a Home edition does not ship (Windows 11 Home 24H2, ARM64)
$script:EditionOnly = 'AppLocker', 'AppvClient', 'AssignedAccess', 'BranchCache', 'ConfigCI', 'iSCSI', 'UEV'

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Measured on a Windows 11 Home ARM64 24H2 host against the Enterprise x64 device: these seven are the whole difference in that direction. A Home host in CI would otherwise fail the first assertion for features it never had.

$script:EditionOnly = 'AppLocker', 'AppvClient', 'AssignedAccess', 'BranchCache', 'ConfigCI', 'iSCSI', 'UEV'
# Present on a Windows 11 Home ARM64 24H2 host and absent from the Enterprise x64 device the
# table was captured on; neither is a plain device every script can count on
$script:SeenElsewhere = 'HostNetworkingService'

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept out of the table rather than added: the Enterprise x64 device, re-captured on 2026-10-06, does not have it, so a script cannot count on it. Whether it is an ARM64 or a Home artefact was not established.

$system | Where-Object { $module.ModuleBase.StartsWith($_, 'OrdinalIgnoreCase') }
} | Select-Object -ExpandProperty Name -Unique | Sort-Object -Unique
# The engine module has no folder and Import-Module of it fails; its commands are there
$engine = (Get-Command -Name Get-Command).ModuleName

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get-Module -Name Microsoft.PowerShell.Core returns nothing on either host and Import-Module of it fails, so the engine module is proved by the module a core command reports. The first draft asked Get-Module and failed on both hosts.

if (Get-Command powershell.exe -ErrorAction SilentlyContinue) {
# ProductType 1 is a workstation; the table describes a client, and a server's set differs
$os = Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction SilentlyContinue
$script:ClientHost = [int]$os.ProductType -eq 1

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

windows-latest in CI is Windows Server, whose in-box set has server modules and lacks client ones; the table describes a client, so the host assertions run on windows-11-arm and on a developer's machine, not there.

…nt the tests run on

Get-IslInboxModule is a hand-written list captured as SYSTEM on the lab
device, and nothing checked it afterwards: a misspelt name, or a module
Windows drops, would have made IslModuleDependency wrong without a test
noticing, the way the PowerShell 7-only tables were before they got a
test of their own.

The new test asks the host's Windows PowerShell, as a child process, for
the modules under the two system module paths a SYSTEM session reads
(REM-PSMODULEPATH). Every listed module must be there, except the engine
module, which has no folder, and the seven a Home edition does not ship;
and nothing may be there that the table or the test does not account
for. The test runs on a Windows client (ProductType 1) and is skipped on
a server, whose set differs.

Measured for this change: the table re-captured as SYSTEM on VM 125 on
2026-10-06 (Windows 11 Enterprise LTSC 24H2, build 26100) is the same
90 modules. A Windows 11 Home ARM64 24H2 host has 84 of them, lacking
AppLocker, AppvClient, AssignedAccess, BranchCache, ConfigCI, iSCSI and
UEV, and has HostNetworkingService besides. Import-Module of
Microsoft.PowerShell.Core by name fails on both hosts although its
commands are there; the help says so. The table is unchanged.
…ows folder only

A GitHub runner has fifty installed modules under Program Files\WindowsPowerShell\Modules, Graph, AWS, SQL and the rest, and so may any managed device; that folder is where software and the Gallery's AllUsers scope install to, and says nothing about the table. The completeness assertion reads System32\WindowsPowerShell\v1.0\Modules alone, with Hyper-V and the container and host-guardian family allowed as features a host may have turned on (the ARM64 runner has them). The existence assertion still reads both folders, where PackageManagement, PowerShellGet and Pester live.

@fadwen fadwen left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notes on the second commit, after the first dispatched CI run.

# Windows features that put a module under System32 when they are turned on: Hyper-V and the
# container and host-guardian family. HostNetworkingService is there on a Windows 11 Home ARM64
# host without the feature. None is on a plain device, so none is in the table
$script:FeatureModules = 'Hyper-V', 'HgsClient', 'HgsDiagnostics', 'HostComputeService',

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ARM64 runner has Hyper-V, HgsClient, HgsDiagnostics and HostComputeService under System32: features turned on in the runner image. They are not in the table because a plain device has none of them, which the help of Get-IslInboxModule says of feature modules.

$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($probe.ToString()))
$raw = & powershell.exe -NoProfile -NonInteractive -EncodedCommand $encoded 2>&1
$answer = ($raw | Where-Object { "$_".StartsWith('{') } | Select-Object -Last 1) | ConvertFrom-Json
$script:WindowsModules = @($answer.Windows)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two lists rather than one so that completeness can be judged on the Windows folder alone while existence still accepts Program Files, where PackageManagement, PowerShellGet and Pester 3.4 live on a plain device.

@fadwen
fadwen added this pull request to stack #24 October 6, 2026 16:17
@fadwen
fadwen merged commit 836f806 into main Oct 6, 2026
4 checks passed
@fadwen
fadwen deleted the test/inbox-modules-against-host branch October 6, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant