ygoe
ygoe

Reputation: 20374

Condition with a function call in PowerShell

Something is really weird with this language. I'm trying to execute a function and use its result value as condition. This is my code:

function Get-Platform()
{
    # Determine current Windows architecture (32/64 bit)
    if ([System.Environment]::GetEnvironmentVariable("ProgramFiles(x86)") -ne $null)
    {
        echo "x64"
        return "x64"
    }
    else
    {
        echo "x86"
        return "x86"
    }
}

if (Get-Platform -eq "x64")
{
    echo "64 bit platform"
}
if (Get-Platform -eq "x86")
{
    echo "32 bit platform"
}

The expected output is this:

x64
64 bit platform

But the actual output is this:

64 bit platform
32 bit platform

What's going on here? How can this be fixed? I couldn't find any examples on the web that use functions inside an ifcondition. Is that possible at all in Powershell? I'm on Windows 7 with no special setup, so I have whatever PS version comes with it.

Upvotes: 15

Views: 27371

Answers (2)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200273

If you want to compare the return value of a function in a conditional, you must group the function call (i.e. put it in parentheses) or (as @FlorianGerhardt suggested) assign the return value of the function to a variable and use that variable in the conditional. Otherwise the comparison operator and the other operand would be passed as arguments to the function (where in your case they're silently discarded). Your function then returns a result that is neither "" nor 0 nor $null, so it evaluates to $true, causing both messages to be displayed.

This should do what you want:

...
if ( (Get-Platform) -eq 'x64' ) {
  echo "64 bit platform"
}
...

BTW, you should avoid using separate if statements for conditions that are mutually exclusive. For a platform check an if..then..elseif

$platform = Get-Platform
if ($platform -eq "x64") {
  ...
} elseif ($platform -eq "x86") {
  ...
}

or a switch statement

Switch (Get-Platform) {
  "x86" { ... }
  "x64" { ... }
}

would be more appropriate.

I'd also avoid echoing inside the function. Just return the value and do any echoing that might be required in with the returned value. Anything echoed inside the function will also be returned to the caller.

One last note: personally I'd rather not rely on the existence of a particular folder or environment variable for determining the operating system architecture. Using WMI for this task deems me a lot more reliable:

function Get-Platform {
  return (gwmi Win32_OperatingSystem).OSArchitecture
}

This function will return a string "32-Bit" or "64-Bit", depending on the operating system architecture.

Upvotes: 23

flayn
flayn

Reputation: 5322

I think you are comparing a function and not the function result. Also somehow the echo does not work as expected in a function. I usually use Write-Host.

Here is my solution to your problem:

function Get-Platform()
{
    # Determine current Windows architecture (32/64 bit)
    if ([System.Environment]::GetEnvironmentVariable("ProgramFiles(x86)") -ne $null)
    {
        Write-Host("x64")
        return "x64"
    }
    else
    {
        Write-Host("x86")
        return "x86"
    }
}

$platform = Get-Platform

if ($platform -eq 'x64')
{
    echo "64 bit platform"
}

if ($platform -eq 'x86')
{
    echo "32 bit platform"
}

Upvotes: 5

Related Questions