Can't enter anything but a string even though it expects an object

This topic contains 10 replies, has 4 voices, and was last updated by Profile photo of Jim Hofer Jim Hofer 3 years, 5 months ago.

  • Author
    Posts
  • #11134
    Profile photo of Michael Szarek
    Michael Szarek
    Participant

    How come when I do a Measure-Command with no parameters and when it asks for the parameter you can't enter anything but a string even though it expects an object to be entered?

  • #11136
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    Its to do with the parameters. When you run measure-command without parameters you get this

    £> Measure-Command
    cmdlet Measure-Command at command pipeline position 1
    Supply values for the following parameters:
    Expression:

    If you look at the help file -Expression ie PowerShell code is a mandatory parameter and so you will be prompted for the expression you want to measure. If you look at the examples they are both inputting expressions

  • #11159
    Profile photo of Michael Szarek
    Michael Szarek
    Participant

    Richard,

    I understand this much. The prompt in your example only accepts a string although it is expecting an object. Why is this?

  • #11174
    Profile photo of Joakim Svendsen
    Joakim Svendsen
    Participant

    I'm guessing it's an artifact of how mandatory parameters are prompted for and then read in. Maybe the actual cmdlet Read-Host is used? Or possibly whatever method Read-Host itself uses under the hood.

    This reminded me of a similar experience I had when at first I tried to use a cmdlet that took a script block, and got the prompt rather than supplying it on the command line. What I saw was something like this:


    PS E:\temp> Measure-Command

    cmdlet Measure-Command at command pipeline position 1
    Supply values for the following parameters:
    Expression: { 42 }
    Measure-Command : Cannot bind parameter 'Expression'. Cannot convert the "{ 42 }" value of type "System.String" to type
    "System.Management.Automation.ScriptBlock".
    At line:1 char:16
    + Measure-Command < <<< + CategoryInfo : InvalidArgument: (:) [Measure-Command], ParentContainsErrorRecordException + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.MeasureCommandCommand

    I think I was playing with Invoke-Command at the time.

    Of course, this works:


    PS E:\temp> Measure-Command { 42 } | select -exp TotalMilliseconds
    0.0206

    I believe that's what's being asked about. It has to do with parsing on the command line vs. how things are read in with Read-Host (or whatever's being used to read in), as far as I can tell. Someone who knows how the actual "read in code" is implemented would have to answer to explain properly, I think, but this attempt at an answer should hopefully provide some enlightenment.

  • #11175
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    The syntax for measure-command is:
    Measure-Command [-Expression] [-InputObject ] []

    -Expression is mandatory – You must have an expression to measure.

    What is an expression?

    Its a string of text that PowerShell can interpret and use to create a pipeline.

    When you don't supply an Expression – PowerShell will prompt you for one. It uses the prompt in the PowerShell console or ISE. At that point all you can enter is a string of text characters. You can't cut and paste an object or type in an object. PowerShell will then take that text and attempt to run it and measure the time it takes. It automatically converts your text into a script block.

  • #11177
    Profile photo of Michael Szarek
    Michael Szarek
    Participant

    Richard,

    My question is when I don't supply an Expression, why can't I enter an object if that is what it is expecting?

  • #11178
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    Because its NOT expecting an object when it prompts you for the mandatory parameter. Its expecting a script block and the only way you can enter that is to type it in

  • #11180
    Profile photo of Jim Hofer
    Jim Hofer
    Participant

    Joakim – I think your example is the closest to describing what Mike wants to know..

    If you have a cmdlet with a mandatory parameter that you fail to specify, PowerShell with prompt you for that parameter. The issue is, PowerShell always interprets the entry as a string. What Mike wants to know, is there any syntax or trick that will allow PowerShell to interpret the string correctly.


    $foo = get-myfoo
    measure-foo

    cmdlet Measure-Foo at command pipeline position 1
    Supply values for the following parameters:
    Foo: $foo
    Measure-Foo: Cannot bind parameter 'Foo'. Cannot convert the "$foo" value of type "System.String"
    to type "FOO".
    At line:1 char:1
    + Measure-Foo
    + ~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Measure-Foo], ParameterBindingException

  • #11183
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    The Mandatory attribute is a safety net. Its best practice to pass the correct data into a cmdlet rather than rely on the cmdlet prompt you for the missing data

  • #11185
    Profile photo of Michael Szarek
    Michael Szarek
    Participant

    Yes Jim that is exactly what I was looking to find out about. I understand the best practice for passing the correct data Richard, but I must know if it is possible to avoid to string parser or if there is any syntax that alert PowerShell that the input is not a string.

  • #11186
    Profile photo of Jim Hofer
    Jim Hofer
    Participant

    What Mike is trying to figure out is if there is PowerShell syntax to pass the correct object to the cmdlet, or if every cmdlet you write has to handle string equivalents of its mandatory parameters and attempt to resolve them itself?. This isn't a question about best practices from a user perspective, it is a question about how to pass non-string values to a cmdlet that doesn't accept strings; or alternately cmdlets need to be coded differently.

    Is there anyway to pass a script or object in PowerShell when prompted for the input instead of explicitly setting it as an argument or piping it in. Based on the conversation in the thread, I suspect the answer is either 'No' or 'I don't know of a way'.

You must be logged in to reply to this topic.