1
$PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      22621  4391    

Consider the following snippet

# Function to determine if the OS is Windows Server
function Is-WindowsServer {
    $osVersion = (Get-WmiObject -Class Win32_OperatingSystem).Caption
    return $osVersion -like "*Server*"
}

# Function to check if SMB/Network Sharing is installed
function Is-SMBInstalled {
    if (Is-WindowsServer) {
        Write-Output "Detected Windows Server. This should print."
        $smbFeature = Get-WindowsFeature -Name FS-SMB1 -ErrorAction SilentlyContinue
        if ($smbFeature -and $smbFeature.Installed) {
            return $true
        } else {
            return $false
        }
    } else {
        Write-Output "Detected Windows 10/11 client. This should print."
        $smbFeature = Get-WindowsOptionalFeature -Online -FeatureName "SMB1Protocol" -ErrorAction SilentlyContinue
        if ($smbFeature -and $smbFeature.State -eq "Enabled") {
            return $true
        } else {
            return $false
        }
    }
    Write-Output "This should be unreachable."
}

Is-SMBInstalled # probe

if (Is-SMBInstalled -eq $true) {
    Write-Output "If above line is False. This should not print."
}

Expected output on Windows 10/11 with Samba disabled:

Detected Windows 10/11 client. This should print.
False

Script output on Windows 10/11 with Samba disabled:

Detected Windows 10/11 client.
False
If above line is False. This should not print.

Moreover, by itself,

if (Is-SMBInstalled -eq $true) {
    Write-Output "If above line is False. This should not print."
}

doesn't seem to properly calls Is-SMBInstalled. Without Is-SMBInstalled # probe, the output is just If above line is False. This should not print.

I've tried refactoring by putting Is-SMBInstalled inside a $variable, this works in a sense that the function is properly called. But the conditional still behaves unexpectedly.

I also tried the grouping function as per https://stackoverflow.com/a/66585435/14097947 if ((Is-SMBInstalled)) {, this also doesn't work.

2
  • It happens to have no ill effects in your case, but note that if (Is-SMBInstalled -eq $true) ... indeed needs to be if ((Is-SMBInstalled) -eq $true) ..., as explained in the answer you linked to; without the (...) around the function call, -eq and $true are passed as arguments to your Is-SMBInstalled function (which the latter happens to ignore). Commented Nov 19, 2024 at 12:48
  • Your real problem is the use of Write-Output, which writes to the success output stream, just like return does, thereby modifying the function's "return value", as pointed out in sirtao's answer and as explained in more detail in the linked duplicate. Commented Nov 19, 2024 at 12:51

1 Answer 1

4

By using Write-Output the result of Is-SMBInstalled is always a mixed-content array because Write-Output push its contents to the Success Stream(aka stdOut) the same as Return.

And thus is always true when compared left-side.

Replace the Write-Output with Write-Host, which does not write on the Success Stream.

And since you are already there:

  1. The Wim cmdlets has been obsolete since Powershell 3, and have been removed from powershell 6+: replace Get-WimObject with Get-CimInstance.
    Doing so will make it forward-compatible.
  2. I suggest using Approved Verbs.

have a example

# Function to determine if the OS is Windows Server
function Test-IsWindowsServer {
    # Left-side Filtering for the win.   
    # It returns $False if it finds nothing, and $True if it finds anything.   
    # NOTE WELL: I don't have Windows Server available to test now, so check if
    # the filter is working correctly.   
    [bool](Get-CimInstance -ClassName Win32_OperatingSystem -Filter 'Caption Like "%server%"')
}

# Function to check if SMB/Network Sharing is installed
function Test-IsSMBInstalled {
        
    if (Test-IsWindowsServer) {
        Write-Host 'Detected Windows Server. This should print.'
        $smbFeature = Get-WindowsFeature -Name FS-SMB1 -ErrorAction SilentlyContinue

        # no reason for a IF, this will return either $true or $False directly.   
        return ($smbFeature.Installed) 
    }
    # Strictly speaking you don't need the Else because it's not reaching here
    # if Test-IsWindowsServer is $true, evaluate yourself if it's clearer with
    # or without.   
    else {
        Write-Host 'Detected Windows 10/11 client. This should print.'
        $smbFeature = Get-WindowsOptionalFeature -Online -FeatureName 'SMB1Protocol' -ErrorAction SilentlyContinue 
        
        # no reason for a IF, this will return either $true or $False directly.   
        # Evaluate using "-like" instead of "-eq".  
        return ($smbFeature.State -eq 'Enabled') 
    }

    # A Write-Warning is the perfect fit for this.   
    Write-Warning 'This should be unreachable.'
}

# This will print the 'Detected' version line and then the boolean output.   
Test-IsSMBInstalled

# note this will print again the 'Detected' version line.   
if (Test-IsSMBInstalled) {  
    Write-Host 'If above line is False. This should not print.'
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.