1

I have the following PowerShell function:

function Get-Devices {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$False, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, ParameterSetName='Code')]
        [String[]]$Codes
    )
    foreach ($Code in $Codes){write-output $Code}
}

While I call like this:

Get-Devices -Code 92D, 88L

It produced the following output:

92
88

Notice, the last character D and the character L is stripped off. I can get it to work if I enclose the values in quotes. Additionally, all of the below will all work as expected:

Get-Devices -Code D92, L88
Get-Devices -Code 92E, 88F
Get-Devices -Code 34G, 12Z
Get-Devices -Code "92D", "88L"

Especially note the 2nd line above. It's only the D and L suffices that have caused problems for me.

What's causing specifically D and L to be stripped off the end of each value? I really don't want to force people to add surrounding quotes to ALL values just to avoid this specific issue. What's the least complex way to force Powershell to not strip off D or L from the end of each value, without requiring surrounding quotes for those values?

I already tried changing the input Parameter type to: [Array[]]$Codes. That didn't make any difference in behavior. I also confirmed all values are treated as a string type when processed by the above loop. Any help to avoid this behavior would be greatly appreciated!

The only good news is that this little piece of code and respective strange behavior is easily reproducible....

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
MKANET
  • 573
  • 6
  • 27
  • 51

2 Answers2

4

To understand what's going on here, remember that Powershell has a close relationship with .Net. Take a look at the docs for declaring number literals in C# for a clue:

We can get more specific by checking the PowerShell language specification*:

  • §2.3.5.1.1 Integer Literals includes: l, kb, mb, gb, tb, and pb.
  • §2.3.5.1.2 Real Literals adds d.

You'll see here that there are several suffixes (including D and L) to indicate which specific type of number you're working with. I'm willing to bet all of those other suffixes will cause you the same problem. If I'm right about that, I would also go back and take a closer look at this assertion:

I also confirmed all values are treated as a string type when processed by the above loop.

That even looks like it's true from your code. However, something before the code is first interpreting those values as numbers, which are then converted to strings. Unfortunately, in this case it's likely the shell itself, meaning there's really nothing you can do about the problem except for require quotes :(


*Found via this question.

Community
  • 1
  • 1
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • Wow Joel. Thanks for the in depth explanation! Interesting that Powershell decides to first treat the input value as a number; ***then***, convert it to the type I asked for. Convincing the users of this script to add quotes around all values (even when they don't include have space characters) is going to pretty much make it not worth using the script. – MKANET Aug 11 '15 at 01:57
  • 1
    I got extremely lucky in this specific case. I just realized that all input values need to be "triple hex" format. So, I only need to worry about a missing "D" character. Hence, I was able to add a condition that "presumes" a D suffix if the value is only 2 characters in length (instead of 3). – MKANET Aug 11 '15 at 15:40
1

Very interesting. I didn't know this and can't find any docmentation, but in an argument context (see Get-Help about_Parsing), D and L seems to be interpreted as indicators for whether a number is to be treated a [decimal] or [long].

See:

PS C:\> $ExecutionContext.InvokeCommand.ExpandString(2.74D)
2.74
PS C:\> $ExecutionContext.InvokeCommand.ExpandString(2.74L)
3

There's nothing you can do in the Param block itself - the D and L are interpreted by the parser, ie. the step after pressing enter but just before the argument is passed to the function

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206