1

I'm trying to write a function that will run 1 line of code if run PowerShell 5.1, and a different line if code if run in PowerShell 7. The problem I am running into is that PowerShell 5.1 won't even execute the code because it doesn't know what to do with the ? in the ternary operator.

It returns the error "Unexpected token '?' in expression or statement".

Is there a way to tell PowerShell 5 to ignore a piece of code?

Here is an example:

Function MyTestFunction
{
    $Value = 5

    if ($PSVersionTable.PSVersion.Major -le 5)
    {
        if ($Value -eq 5) { "Value is 5" } else { "Value isn't 5" }
    }
    else
    {
        $Value -eq 7 ? "Value is 7" : "Value isn't 7"
    }
}

I can get it to work by converting it to a string and using invoke-expression or a scriptblock. But this just seems sloppy to me. And it slows down the execution a bit.

$String = "'$Value -eq 7 ? '"Value is 7'" : '"Value isn't 7'""

Invoke-Expression -Command $String

& ([scriptblock]::Create($String))

I'm pretty sure there isn't but I'm hoping there's some command or setting that I'm not aware of in PowerShell 5 that will allow me to tell powershell to ignore the line of code

$Value -eq 7 ? "Value is 7" : "Value isn't 7"

when it's run in 5.1 so it will compile and execute.

Preferably Something that's doesn't require me to escape or convert the code.

kmarryat
  • 156
  • 4
  • 2
    AFAIK PowerShell always parses the whole source file. The only practical way that comes to my mind is to move the PS 7 specific code into a separate source file and load that depending on PS version. – zett42 Jan 07 '23 at 07:54
  • Even though PowerShell uses JIT compilation since version 3, it does not provide pre-processor directives. Well technically it does with the `#Requires` statements but it does not provide a `#if` like C# does, which opens a conditional compilation. You could however store the two different code blocks in a string, check the PS version and use the `iex` command to invoke the correct script block: `{ iex "& $command" }` –  Jan 07 '23 at 10:19
  • 2
    Is there a specific reason you need to use a ternary on the ps7 branch rather than an “if expression” like the ps5 branch? You *could* conditionally dot-source different external script files depending on ps version which would mean ps5 never tries to parse the ps7 file, but that seems harder to maintain than just downgrading the ps7 ternary to a ps5 “if expression”… – mclayton Jan 07 '23 at 15:11
  • Thank you #zett42 and #mclayton . I do think dot sourcing the offending code would be the only other alternative to what I already tried with converting it to a string. Both work arounds will slow down execution a bit but should work. FYI, the ternary was just an example, I'm not trying to use it specifically. I was thinking about what I might encounter in future projects. – kmarryat Jan 07 '23 at 15:43
  • If the intent is to make a script compatible with Core and Windows PowerShell I really don't see the point in forcing it to use a feature only available to Core – Santiago Squarzon Jan 07 '23 at 16:55

2 Answers2

-1

Here is the reference to your issue. Determine the version of powershell

You may use the 'PSVersion' object in 'PSVersionTable' where 'Major' is the property to check the version and the invoke-command. The below modified code may look like this with if-else statement and should run the first line of code in Powershell 5.1 and the below code for version 7 should run only on Powershell 7.

Function MyTestFunction {
if ($PSVersionTable.PSVersion.Major -le 5) {
    if ($Value -eq 5) { "Value is 5" } else { "Value isn't 5" }
}
elseif ($PSVersionTable.PSVersion.Major -eq 7) {
    if ($Value -eq 7) { "Value is 7" } else { "Value isn't 7" }
}
}

Since the ternary operator '? :' was not available prior to Powershell 7 the if statement can be rewritten as

if ($Value -eq 7) { "Value is 7" } else { "Value isn't 7" }

This should run on both 5.1 and 7 versions.

AmpHertz
  • 1
  • 1
  • Thank you for the Reply but my problem is NOT identifying the powershell version. My original code handles that just fine. My problem is that Powershell 5.1 errors on this line of code which has a Powershell 7 ternary operator. $Value -eq 7 ? "Value is 7" : "Value isn't 7" I'm looking for a way to have powershell 5 ignore this line since it will not be executed when the function is run in ps5. – kmarryat Jan 07 '23 at 05:43
-1

My advice would to use switch

function FunctionName {

switch ($PSVersionTable.PSVersion.Major -le 5) {
    false { Write-Output "PowerShell Versions is 7 "  }
    Default { Write-Output "PowerShell Versions is 5 "}
}
    # verify output
$PSVersionTable.PSVersion.ToString()
}

On windows powershell output was

PS> FunctionName
PowerShell Versions is 5
5.1.22621.963

On VS-Code with pwsh 7 output was


PS> FunctionName
PowerShell Versions is 7 
7.3.1

More info on switch

about_switch

Hopefully this can help. I find switch statements to be much easier to understand.

stim-ca
  • 49
  • 4