Jack Charon
Jack Charon

Reputation: 38

Strange behaviour of Write-Error (PowerShell): no output from within methods with a return value

The output of Write-Error is ommited in methods that have a return value (i.e. are not void):

Class MyClass {
    [void]MethodWithoutReturnValue([string]$Msg) {
        Write-Error "MyClass.MethodWithoutReturnValue(): $Msg"
    }

    [bool]MethodWithReturnValue([string]$Msg) {
        Write-Error "MyClass.MethodWithReturnValue(): $Msg"
        $this.MethodWithoutReturnValue("this won't work either")
        return $true
    }
}

[MyClass]$obj = [MyClass]::new()
$obj.MethodWithoutReturnValue('this error will show up')
[bool]$Result = $obj.MethodWithReturnValue('this error will NOT show up')

I'm expecting three error message but only get one. Please notice that the calling the void method from the bool method also omits the output, as if the call stack is "poisoned" somehow. And yes (though not shown in this example) void method calling void method works.

Can someone please explain this behaviour or did I just find a bug?

Upvotes: 1

Views: 508

Answers (1)

Sage Pourpre
Sage Pourpre

Reputation: 10323

There's a bug open for that currently. The problem is actually that Write-Error work in void method.

By design, the intent is that you should use Throw to produce an error from within a class.

Here's the modified version of your script

Class MyClass {
    [void]MethodWithoutReturnValue([string]$Msg) {
       Throw "MyClass.MethodWithoutReturnValue(): $Msg"
    }

    [bool]MethodWithReturnValue([string]$Msg) {
       Throw "MyClass.MethodWithReturnValue(): $Msg"
        $this.MethodWithoutReturnValue("this won't work either")
        return $true
    }
}

[MyClass]$obj = [MyClass]::new()
$obj.MethodWithoutReturnValue('this error will show up')
[bool]$Result = $obj.MethodWithReturnValue('this error will NOT show up')

Additional note

Using Throw will stop your script so the script won't proceed further. To prevent that, use a Try{}Catch{} statement.

[MyClass]$obj = [MyClass]::new()
Try {
    $obj.MethodWithoutReturnValue('this error will show up')
    }
Catch {
    Write-Error $_
}
[bool]$Result = $obj.MethodWithReturnValue('this error will NOT show up')

# I love Cyan
Write-Host 'Second error not being in a try catch mean this will not get printed' -ForegroundColor Cyan

Reference

Github -Write-Error fails to work in class methods that return a non-void value

Upvotes: 2

Related Questions