Skip to content

feat(win32): default -Architecture to the device's 64-bit host - #30

Merged
fadwen merged 1 commit into
fix/batch-powershell-warningfrom
feat/native-64-bit-default
Oct 8, 2026
Merged

fadwen merged 1 commit into
fix/batch-powershell-warningfrom
feat/native-64-bit-default

Conversation

@fadwen

@fadwen fadwen commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Summary

Invoke-IntuneDetectionTest, Invoke-IntuneRequirementTest and Invoke-IntuneWin32AppTest defaulted -Architecture to x64, which Windows on ARM refuses: there is no x64 PowerShell host there, and the agent runs Win32 detection and requirement scripts in the native ARM64 host when the rule's "run as 32-bit" option is off (Validation/Findings.md, "Windows on ARM"). Every example in the help needed -Architecture arm64 added by hand on such a device, and a script written for an x64 machine failed on an ARM64 one before it ran anything.

Left out, the architecture is now the device's 64-bit host: x64 on an x64 device, arm64 on Windows on ARM. That is the host the agent would use on the same device, so the default follows the device instead of assuming one CPU.

Changes

  • Private/Get-IslHostArchitecture.ps1 (new): returns arm64 on an ARM64 device and x64 elsewhere.
  • The three commands: -Architecture has no default; an empty value is resolved with the helper before the first launch. x64 and arm64 still name one host each and are still refused on the other CPU; the result's Architecture field reports the host that ran.
  • Tests: the three tests that asserted the x64 default expect the device's own 64-bit host, and Invoke-IntuneDetectionTest gains one; Tests/Unit/Private/Get-IslHostArchitecture.Tests.ps1 checks the helper names a host Get-IslHostPath resolves to System32.
  • Help for the three commands and the rebuilt MAML: the parameter text describes the default; DefaultValue is empty.
  • CHANGELOG.md: Changed entry under Unreleased.

Verification

  • Get-IslHostArchitecture, Get-IslHostPath, the three command suites and Module.Contract: 81 passed on PowerShell 7.6.6; the same minus Get-IslHostPath on Windows PowerShell 5.1: 76 passed. Full unit suite on PowerShell 7.6.6: 907 passed, 2 skipped; on Windows PowerShell 5.1: 904 passed, 5 skipped.
  • On a Windows on ARM machine, Invoke-IntuneDetectionTest -Path and Invoke-IntuneRequirementTest -Path without -Architecture now run in System32\WindowsPowerShell\v1.0\powershell.exe and report Architecture: arm64; before this change both threw "No x64 PowerShell host on this Arm64 device".
  • Build/Build-Help.ps1 -SkipUpdate: help valid, MAML rebuilt and committed. PSScriptAnalyzer (Error, Warning) clean on the four source files; no line over 115 characters.
  • The arm64 CI job runs the changed tests on an ARM64 runner, where the default resolves to arm64.

Notes

  • Stacked on the batch-file warning PR (fix/batch-powershell-warning); merge that first.
  • Behaviour change for a reader on ARM who meant to test an x64-only app: no throw any more, the result says arm64. -Architecture x64 still throws there.

Invoke-IntuneDetectionTest, Invoke-IntuneRequirementTest and
Invoke-IntuneWin32AppTest defaulted -Architecture to x64, which Windows on
ARM refuses: there is no x64 PowerShell host there, and the agent runs
Win32 detection and requirement scripts in the native ARM64 host when the
rule's "run as 32-bit" option is off (Findings, "Windows on ARM"). Every
example in the help had to be given -Architecture arm64 by hand on such a
device.

The parameter now has no default. Left out, the commands resolve it with
Get-IslHostArchitecture, a new private helper that returns arm64 on an
ARM64 device and x64 elsewhere, which is the host the agent would use.
Explicit x64 and arm64 keep naming one host each and are still refused on
the other CPU; the result's Architecture field reports the host that ran.

The three tests that asserted the x64 default now expect the device's own
64-bit host, so the Windows on ARM job exercises the same assertion.

@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.

# Left out: the device's 64-bit host (x64, or arm64 on Windows on ARM), the agent's default
[ValidateSet('x86', 'x64', 'arm64')]
[string]$Architecture = 'x64',
[string]$Architecture,

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.

No default expression on the parameter, resolved in the body instead, for two reasons. [ValidateSet] is not applied to a default, so an empty default passes; and PlatyPS would print a default expression such as (Get-IslHostArchitecture) verbatim in the help's DefaultValue, where an empty value with the description explaining it reads better. Same in the other two commands.

Write-Verbose "Starting $($MyInvocation.MyCommand.Name) for $($PSBoundParameters.Keys -join ', ')"
# The agent's default host is the device's 64-bit one: arm64 on Windows on ARM, where no x64
# host exists, and x64 elsewhere
if (-not $Architecture) { $Architecture = Get-IslHostArchitecture }

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.

Resolved before $detectionSplat is built, so the dependency and supersedence flows and the result's Architecture field all carry the resolved value rather than an empty string that Invoke-IntuneDetectionTest would then refuse through its ValidateSet.

param()

$osArchitecture = "$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)"
if ($osArchitecture -eq 'Arm64') { 'arm64' } else { 'x64' }

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.

A separate helper rather than Get-IslDeviceFact, which already derives the same value: that one also reads free disk space and memory through CIM, which the harness does not need on every launch. The OS architecture is the same test Get-IslHostPath makes, so the two agree by construction.

}
$result = Invoke-IntuneDetectionTest -Path $script:Detect
Should-Invoke Invoke-IslScriptRun -ModuleName IntuneScriptLab -Exactly -Times 1 -ParameterFilter {
$Architecture -in 'x64', 'arm64'

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 parameter filter accepts either 64-bit host and the exact value is asserted on the result instead, because the filter runs in the mock's scope where the test file's $script:Native is not reliably visible. The same pattern replaces the literal 'x64' in the requirement and app test suites, so the arm64 CI job runs the same assertions as the x64 one.

```yaml
Type: System.String
DefaultValue: x64
DefaultValue: ''

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.

Empty DefaultValue is what Update-MarkdownCommandHelp writes for a parameter without one (compare -Credential in the same file), so a later full help build does not change this line.

@fadwen
fadwen added this pull request to stack #31 October 8, 2026 22:12
@fadwen
fadwen merged commit 26229c9 into main Oct 8, 2026
8 checks passed
@fadwen
fadwen deleted the feat/native-64-bit-default branch October 8, 2026 22:27
@fadwen fadwen mentioned this pull request Oct 8, 2026
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