Skip to content

fix(win32): warn about powershell.exe inside the batch file an install command names - #29

Merged
fadwen merged 1 commit into
fix/install-command-cwdfrom
fix/batch-powershell-warning
Oct 8, 2026
Merged

fadwen merged 1 commit into
fix/install-command-cwdfrom
fix/batch-powershell-warning

Conversation

@fadwen

@fadwen fadwen commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Summary

Invoke-IntuneWin32AppTest warned that powershell.exe runs as the 32-bit host only when powershell appeared on the install or uninstall command line. The common shape is an install.cmd wrapper that calls powershell.exe inside: that runs 32-bit just the same, from the agent's 32-bit cmd.exe, and HKLM:\SOFTWARE and Program Files are redirected without the command line showing it. The harness reproduced the effect (the value landed in WOW6432Node, the post-install detection failed) but said nothing about the cause.

Changes

  • Public/Invoke-IntuneWin32AppTest.ps1: when the command line itself has no powershell call and its first token is a .cmd or .bat file in the content folder, the file is scanned for the same pattern and the warning names the file and line. The command-line warning is unchanged.
  • Tests/Unit/Public/Invoke-IntuneWin32AppTest.Tests.ps1: a batch file with a powershell.exe line produces the warning with its line number; a batch file without one, named with quotes and arguments, produces no 32-bit warning.
  • docs/IntuneScriptLab/Invoke-IntuneWin32AppTest.md and the rebuilt MAML: the launch paragraph says the warning comes from the command line or the batch file it names.
  • CHANGELOG.md: Fixed entry under Unreleased.

Verification

  • Tests/Unit/Public/Invoke-IntuneWin32AppTest.Tests.ps1: 36 passed on PowerShell 7.6.6 and on Windows PowerShell 5.1.
  • Full unit suite on PowerShell 7.6.6 with the stacked changes applied: 907 passed, 2 skipped; on Windows PowerShell 5.1: 904 passed, 5 skipped.
  • Build/Build-Help.ps1 -SkipUpdate: help valid, MAML rebuilt and committed.
  • PSScriptAnalyzer (Error, Warning) clean on the changed file; no line over 115 characters.
  • Measured on the x64 lab device as SYSTEM with 0.29.0: an install.cmd calling powershell.exe wrote HKLM:\SOFTWARE\IslPost4 into WOW6432Node and the 64-bit detection missed it, with no warning; the same install with powershell.exe on the command line produced the warning. The new branch covers the first case.

Notes

  • Stacked on the launcher fix (fix/install-command-cwd); merge that first.

…l command names

Invoke-IntuneWin32AppTest warned about the 32-bit host only when
"powershell" appeared on the install or uninstall command line. A
powershell.exe call inside the batch file the command line names, the
common "install.cmd" wrapper, runs 32-bit just the same from the agent's
32-bit cmd.exe, so HKLM:\SOFTWARE and Program Files are redirected there
without the command line showing it; the harness reproduced the miss
(the post-install detection failed) but said nothing about why.

When the command line itself has no powershell call and its first token
is a .cmd or .bat file in the content folder, the file is scanned for the
same pattern and the warning names the file and line. The help's launch
paragraph mentions both places the warning comes from.

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

'process); HKLM:\SOFTWARE and Program Files are redirected there')
}
$source = (Resolve-Path -LiteralPath $Content).ProviderPath
else {

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.

An else rather than a second independent check, so a command line such as powershell.exe -File install.ps1 keeps its one warning and a batch file is only scanned when the command line itself said nothing. Two warnings for the same host would read as two problems.

# The same host hides inside a batch file the command line names: install.cmd calling
# powershell.exe runs it 32-bit too, from the agent's 32-bit cmd.exe, without the
# command line showing it
$first = if ($CommandLine -match '^\s*"([^"]+)"') { $Matches[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.

The first token is taken from the command line as the portal would see it: a quoted path ("install.cmd" /quiet) or the bare first word. No attempt at full cmd.exe parsing; anything more exotic falls through to no warning, which is the previous behaviour.

# command line showing it
$first = if ($CommandLine -match '^\s*"([^"]+)"') { $Matches[1] }
else { ($CommandLine.Trim() -split '\s+', 2)[0] }
$batch = if ($first -match '(?i)\.(cmd|bat)$') { Join-Path -Path $source -ChildPath $first }

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.

Only .cmd and .bat are scanned, because those are text the harness can read. A setup.exe or a .vbs wrapper that launches powershell.exe is out of reach, and Join-Path with the source folder keeps a .\install.cmd spelling working as well as a bare name.

$batch = if ($first -match '(?i)\.(cmd|bat)$') { Join-Path -Path $source -ChildPath $first }
else { $null }
if ($batch -and (Test-Path -LiteralPath $batch -PathType Leaf)) {
$hit = Select-String -LiteralPath $batch -Pattern $hostPattern | Select-Object -First 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.

First hit only: one warning per batch file, naming the first line so the reader can find it, rather than one per call. The pattern is the same one applied to the command line, so a powershell.exe token inside a quoted string or at line start is matched the same way in both places.

$intuneWin32AppTestSplat = @{
DetectionPath = $script:Fixture.Detection
ContentPath = $script:Fixture.Content
InstallCommand = '"install.cmd" /quiet'

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 negative case uses the quoted-with-arguments spelling so it exercises the first-token parsing, not just the absence of a powershell line: the file must be found and scanned, and still produce nothing.

@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 fix/batch-powershell-warning 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