Permalink
Browse files

Replaced existing ResolveError with a modified variant that includes …

…a short view, so that exceptions can be represented as one-liners for build output parsing purposes (it special cases Sql Exceptions as well to dig into the real errors)

Relies on new SelectObjectWithDefault function that can safely read properties off of objects w/out adding to the $Error collection (oddly, I've found this necessary when using WinRM, so I left that code in)

For instance, a short representation of an Error looks like this:
Error:  At C:\source\project\build\modules\Sql.psm1:175 char:36 +   [Void]$database.ExecuteNonQuery <<<< ($commands) [<<==>>] Exception: Exception calling "ExecuteNonQuery" with "1" argument(s): "ExecuteNonQuery failed for Database 'a73fa37f891e46bbab9e2b23b8f87c56'. " --> ExecuteNonQuery failed for Database 'a73fa37f891e46bbab9e2b23b8f87c56'.  --> An exception occurred while executing a Transact-SQL statement or batch. --> Foreign key 'fk_file_cabinet_num' references invalid column 'file_cabinet_num' in referencing table 'file_cabinet_files'.Could not create constraint. See previous errors. --> (Line [4] Proc
edure [] Class [16]  Number [1769] State [1] )

This is much more actionable / easier to read than 50 lines of output from an Exception with 4 InnerExceptions
  • Loading branch information...
1 parent 808148c commit fff5f6fc5326a29cc90310a75562a188c36a787e @Iristyle Iristyle committed with May 17, 2012
Showing with 86 additions and 14 deletions.
  1. +86 −14 psake.psm1
View
@@ -384,7 +384,7 @@ function Invoke-psake {
if ($currentConfig.verboseError) {
$error_message = "{0}: An Error Occurred. See Error Details Below: `n" -f (Get-Date)
$error_message += ("-" * 70) + "`n"
- $error_message += "Error: {0}`n" -f (($_ | Out-String) -replace "`n", '')
+ $error_message += "Error: {0}`n" -f (ResolveError $_ -Short)
$error_message += ("-" * 70) + "`n"
$error_message += ResolveError $_
$error_message += ("-" * 70) + "`n"
@@ -393,7 +393,7 @@ function Invoke-psake {
$error_message += get-variable -scope script | format-table | out-string
} else {
# ($_ | Out-String) gets error messages with source information included.
- $error_message = "Error: {0}: `n{1}" -f (Get-Date), ($_ | Out-String)
+ $error_message = "Error: {0}: `n{1}" -f (Get-Date), (ResolveError $_ -Short)
}
$psake.build_success = $false
@@ -585,20 +585,92 @@ function CleanupEnvironment {
}
}
-# borrowed from Jeffrey Snover http://blogs.msdn.com/powershell/archive/2006/12/07/resolveerror.aspx
-function ResolveError($ErrorRecord = $Error[0]) {
- $error_message = "`nErrorRecord:{0}ErrorRecord.InvocationInfo:{1}Exception:{2}"
- $formatted_errorRecord = $ErrorRecord | format-list * -force | out-string
- $formatted_invocationInfo = $ErrorRecord.InvocationInfo | format-list * -force | out-string
- $formatted_exception = ""
- $Exception = $ErrorRecord.Exception
- for ($i = 0; $Exception; $i++, ($Exception = $Exception.InnerException)) {
- $formatted_exception += ("$i" * 70) + "`n"
- $formatted_exception += $Exception | format-list * -force | out-string
- $formatted_exception += "`n"
+function SelectObjectWithDefault
+{
+ [CmdletBinding()]
+ param(
+ [Parameter(ValueFromPipeline=$true)]
+ [PSObject]
+ $InputObject,
+ [string]
+ $Name,
+ $Value
+ )
+
+ process {
+ if ($_ -eq $null) { $Value }
+ elseif ($_ | Get-Member -Name $Name) {
+ $_.$Name
+ }
+ elseif (($_ -is [Hashtable]) -and ($_.Keys -contains $Name)) {
+ $_.$Name
+ }
+ else { $Value }
}
+}
+
+# borrowed from Jeffrey Snover http://blogs.msdn.com/powershell/archive/2006/12/07/resolve-error.aspx
+# modified to better handle SQL errors
+function ResolveError
+{
+ [CmdletBinding()]
+ param(
+ [Parameter(ValueFromPipeline=$true)]
+ $ErrorRecord=$Error[0],
+ [Switch]
+ $Short
+ )
+
+ process {
+ if ($_ -eq $null) { $_ = $ErrorRecord }
+ $ex = $_.Exception
+
+ if (-not $Short) {
+ $error_message = "`nErrorRecord:{0}ErrorRecord.InvocationInfo:{1}Exception:`n{2}"
+ $formatted_errorRecord = $_ | format-list * -force | out-string
+ $formatted_invocationInfo = $_.InvocationInfo | format-list * -force | out-string
+ $formatted_exception = ''
+
+ $i = 0
+ while ($ex -ne $null) {
+ $i++
+ $formatted_exception += ("$i" * 70) + "`n" +
+ ($ex | format-list * -force | out-string) + "`n"
+ $ex = $ex | SelectObjectWithDefault -Name 'InnerException' -Value $null
+ }
- return $error_message -f $formatted_errorRecord, $formatted_invocationInfo, $formatted_exception
+ return $error_message -f $formatted_errorRecord, $formatted_invocationInfo, $formatted_exception
+ }
+
+ $lastException = @()
+ while ($ex -ne $null) {
+ $lastMessage = $ex | SelectObjectWithDefault -Name 'Message' -Value ''
+ $lastException += ($lastMessage -replace "`n", '')
+ if ($ex -is [Data.SqlClient.SqlException]) {
+ $lastException += "(Line [$($ex.LineNumber)] " +
+ "Procedure [$($ex.Procedure)] Class [$($ex.Class)] " +
+ " Number [$($ex.Number)] State [$($ex.State)] )"
+ }
+ $ex = $ex | SelectObjectWithDefault -Name 'InnerException' -Value $null
+ }
+ $shortException = $lastException -join ' --> '
+
+ $header = $null
+ $current = $_
+ $header = (($_.InvocationInfo |
+ SelectObjectWithDefault -Name 'PositionMessage' -Value '') -replace "`n", ' '),
+ ($_ | SelectObjectWithDefault -Name 'Message' -Value ''),
+ ($_ | SelectObjectWithDefault -Name 'Exception' -Value '') |
+ ? { -not [String]::IsNullOrEmpty($_) } |
+ Select -First 1
+
+ $delimiter = ''
+ if ((-not [String]::IsNullOrEmpty($header)) -and
+ (-not [String]::IsNullOrEmpty($shortException)))
+ { $delimiter = ' [<<==>>] ' }
+
+ return "$($header)$($delimiter)Exception: $($shortException)"
+ }
}
function WriteDocumentation {

0 comments on commit fff5f6f

Please sign in to comment.