From 67ec859beaf292283f9a34a9ef6a3ce385ae121d Mon Sep 17 00:00:00 2001
From: fadwen <110697945+fadwen@users.noreply.github.com>
Date: Tue, 6 Oct 2026 01:49:20 -0700
Subject: [PATCH 1/2] feat(harness): script paths from the pipeline, and a view
for every result type
Invoke-IntuneDetectionTest, Invoke-IntunePlatformScriptTest and
Invoke-IntuneRequirementTest took one -Path and nothing from the
pipeline, while Test-IntuneScript and Repair-IntuneScript take a folder's
scripts straight from Get-ChildItem. The three now bind -Path by value
and from a FullName or PSPath property, and run their body once per
script; the help's INPUTS says so.
Test-IntuneWin32Rule, Test-IntuneWin32Requirement and
Export-IntuneAgentDiagnostic results printed as property dumps, the
only result types without a format view. Each has a list view now, and
the module contract test requires a view for every output type an
exported command declares, so the next command cannot ship without one.
---
CHANGELOG.md | 5 +
IntuneScriptLab.Format.ps1xml | 59 +++++++++
Public/Invoke-IntuneDetectionTest.ps1 | 113 ++++++++++--------
Public/Invoke-IntunePlatformScriptTest.ps1 | 88 +++++++-------
Public/Invoke-IntuneRequirementTest.ps1 | 92 +++++++-------
Tests/Unit/Module.Contract.Tests.ps1 | 11 ++
.../Invoke-IntuneDetectionTest.Tests.ps1 | 13 ++
.../Invoke-IntunePlatformScriptTest.Tests.ps1 | 9 ++
.../Invoke-IntuneRequirementTest.Tests.ps1 | 10 ++
.../Invoke-IntuneDetectionTest.md | 15 ++-
.../Invoke-IntunePlatformScriptTest.md | 15 ++-
.../Invoke-IntuneRequirementTest.md | 15 ++-
docs/IntuneScriptLab/Repair-IntuneScript.md | 4 +-
en-US/IntuneScriptLab-Help.xml | 27 +++--
14 files changed, 306 insertions(+), 170 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f2df62a..0cf1656 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,11 @@ release notes.
### Added
+- `Invoke-IntuneDetectionTest`, `Invoke-IntunePlatformScriptTest` and `Invoke-IntuneRequirementTest` take script
+ paths from the pipeline, by value or from a `FullName` or `PSPath` property, so `Get-ChildItem .\Detections |
+ Invoke-IntuneDetectionTest` runs each one. `Test-IntuneWin32Rule`, `Test-IntuneWin32Requirement` and
+ `Export-IntuneAgentDiagnostic` results have a format view, like every other result type; the module contract
+ test now requires one for every output type an exported command declares.
- `Repair-IntuneScript` applies eight more edits, each the one the finding's message asks for: `-Force` on
`Install-Module`, `Install-PackageProvider`, `Install-Package`, `Update-Module` and `Uninstall-Module`,
`-Confirm:$false` on `Register-PSRepository`, `-ErrorAction SilentlyContinue` on a probing cmdlet in a Win32
diff --git a/IntuneScriptLab.Format.ps1xml b/IntuneScriptLab.Format.ps1xml
index d6f6753..db464c6 100644
--- a/IntuneScriptLab.Format.ps1xml
+++ b/IntuneScriptLab.Format.ps1xml
@@ -412,6 +412,65 @@
+
+ IntuneScriptLab.RuleResult
+
+ IntuneScriptLab.RuleResult
+
+
+
+
+
+ Met
+ "$($_.Kind) $($_.Operation)$(if ($_.Operator) { " $($_.Operator) '$($_.Value)'" })"
+ Target
+ Actual
+ Reason
+ Check32BitOn64System
+
+
+
+
+
+
+ IntuneScriptLab.ApplicabilityResult
+
+ IntuneScriptLab.ApplicabilityResult
+
+
+
+
+
+ Applicable
+ Reason
+ Applicability
+ Details
+ ($_.Checks | ForEach-Object { "$($_.Requirement): $(if ($_.Met) { 'met' } else { 'not met' })" }) -join "; "
+
+
+
+
+
+
+ IntuneScriptLab.Diagnostic
+
+ IntuneScriptLab.Diagnostic
+
+
+
+
+
+ Path
+ "{0:N1} MB" -f ($_.SizeBytes / 1MB)
+ Files
+ Logs
+ Registry
+ Timeline
+
+
+
+
+
IntuneScriptLab.RequirementResult
diff --git a/Public/Invoke-IntuneDetectionTest.ps1 b/Public/Invoke-IntuneDetectionTest.ps1
index 7d2090a..172adff 100644
--- a/Public/Invoke-IntuneDetectionTest.ps1
+++ b/Public/Invoke-IntuneDetectionTest.ps1
@@ -7,7 +7,8 @@ function Invoke-IntuneDetectionTest {
[CmdletBinding()]
[OutputType('IntuneScriptLab.DetectionResult')]
param(
- [Parameter(Mandatory, Position = 0)]
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
+ [Alias('FullName', 'PSPath')]
[string]$Path,
[ValidateSet('x86', 'x64', 'arm64')]
@@ -28,62 +29,70 @@ function Invoke-IntuneDetectionTest {
[switch]$EnforceSignatureCheck
)
- if ($Credential -and $Context -eq 'System') {
- throw '-Credential applies to -Context User; System runs as NT AUTHORITY\SYSTEM'
- }
- Write-Verbose "Starting $($MyInvocation.MyCommand.Name) for $($PSBoundParameters.Keys -join ', ')"
- $reasons = [System.Collections.Generic.List[string]]::new()
- $signatureStatus = ''
- $run = $null
- if ($EnforceSignatureCheck) {
- # With the check on, AgentExecutor returns exit 1 for an unsigned script without running it:
- # no probe record, "EnforceSignatureCheck: 1 ... applicationDetected: False" (W32-DET-SIGCHECK)
- $signature = Get-AuthenticodeSignature -FilePath (Resolve-Path -LiteralPath $Path).ProviderPath
- $signatureStatus = "$($signature.Status)"
- if ($signature.Status -ne 'Valid') {
- $reasons.Add("Signature status ${signatureStatus}: with the signature check enforced the agent " +
- 'does not run the script and reports not detected (exit 1 from AgentExecutor)')
+ process {
+ if ($Credential -and $Context -eq 'System') {
+ throw '-Credential applies to -Context User; System runs as NT AUTHORITY\SYSTEM'
}
- }
+ Write-Verbose "Starting $($MyInvocation.MyCommand.Name) for $($PSBoundParameters.Keys -join ', ')"
- if ($reasons.Count -eq 0) {
- $scriptRunSplat = @{
- Path = $Path
- Architecture = $Architecture
- Context = $Context
- Phase = 'detect'
- TimeoutSeconds = $TimeoutSeconds
+ $reasons = [System.Collections.Generic.List[string]]::new()
+ $signatureStatus = ''
+ $run = $null
+ if ($EnforceSignatureCheck) {
+ # With the check on, AgentExecutor returns exit 1 for an unsigned script without running it:
+ # no probe record, "EnforceSignatureCheck: 1 ... applicationDetected: False" (W32-DET-SIGCHECK)
+ $signature = Get-AuthenticodeSignature -FilePath (Resolve-Path -LiteralPath $Path).ProviderPath
+ $signatureStatus = "$($signature.Status)"
+ if ($signature.Status -ne 'Valid') {
+ $reasons.Add("Signature status ${signatureStatus}: with the signature check enforced the agent " +
+ 'does not run the script and reports not detected (exit 1 from AgentExecutor)')
+ }
}
- if ($Credential) { $scriptRunSplat.Credential = $Credential }
- $run = Invoke-IslScriptRun @scriptRunSplat
- $hasStdOut = -not [string]::IsNullOrWhiteSpace($run.StdOut)
- $hasStdErr = -not [string]::IsNullOrWhiteSpace($run.StdErr)
- if ($run.TimedOut) { $reasons.Add("Timed out after $TimeoutSeconds s; Intune kills the script at its " +
- "60-minute timeout and reports not detected") }
- elseif ($run.ExitCode -ne 0) { $reasons.Add("Exit code $($run.ExitCode): only exit 0 can mean installed") }
- if (-not $hasStdOut) { $reasons.Add('Nothing on stdout: exit 0 alone is "not detected"') }
- if ($hasStdErr) { $reasons.Add('Output on stderr: any error output means "not detected" even with exit ' +
- '0 and stdout') }
- }
+ if ($reasons.Count -eq 0) {
+ $scriptRunSplat = @{
+ Path = $Path
+ Architecture = $Architecture
+ Context = $Context
+ Phase = 'detect'
+ TimeoutSeconds = $TimeoutSeconds
+ }
+ if ($Credential) { $scriptRunSplat.Credential = $Credential }
+ $run = Invoke-IslScriptRun @scriptRunSplat
+ $hasStdOut = -not [string]::IsNullOrWhiteSpace($run.StdOut)
+ $hasStdErr = -not [string]::IsNullOrWhiteSpace($run.StdErr)
- Write-Verbose "Completed $($MyInvocation.MyCommand.Name)"
- [pscustomobject]@{
- PSTypeName = 'IntuneScriptLab.DetectionResult'
- Detected = ($reasons.Count -eq 0)
- Reason = if ($reasons.Count -eq 0) { ('Exit 0 with stdout and no ' +
- 'stderr') } else { $reasons -join '; ' }
- ExitCode = if ($run) { $run.ExitCode } else { 1 }
- StdOut = if ($run) { $run.StdOut } else { '' }
- StdErr = if ($run) { $run.StdErr } else { '' }
- TimedOut = if ($run) { $run.TimedOut } else { $false }
- Duration = if ($run) { $run.Duration } else { [timespan]::Zero }
- SignatureStatus = $signatureStatus
- Architecture = $Architecture
- Context = $Context
- RunAs = if ($run) { $run.RunAs } else { '' }
- Host = if ($run) { $run.Host } else { '' }
- ScriptPath = if ($run) { $run.ScriptPath } else { (Resolve-Path -LiteralPath $Path).ProviderPath }
+ if ($run.TimedOut) {
+ $reasons.Add("Timed out after $TimeoutSeconds s; Intune kills the script at its " +
+ '60-minute timeout and reports not detected')
+ }
+ elseif ($run.ExitCode -ne 0) {
+ $reasons.Add("Exit code $($run.ExitCode): only exit 0 can mean installed")
+ }
+ if (-not $hasStdOut) { $reasons.Add('Nothing on stdout: exit 0 alone is "not detected"') }
+ if ($hasStdErr) {
+ $reasons.Add('Output on stderr: any error output means "not detected" even with exit 0 and stdout')
+ }
+ }
+
+ Write-Verbose "Completed $($MyInvocation.MyCommand.Name)"
+ [pscustomobject]@{
+ PSTypeName = 'IntuneScriptLab.DetectionResult'
+ Detected = ($reasons.Count -eq 0)
+ Reason = if ($reasons.Count -eq 0) { ('Exit 0 with stdout and no ' +
+ 'stderr') } else { $reasons -join '; ' }
+ ExitCode = if ($run) { $run.ExitCode } else { 1 }
+ StdOut = if ($run) { $run.StdOut } else { '' }
+ StdErr = if ($run) { $run.StdErr } else { '' }
+ TimedOut = if ($run) { $run.TimedOut } else { $false }
+ Duration = if ($run) { $run.Duration } else { [timespan]::Zero }
+ SignatureStatus = $signatureStatus
+ Architecture = $Architecture
+ Context = $Context
+ RunAs = if ($run) { $run.RunAs } else { '' }
+ Host = if ($run) { $run.Host } else { '' }
+ ScriptPath = if ($run) { $run.ScriptPath } else { (Resolve-Path -LiteralPath $Path).ProviderPath }
+ }
}
}
diff --git a/Public/Invoke-IntunePlatformScriptTest.ps1 b/Public/Invoke-IntunePlatformScriptTest.ps1
index fd11fd3..20f0886 100644
--- a/Public/Invoke-IntunePlatformScriptTest.ps1
+++ b/Public/Invoke-IntunePlatformScriptTest.ps1
@@ -7,7 +7,8 @@ function Invoke-IntunePlatformScriptTest {
[CmdletBinding()]
[OutputType('IntuneScriptLab.PlatformScriptResult')]
param(
- [Parameter(Mandatory, Position = 0)]
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
+ [Alias('FullName', 'PSPath')]
[string]$Path,
[ValidateSet('x86', 'x64', 'arm64')]
@@ -26,50 +27,53 @@ function Invoke-IntunePlatformScriptTest {
[ValidateRange(1, 86400)]
[int]$TimeoutSeconds = 300
)
- Write-Verbose "Starting $($MyInvocation.MyCommand.Name) for $($PSBoundParameters.Keys -join ', ')"
- $scriptRunSplat = @{
- Path = $Path
- Architecture = $Architecture
- Context = $Context
- Phase = 'script'
- TimeoutSeconds = $TimeoutSeconds
- }
- if ($Credential) {
- if ($Context -eq 'System') {
- throw '-Credential applies to -Context User; System runs as NT AUTHORITY\SYSTEM'
+ process {
+ Write-Verbose "Starting $($MyInvocation.MyCommand.Name) for $($PSBoundParameters.Keys -join ', ')"
+
+ $scriptRunSplat = @{
+ Path = $Path
+ Architecture = $Architecture
+ Context = $Context
+ Phase = 'script'
+ TimeoutSeconds = $TimeoutSeconds
}
- $scriptRunSplat.Credential = $Credential
- }
- $run = Invoke-IslScriptRun @scriptRunSplat
- $runState = if ($run.TimedOut) { 'TimedOut' } elseif ($run.ExitCode -eq 0) { 'Success' } else { 'Failed' }
+ if ($Credential) {
+ if ($Context -eq 'System') {
+ throw '-Credential applies to -Context User; System runs as NT AUTHORITY\SYSTEM'
+ }
+ $scriptRunSplat.Credential = $Credential
+ }
+ $run = Invoke-IslScriptRun @scriptRunSplat
+ $runState = if ($run.TimedOut) { 'TimedOut' } elseif ($run.ExitCode -eq 0) { 'Success' } else { 'Failed' }
- # What happens next under Intune, from the PS-FAIL experiments: a failed script is fetched and
- # run again at the agent's next script policy fetch, which happens at a service start or
- # restart and otherwise every 8 hours (the hourly Win32 check-ins fetch no script policy),
- # three runs in all, then never again
- $warnings = [System.Collections.Generic.List[string]]::new()
- if ($runState -ne 'Success') {
- $warnings.Add(('Intune runs a failed platform script again at its next script policy fetch (an agent ' +
- 'start or restart, otherwise every 8 hours), three runs in total (initial plus two retries), ' +
- 'then reports Failed for good'))
- }
+ # What happens next under Intune, from the PS-FAIL experiments: a failed script is fetched and
+ # run again at the agent's next script policy fetch, which happens at a service start or
+ # restart and otherwise every 8 hours (the hourly Win32 check-ins fetch no script policy),
+ # three runs in all, then never again
+ $warnings = [System.Collections.Generic.List[string]]::new()
+ if ($runState -ne 'Success') {
+ $warnings.Add(('Intune runs a failed platform script again at its next script policy fetch (an ' +
+ 'agent start or restart, otherwise every 8 hours), three runs in total (initial plus two ' +
+ 'retries), then reports Failed for good'))
+ }
- Write-Verbose "Completed $($MyInvocation.MyCommand.Name)"
- [pscustomobject]@{
- PSTypeName = 'IntuneScriptLab.PlatformScriptResult'
- RunState = $runState
- ExitCode = $run.ExitCode
- ResultMessage = ($run.StdOut + $run.StdErr).TrimEnd("`r", "`n")
- StdOut = $run.StdOut
- StdErr = $run.StdErr
- TimedOut = $run.TimedOut
- Duration = $run.Duration
- Warnings = $warnings.ToArray()
- Architecture = $Architecture
- Context = $Context
- RunAs = $run.RunAs
- Host = $run.Host
- ScriptPath = $run.ScriptPath
+ Write-Verbose "Completed $($MyInvocation.MyCommand.Name)"
+ [pscustomobject]@{
+ PSTypeName = 'IntuneScriptLab.PlatformScriptResult'
+ RunState = $runState
+ ExitCode = $run.ExitCode
+ ResultMessage = ($run.StdOut + $run.StdErr).TrimEnd("`r", "`n")
+ StdOut = $run.StdOut
+ StdErr = $run.StdErr
+ TimedOut = $run.TimedOut
+ Duration = $run.Duration
+ Warnings = $warnings.ToArray()
+ Architecture = $Architecture
+ Context = $Context
+ RunAs = $run.RunAs
+ Host = $run.Host
+ ScriptPath = $run.ScriptPath
+ }
}
}
diff --git a/Public/Invoke-IntuneRequirementTest.ps1 b/Public/Invoke-IntuneRequirementTest.ps1
index 06775cb..ad2b709 100644
--- a/Public/Invoke-IntuneRequirementTest.ps1
+++ b/Public/Invoke-IntuneRequirementTest.ps1
@@ -7,7 +7,8 @@ function Invoke-IntuneRequirementTest {
[CmdletBinding()]
[OutputType('IntuneScriptLab.RequirementResult')]
param(
- [Parameter(Mandatory, Position = 0)]
+ [Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
+ [Alias('FullName', 'PSPath')]
[string]$Path,
[Parameter(Mandatory)]
@@ -37,51 +38,54 @@ function Invoke-IntuneRequirementTest {
[ValidateRange(1, 86400)]
[int]$TimeoutSeconds = 300
)
- Write-Verbose "Starting $($MyInvocation.MyCommand.Name) for $($PSBoundParameters.Keys -join ', ')"
- $scriptRunSplat = @{
- Path = $Path
- Architecture = $Architecture
- Context = $Context
- Phase = 'requirement'
- TimeoutSeconds = $TimeoutSeconds
- }
- if ($Credential) {
- if ($Context -eq 'System') {
- throw '-Credential applies to -Context User; System runs as NT AUTHORITY\SYSTEM'
+ process {
+ Write-Verbose "Starting $($MyInvocation.MyCommand.Name) for $($PSBoundParameters.Keys -join ', ')"
+
+ $scriptRunSplat = @{
+ Path = $Path
+ Architecture = $Architecture
+ Context = $Context
+ Phase = 'requirement'
+ TimeoutSeconds = $TimeoutSeconds
}
- $scriptRunSplat.Credential = $Credential
- }
- $run = Invoke-IslScriptRun @scriptRunSplat
- $compareSplat = @{
- StdOut = $run.StdOut
- StdErr = $run.StdErr
- ExitCode = $run.ExitCode
- TimedOut = $run.TimedOut
- OutputType = $OutputType
- Operator = $Operator
- Value = $Value
- }
- $verdict = Compare-IslRequirementOutput @compareSplat
+ if ($Credential) {
+ if ($Context -eq 'System') {
+ throw '-Credential applies to -Context User; System runs as NT AUTHORITY\SYSTEM'
+ }
+ $scriptRunSplat.Credential = $Credential
+ }
+ $run = Invoke-IslScriptRun @scriptRunSplat
+ $compareSplat = @{
+ StdOut = $run.StdOut
+ StdErr = $run.StdErr
+ ExitCode = $run.ExitCode
+ TimedOut = $run.TimedOut
+ OutputType = $OutputType
+ Operator = $Operator
+ Value = $Value
+ }
+ $verdict = Compare-IslRequirementOutput @compareSplat
- Write-Verbose "Completed $($MyInvocation.MyCommand.Name)"
- [pscustomobject]@{
- PSTypeName = 'IntuneScriptLab.RequirementResult'
- Applicable = $verdict.Met
- Reason = $verdict.Reason
- Output = $verdict.Output
- ExitCode = $run.ExitCode
- StdOut = $run.StdOut
- StdErr = $run.StdErr
- TimedOut = $run.TimedOut
- Duration = $run.Duration
- OutputType = $OutputType
- Operator = $Operator
- Value = $Value
- Architecture = $Architecture
- Context = $Context
- RunAs = $run.RunAs
- Host = $run.Host
- ScriptPath = $run.ScriptPath
+ Write-Verbose "Completed $($MyInvocation.MyCommand.Name)"
+ [pscustomobject]@{
+ PSTypeName = 'IntuneScriptLab.RequirementResult'
+ Applicable = $verdict.Met
+ Reason = $verdict.Reason
+ Output = $verdict.Output
+ ExitCode = $run.ExitCode
+ StdOut = $run.StdOut
+ StdErr = $run.StdErr
+ TimedOut = $run.TimedOut
+ Duration = $run.Duration
+ OutputType = $OutputType
+ Operator = $Operator
+ Value = $Value
+ Architecture = $Architecture
+ Context = $Context
+ RunAs = $run.RunAs
+ Host = $run.Host
+ ScriptPath = $run.ScriptPath
+ }
}
}
diff --git a/Tests/Unit/Module.Contract.Tests.ps1 b/Tests/Unit/Module.Contract.Tests.ps1
index 17c345d..a20d338 100644
--- a/Tests/Unit/Module.Contract.Tests.ps1
+++ b/Tests/Unit/Module.Contract.Tests.ps1
@@ -53,6 +53,17 @@ Describe 'IntuneScriptLab module contract' -Tag 'Unit', 'Contract' {
$text.Length | Should-BeLessThanOrEqual $Limit
}
+ It 'has a format view for every output type an exported command declares' {
+ # A result type without a view prints as a property dump; the view is part of the command's contract
+ $declared = @(Get-Command -Module IntuneScriptLab -CommandType Function | ForEach-Object {
+ $_.OutputType.Name
+ } | Where-Object { $_ -like 'IntuneScriptLab.*' } | Sort-Object -Unique)
+ $declared.Count | Should-BeGreaterThan 10
+ [xml]$format = Get-Content (Join-Path $script:ModuleRoot 'IntuneScriptLab.Format.ps1xml') -Raw
+ $viewed = @($format.Configuration.ViewDefinitions.View.ViewSelectedBy.TypeName | Sort-Object -Unique)
+ @($declared | Where-Object { $_ -notin $viewed }) | Should-BeCollection @()
+ }
+
It 'exports exactly the public functions' {
$exported = @((Get-Command -Module IntuneScriptLab -CommandType Function).Name | Sort-Object)
$exported | Should-BeCollection @(
diff --git a/Tests/Unit/Public/Invoke-IntuneDetectionTest.Tests.ps1 b/Tests/Unit/Public/Invoke-IntuneDetectionTest.Tests.ps1
index 6d3dfdd..ba13a79 100644
--- a/Tests/Unit/Public/Invoke-IntuneDetectionTest.Tests.ps1
+++ b/Tests/Unit/Public/Invoke-IntuneDetectionTest.Tests.ps1
@@ -28,6 +28,19 @@ Describe 'Invoke-IntuneDetectionTest' -Tag 'Unit', 'Public' {
$command.Parameters['Context'].Attributes.ValidValues | Should-BeCollection @('User', 'System')
}
+ It 'takes script paths from the pipeline, as Get-ChildItem gives them' {
+ Mock Invoke-IslScriptRun -ModuleName IntuneScriptLab {
+ # The result's ScriptPath comes from the launch, which is mocked here
+ [pscustomobject]@{ ExitCode = 0; TimedOut = $false; StdOut = 'ok'; StdErr = ''; ScriptPath = $Path }
+ }
+ $one = New-TestScript 'Pipe\Detect-One.ps1' 'exit 0'
+ $two = New-TestScript 'Pipe\Detect-Two.ps1' 'exit 0'
+ $results = @(Get-ChildItem (Split-Path $one) -Filter *.ps1 | Invoke-IntuneDetectionTest)
+ $results.Count | Should-Be 2
+ @($results.ScriptPath | Sort-Object) | Should-BeCollection @($one, $two)
+ @('a.ps1', 'b.ps1' | Invoke-IntuneDetectionTest).Count | Should-Be 2
+ }
+
It 'rejects a timeout outside 1..86400' {
{ Invoke-IntuneDetectionTest -Path $script:Detect -TimeoutSeconds 0 } | Should-Throw
}
diff --git a/Tests/Unit/Public/Invoke-IntunePlatformScriptTest.Tests.ps1 b/Tests/Unit/Public/Invoke-IntunePlatformScriptTest.Tests.ps1
index c96ccdd..26f5130 100644
--- a/Tests/Unit/Public/Invoke-IntunePlatformScriptTest.Tests.ps1
+++ b/Tests/Unit/Public/Invoke-IntunePlatformScriptTest.Tests.ps1
@@ -19,6 +19,15 @@ AfterAll {
Describe 'Invoke-IntunePlatformScriptTest' -Tag 'Unit', 'Public' {
Context 'Parameter Validation' {
+ It 'takes script paths from the pipeline, one result each' {
+ Mock Invoke-IslScriptRun -ModuleName IntuneScriptLab {
+ [pscustomobject]@{ ExitCode = 0; TimedOut = $false; StdOut = 'ok'; StdErr = '' }
+ }
+ $results = @('C:\lab\a.ps1', 'C:\lab\b.ps1' | Invoke-IntunePlatformScriptTest)
+ $results.Count | Should-Be 2
+ Should-Invoke Invoke-IslScriptRun -ModuleName IntuneScriptLab -Times 2 -Exactly
+ }
+
It 'defaults to the 32-bit host and the current user, as the portal does' {
Mock Invoke-IslScriptRun -ModuleName IntuneScriptLab {
[pscustomobject]@{ ExitCode = 0; TimedOut = $false; StdOut = ''; StdErr = '' }
diff --git a/Tests/Unit/Public/Invoke-IntuneRequirementTest.Tests.ps1 b/Tests/Unit/Public/Invoke-IntuneRequirementTest.Tests.ps1
index 63cd688..9078290 100644
--- a/Tests/Unit/Public/Invoke-IntuneRequirementTest.Tests.ps1
+++ b/Tests/Unit/Public/Invoke-IntuneRequirementTest.Tests.ps1
@@ -30,6 +30,16 @@ Describe 'Invoke-IntuneRequirementTest' -Tag 'Unit', 'Public' {
$command.Parameters['Operator'].Attributes.ValidValues.Count | Should-Be 6
}
+ It 'takes script paths from the pipeline, with the rule given once' {
+ Mock Invoke-IslScriptRun -ModuleName IntuneScriptLab {
+ [pscustomobject]@{ ExitCode = 0; TimedOut = $false; StdOut = 'ok'; StdErr = '' }
+ }
+ $results = @('C:\lab\a.ps1', 'C:\lab\b.ps1' |
+ Invoke-IntuneRequirementTest -OutputType String -Operator Equal -Value ok)
+ $results.Count | Should-Be 2
+ $results.Applicable | Should-All { $_ }
+ }
+
It 'defaults to the 64-bit host, as the portal does for requirement rules' {
Mock Invoke-IslScriptRun -ModuleName IntuneScriptLab {
[pscustomobject]@{ ExitCode = 0; TimedOut = $false; StdOut = "ok`r`n"; StdErr = '' }
diff --git a/docs/IntuneScriptLab/Invoke-IntuneDetectionTest.md b/docs/IntuneScriptLab/Invoke-IntuneDetectionTest.md
index a333e61..b8f7dc2 100644
--- a/docs/IntuneScriptLab/Invoke-IntuneDetectionTest.md
+++ b/docs/IntuneScriptLab/Invoke-IntuneDetectionTest.md
@@ -4,7 +4,7 @@ external help file: IntuneScriptLab-Help.xml
HelpUri: https://github.com/fadwen/IntuneScriptLab/blob/main/docs/IntuneScriptLab/Invoke-IntuneDetectionTest.md
Locale: en-US
Module Name: IntuneScriptLab
-ms.date: 10/05/2026
+ms.date: 10/06/2026
PlatyPS schema version: 2024-05-01
title: Invoke-IntuneDetectionTest
---
@@ -165,13 +165,15 @@ The detection script.
Type: System.String
DefaultValue: ''
SupportsWildcards: false
-Aliases: []
+Aliases:
+- FullName
+- PSPath
ParameterSets:
- Name: (All)
Position: 0
IsRequired: true
- ValueFromPipeline: false
- ValueFromPipelineByPropertyName: false
+ ValueFromPipeline: true
+ ValueFromPipelineByPropertyName: true
ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
@@ -209,9 +211,10 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable
## INPUTS
-### None
+### System.String
-This command does not accept pipeline input. Pass the script path with -Path.
+A script path, or an object with a FullName or PSPath property such as Get-ChildItem gives,
+one result per script.
## OUTPUTS
diff --git a/docs/IntuneScriptLab/Invoke-IntunePlatformScriptTest.md b/docs/IntuneScriptLab/Invoke-IntunePlatformScriptTest.md
index e649c57..a6f25b9 100644
--- a/docs/IntuneScriptLab/Invoke-IntunePlatformScriptTest.md
+++ b/docs/IntuneScriptLab/Invoke-IntunePlatformScriptTest.md
@@ -4,7 +4,7 @@ external help file: IntuneScriptLab-Help.xml
HelpUri: https://github.com/fadwen/IntuneScriptLab/blob/main/docs/IntuneScriptLab/Invoke-IntunePlatformScriptTest.md
Locale: en-US
Module Name: IntuneScriptLab
-ms.date: 10/05/2026
+ms.date: 10/06/2026
PlatyPS schema version: 2024-05-01
title: Invoke-IntunePlatformScriptTest
---
@@ -139,13 +139,15 @@ The script.
Type: System.String
DefaultValue: ''
SupportsWildcards: false
-Aliases: []
+Aliases:
+- FullName
+- PSPath
ParameterSets:
- Name: (All)
Position: 0
IsRequired: true
- ValueFromPipeline: false
- ValueFromPipelineByPropertyName: false
+ ValueFromPipeline: true
+ ValueFromPipelineByPropertyName: true
ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
@@ -183,9 +185,10 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable
## INPUTS
-### None
+### System.String
-This command does not accept pipeline input. Pass the script path with -Path.
+A script path, or an object with a FullName or PSPath property such as Get-ChildItem gives,
+one result per script.
## OUTPUTS
diff --git a/docs/IntuneScriptLab/Invoke-IntuneRequirementTest.md b/docs/IntuneScriptLab/Invoke-IntuneRequirementTest.md
index e6e95e3..9f9a009 100644
--- a/docs/IntuneScriptLab/Invoke-IntuneRequirementTest.md
+++ b/docs/IntuneScriptLab/Invoke-IntuneRequirementTest.md
@@ -4,7 +4,7 @@ external help file: IntuneScriptLab-Help.xml
HelpUri: https://github.com/fadwen/IntuneScriptLab/blob/main/docs/IntuneScriptLab/Invoke-IntuneRequirementTest.md
Locale: en-US
Module Name: IntuneScriptLab
-ms.date: 10/05/2026
+ms.date: 10/06/2026
PlatyPS schema version: 2024-05-01
title: Invoke-IntuneRequirementTest
---
@@ -188,13 +188,15 @@ The requirement script.
Type: System.String
DefaultValue: ''
SupportsWildcards: false
-Aliases: []
+Aliases:
+- FullName
+- PSPath
ParameterSets:
- Name: (All)
Position: 0
IsRequired: true
- ValueFromPipeline: false
- ValueFromPipelineByPropertyName: false
+ ValueFromPipeline: true
+ ValueFromPipelineByPropertyName: true
ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
@@ -253,9 +255,10 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable
## INPUTS
-### None
+### System.String
-This command does not accept pipeline input. Pass the script path with -Path.
+A script path, or an object with a FullName or PSPath property such as Get-ChildItem gives,
+one result per script.
## OUTPUTS
diff --git a/docs/IntuneScriptLab/Repair-IntuneScript.md b/docs/IntuneScriptLab/Repair-IntuneScript.md
index 4949872..0912d4e 100644
--- a/docs/IntuneScriptLab/Repair-IntuneScript.md
+++ b/docs/IntuneScriptLab/Repair-IntuneScript.md
@@ -1,4 +1,4 @@
----
+---
document type: cmdlet
external help file: IntuneScriptLab-Help.xml
HelpUri: https://github.com/fadwen/IntuneScriptLab/blob/main/docs/IntuneScriptLab/Repair-IntuneScript.md
@@ -22,7 +22,7 @@ Applies the mechanical fixes for findings that have one, and reports what is lef
```
Repair-IntuneScript [-Path] [-ScriptType ] [-Context ]
[-Architecture ] [-IncludeRule ] [-ExcludeRule ]
- [-EnforceSignatureCheck] [-Settings