views:

99

answers:

2

When I have an error inside a script block that I'm testing with Measure-Command, the error is show at the line of the invocation, and not at the location the error is thrown.

Here's an example:

function ThrowAnError
{
    Write-Host "in ThrowAnError"
    throw "ThrowAnError"
}

Measure-Command  { ThrowAnError }

This reports At ScriptBlockErrors.ps1:6 char:16 and I'd love to be able to know that the error happended at line 4.

Any ideas?

A: 

It works fine in PowerShell v2:

PS Home:\> .\x.ps1
in ThrowAnError
ThrowAnError
At C:\...\x.ps1:4 char:10
+     throw <<<<  "ThrowAnError"
    + CategoryInfo          : OperationStopped: (ThrowAnError:String) [], RuntimeException
    + FullyQualifiedErrorId : ThrowAnError

But for PowerShell v1 I fear you're out of luck.

Joey
+2  A: 

As Johannes points out this scenario works fine in V2. In V1, you can get accurate error line info when you run the sriptblock directly but Measure-Command is doing something that results in loss of the original error's line number.

You can work-around this in V1 with a custom measure routine that uses the .NET StopWatch class. This routine is pretty simple and mirrors in script what Measure-Command does in binary code:

function ThrowAnError
{    
    Write-Host "in ThrowAnError"    
    throw "ThrowAnError"
}

function Measure-CommandEx([scriptblock]$expression)
{
    trap { $sw.Stop(); $sw.Elapsed; break }
    $sw = [Diagnostics.StopWatch]::StartNew()
    &$expression | Out-Null
    $sw.Stop()
    $sw.Elapsed
}

Measure-CommandEx { ThrowAnError }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 4
Ticks             : 44832
TotalDays         : 5.18888888888889E-08
TotalHours        : 1.24533333333333E-06
TotalMinutes      : 7.472E-05
TotalSeconds      : 0.0044832
TotalMilliseconds : 4.4832

ThrowAnError
At C:\Documents and Settings\Keith\foo.ps1:4 char:7
+     throw  <<<< "ThrowAnError"

Note that for very fine measurements it doesn't seem quite as accurate as the built-in Measure-Command because there is a bit of time lost in the interpretation and execution of the Start() and Stop() calls. However for operations that take in the 100 milliSecs (rough guess) or more, this should be accurate enough.

Keith Hill