Binary cmdlet binding fails to unwrap a scalar PSObject for StringCollection parameters · Issue #27969 · PowerShell/PowerShell · GitHub
Skip to content

Binary cmdlet binding fails to unwrap a scalar PSObject for StringCollection parameters #27969

Description

Prerequisites

Steps to reproduce

$source = @'
using System.Collections.Specialized;
using System.Management.Automation;

[Cmdlet("Test", "StringCollectionBinding")]
public sealed class TestStringCollectionBindingCommand : PSCmdlet
{
    [Parameter(Mandatory = true)]
    public StringCollection Value { get; set; }

    protected override void ProcessRecord()
    {
        WriteObject(Value[0]);
    }
}
'@

$type = Add-Type -TypeDefinition $source -PassThru
Import-Module -Assembly $type.Assembly

# Select-Object emits one scalar PSObject wrapping a string.
$value = 'test-value' | Select-Object -Unique

$value.GetType().FullName
$value -is [System.Management.Automation.PSObject]

Test-StringCollectionBinding -Value $value

# The control case succeeds:
Test-StringCollectionBinding -Value ([string[]]$value)

# Multiple pipeline results also succeed:
$values = 'first', 'second' | Select-Object -Unique
Test-StringCollectionBinding -Value $values

Expected behavior

System.String
True
test-value

Actual behavior

System.String
True

Test-StringCollectionBinding:
Cannot convert 'expected' to the type
'System.Collections.Specialized.StringCollection' required by parameter
'Value'. Unable to cast object of type
'System.Management.Automation.PSObject' to type 'System.String'.

Error details

Exception             : 
    Type              : System.Management.Automation.ParameterBindingException
    Message           : Cannot convert 'test-value' to the type 'System.Collections.Specialized.StringCollection' required by parameter 'Value'. Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.String'.
    ParameterName     : Value
    ParameterType     : [System.Collections.Specialized.StringCollection]
    TypeSpecified     : [System.Management.Automation.PSObject]
    ErrorId           : CannotConvertArgument
    Line              : 22
    Offset            : 37
    CommandInvocation : 
        MyCommand        : Test-StringCollectionBinding
        ScriptLineNumber : 22
        OffsetInLine     : 1
        HistoryId        : 1
        Line             : Test-StringCollectionBinding -Value $value 2>$null

        Statement        : Test-StringCollectionBinding -Value $value 2>$null
        PositionMessage  : At line:22 char:1
                           + Test-StringCollectionBinding -Value $value 2>$null
                           + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        InvocationName   : Test-StringCollectionBinding
        PipelineLength   : 1
        PipelinePosition : 1
    ErrorRecord       : 
        Exception             : 
            Type    : System.Management.Automation.ParentContainsErrorRecordException
            Message : Cannot convert 'test-value' to the type 'System.Collections.Specialized.StringCollection' required by parameter 'Value'. Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.String'.
            HResult : -2146233087
        CategoryInfo          : InvalidArgument: (:) [Test-StringCollectionBinding], ParentContainsErrorRecordException
        FullyQualifiedErrorId : CannotConvertArgument,TestStringCollectionBindingCommand
        InvocationInfo        : 
            MyCommand        : Test-StringCollectionBinding
            ScriptLineNumber : 22
            OffsetInLine     : 37
            HistoryId        : 1
            Line             : Test-StringCollectionBinding -Value $value 2>$null

            Statement        : $value
            PositionMessage  : At line:22 char:37
                               + Test-StringCollectionBinding -Value $value 2>$null
                               +                                     ~~~~~~
            CommandOrigin    : Internal
        ScriptStackTrace      : at <ScriptBlock>, <No file>: line 22
    TargetSite        : 
        Name          : EncodeCollection
        DeclaringType : [System.Management.Automation.ParameterBinderBase]
        MemberType    : Method
        Module        : System.Management.Automation.dll
    Data              : 
        System.Management.Automation.Interpreter.InterpretedFrameInfo, System.Management.Automation, Version=7.6.0.500, Culture=neutral, PublicKeyToken=31bf3856ad364e35 : <ScriptBlock>

    InnerException    : 
        Type       : System.InvalidCastException
        TargetSite : 
            Name          : ChkCastAny_NoCacheLookup
            DeclaringType : [System.Runtime.CompilerServices.CastHelpers]
            MemberType    : Method
            Module        : System.Private.CoreLib.dll
        Message    : Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.String'.
        Source     : System.Private.CoreLib
        HResult    : -2147467262
        StackTrace : 
   at System.Collections.Specialized.StringCollection.System.Collections.IList.Add(Object value)
   at System.Management.Automation.ParameterBinderBase.EncodeCollection(CommandParameterInternal argument, String parameterName, ParameterCollectionTypeInformation collectionTypeInformation, Type toType, Object currentValue, Boolean 
coerceElementTypeIfNeeded, Boolean& coercionRequired)
    Source            : System.Management.Automation
    HResult           : -2146233087
    StackTrace        : 
   at System.Management.Automation.ParameterBinderBase.EncodeCollection(CommandParameterInternal argument, String parameterName, ParameterCollectionTypeInformation collectionTypeInformation, Type toType, Object currentValue, Boolean 
coerceElementTypeIfNeeded, Boolean& coercionRequired)
   at System.Management.Automation.ParameterBinderBase.CoerceTypeAsNeeded(CommandParameterInternal argument, String parameterName, Type toType, ParameterCollectionTypeInformation collectionTypeInfo, Object currentValue)
   at System.Management.Automation.ParameterBinderBase.BindParameter(CommandParameterInternal parameter, CompiledCommandParameter parameterMetadata, ParameterBindingFlags flags)
   at System.Management.Automation.CmdletParameterBinderController.BindParameter(CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
   at System.Management.Automation.CmdletParameterBinderController.BindParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter, ParameterBindingFlags flags)
   at System.Management.Automation.CmdletParameterBinderController.BindNamedParameter(UInt32 parameterSets, CommandParameterInternal argument, MergedCompiledCommandParameter parameter)
   at System.Management.Automation.ParameterBinderController.BindNamedParameters(UInt32 parameterSets, Collection`1 arguments)
   at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1 arguments)
   at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)
   at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
   at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
   at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary psDefaultParameterValues)
   at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
   at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
--- End of stack trace from previous location ---
   at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
   at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext 
funcContext)
   at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
CategoryInfo          : InvalidArgument: (:) [Test-StringCollectionBinding], ParameterBindingException
FullyQualifiedErrorId : CannotConvertArgument,TestStringCollectionBindingCommand
InvocationInfo        : 
    MyCommand        : Test-StringCollectionBinding
    ScriptLineNumber : 22
    OffsetInLine     : 37
    HistoryId        : 1
    Line             : Test-StringCollectionBinding -Value $value 2>$null

    Statement        : $value
    PositionMessage  : At line:22 char:37
                       + Test-StringCollectionBinding -Value $value 2>$null
                       +                                     ~~~~~~
    CommandOrigin    : Internal
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 22

Environment data

Name                           Value
----                           -----
PSVersion                      7.6.5
PSEdition                      Core
GitCommitId                    7.6.5
OS                             Microsoft Windows 10.0.26200
Platform                       Win32NT
PSRemotingProtocolVersion      2.4
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs-TriageThe issue is new and needs to be triaged by a work group.WG-Enginecore PowerShell engine, interpreter, and runtimeWG-NeedsReviewNeeds a review by the labeled Working Group

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions