Reputation: 80941
Imagine a script test.ps1
that looks like this:
Param (
[ValidateNotNullOrEmpty()]
$VMHost,
[switch]
$trace
)
$ErrorActionPreference = "Stop"
Set-StrictMode -Version 2
trap {
Set-PSDebug -Trace 0
$_.InvocationInfo
break
}
if ($trace) {
Set-PSDebug -Trace 2
}
if ($VMHost) {
$VMHost = @(@($VMHost) | % {
$h = $_
Switch ($h.GetType().Name) {
'String' {
"isastring"
}
default {
Write-Error -Category InvalidType -TargetObject $h -ErrorAction Stop -Message 'VMHost argument must be a String or a VMHost object.'
}
}
})
}
When run normally it does this:
PS> & .\test.ps1 -VMHost "foo"
foo
When run with the -trace
argument however it does this:
PS> & .\test.ps1 -VMHost "foo" -trace
DEBUG: 21+ if ( >>>> $VMHost) {
DEBUG: 22+ >>>> $VMHost = @(@($VMHost) | % {
DEBUG: 22+ $VMHost = @( >>>> @($VMHost) | % {
DEBUG: 22+ $VMHost = @(@( >>>> $VMHost) | % {
DEBUG: 22+ $VMHost = @(@($VMHost) | % >>>> {
DEBUG: ! CALL function '<ScriptBlock>' (defined in file 'path...\test.ps1')
DEBUG: 23+ >>>> $h = $_
DEBUG: ! SET $h = 'foo'.
DEBUG: ! SET $switch = 'String'.
DEBUG: 24+ Switch ( >>>> $h.GetType().Name) {
DEBUG: ! SET $switch = ''.
DEBUG: 35+ >>>> })
DEBUG: ! SET $VMHost = ''.
DEBUG: 13+ >>>> Set-PSDebug -Trace 0
DEBUG: ! CALL function '<ScriptBlock><trap>' (defined in file
'path...\test.ps1')
MyCommand :
BoundParameters : {}
UnboundArguments : {}
ScriptLineNumber : 23
OffsetInLine : 19
HistoryId : -1
ScriptName : path...\test.ps1
Line : $VMHost = @(@($VMHost) | % {
PositionMessage : At path...\test.ps1:23 char:19
+ $VMHost = @(@($VMHost) | % {
+ ~~~~~~~
PSScriptRoot : C:\Users\ereisner\TenableAppliancePackaging
PSCommandPath : C:\Users\ereisner\TenableAppliancePackaging\test.ps1
InvocationName :
PipelineLength : 0
PipelinePosition : 0
ExpectingInput : False
CommandOrigin : Internal
DisplayScriptPosition :
The variable cannot be validated because the value System.Object[] is not a valid value for the VMHost variable.
At path...\test.ps1:22 char:19
+ $VMHost = @(@($VMHost) | % {
+ ~~~~~~~
+ CategoryInfo : MetadataError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ValidateSetFailure
How is trace debugging causing an error like this?
What is powershell doing here?
Can this filter/assignment be cleanly rewritten to avoid this problem (bug?)?
Powershell version info:
PS> $PSVersionTable
Name Value
---- -----
PSVersion 3.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.42000
BuildVersion 6.2.9200.16481
PSCompatibleVersions {1.0, 2.0, 3.0}
PSRemotingProtocolVersion 2.2
Upvotes: 2
Views: 264
Reputation: 80941
Not a full answer but it appears that this is a powershell version 3 bug.
The issue appears to be in how switch
behaves in this scenario. It appears to "loop" one past the end of the single string argument it is given.
The same code run under PS 4 works as expected.
Upvotes: 1