3

My questions are:

  • Why is this error not being thrown out into the code?
  • How can I make the error get thrown up into the code?
  • Where / How could I have figured this out on my own? / Where is the documentation for this "feature"?

    Function demo_problem
    {
        describe_global_error_variable
        $ret_value = "be loud please".extended_property
        write-host "returned a value=[$ret_value]."
        describe_global_error_variable
    }
    
    
    Function describe_global_error_variable
    {
        $cnt = $Error.Count
        write-host "`$Error .Count=[$($cnt)]." 
        $i=0
        while ($i -lt $cnt) {
            write-host "`$Error[$i].Exception.Message=[$($Error[$i].Exception.Message)]"
            $i += 1
            }
    }
    
    $script_block_throws = { 
            write-host "at beginning of script_block for script_block_throws.  `$this=[$this]."
            1/0
            return $true
            write-host "at end of script_block for script_block_throws.  `$this=[$this]."
        }
    
    $script_block_try_catch_throw = { 
            write-host "at beginning of script_block for script_block_try_catch_throw.  `$this=[$this]."
            try
            {
                1/0
                return $true
            }
            catch [Exception]{
                write-host "script_block_try_catch_throw caught an exception"
                throw "caught an exception" 
            }
            return $false
            write-host "at end of script_block for script_block_try_catch_throw.  `$this=[$this]."
        }
    
    try {
        Update-TypeData -Value:$script_block_throws -TypeName:System.String -MemberName:extended_property -Force -MemberType:ScriptProperty 
        demo_problem
        Update-TypeData -Value:$script_block_try_catch_throw -TypeName:System.String -MemberName:extended_property -Force -MemberType:ScriptProperty 
        demo_problem
    }
    catch [Exception]{
        write-host "exception got thrown out of the script block...."   
    }
    
    <#
    PS C:\ .\powershell_call_to_extended_property_fails_silently.ps1
    $Error .Count=[0]. \
    at beginning of script_block for script_block_throws.  $this=[be loud please].
    returned a value=[].
    $Error .Count=[1]. \
    $Error[0].Exception.Message=[Attempted to divide by zero.]
    $Error .Count=[1]. \
    $Error[0].Exception.Message=[Attempted to divide by zero.]
    at beginning of script_block for script_block_try_catch_throw.  $this=[be loud please].
    script_block_try_catch_throw caught an exception
    returned a value=[].
    $Error .Count=[3]. \
    $Error[0].Exception.Message=[caught an exception]
    $Error[1].Exception.Message=[Attempted to divide by zero.]
    $Error[2].Exception.Message=[Attempted to divide by zero.]
    #>
    
Jeff Maass
  • 3,632
  • 3
  • 26
  • 30

2 Answers2

5

What I've been told from the PowerShell team is that exceptions from properties are always masked as properties are heavily used during formatting & output. Exceptions are not masked for ScriptMethod. While this is unfortunate from a debugging stand-point, properties in general should not be doing much more than getting & setting state. I'd also add that .NET devs don't expect a property get to throw.

If you don't like this behavior feel free to submit an issue on the http://connect.microsoft.com site. I know at least one of the PowerShell devs doesn't like that the exception is always hidden i.e. even outside of formatting operations. Having some customer input on this could help the dev make a case for changing the behavior - at least when in strict mode.

Keith Hill
  • 194,368
  • 42
  • 353
  • 369
  • @keith-hill Properties **do** much more, look at the WPF for instance. Getting & setting of state is just a core of it. Powershell is actually very similar to WPF in that properties there are also irreplaceable for their visual representation. With the all exceptions muted, even such simple and standard scenario as lazy evaluation may be impossible/irresponsible for a lot of tasks. Are you sure there isn't at least a single exception type they would let go through? There probably isn't another .NET team who would have balls to mute all exceptions for a whole IL feature. – Mark Toman Jan 10 '14 at 12:18
  • I think this is most annoying because exceptions can only be generated at runtime, as such, if someone wanted to do type checking before being able to assign a value, this would be the place to do it. – wesm Dec 18 '14 at 22:47
2

I really think this is either some kind of scope problem or a bug. I was able to reproduce it pretty easily. The only way I was able to solve the problem was by way of a workaround, which looks like this:

Update-TypeData -Value:$script_block_try_catch_throw -TypeName:System.String -MemberName:extended_property -Force -MemberType:ScriptProperty -ErrorAction Stop
demo_problem
if($error[0].Exception.Message -eq "caught an exception")
{
    throw "I only exist to trigger the catch block"
}

I even tried this to no avail:

Update-TypeData -Value:{try{&$script_block_try_catch_throw}catch{throw "Error!"}} -TypeName:System.String -MemberName:extended_property -Force -MemberType:ScriptProperty -ErrorAction Stop

I was surprised that didn't work.

crownedjitter
  • 690
  • 4
  • 6
  • Thank you for trying. Of course, adding a check of $Error really isn't feasible b/c these blocks are meant to be extension methods. Requiring the developer to remember which methods require the check of $ERROR would undoubtedly fail. – Jeff Maass Nov 04 '13 at 04:24
  • +1 because, if Keith Hill is correct, it sure sounds like this is a by design.... :( – Jeff Maass Nov 05 '13 at 12:59