PowerShell Try, Catch, custom terminating error me

2019-05-21 07:05发布

问题:

Is there a way to customize the error message of a terminating error?

In the example below I would like to just end up with one Try section and collect all errors in one Catch section by combining both script blocks. My problem is that the $error generated by Import-csv is not descriptive enough and I would like to have the text Failed CSV-File import c:\test.csv within the $error message.

Thank you for your advise.

Script block 1

Try {
    $File = (Import-Csv -Path c:\test.csv)
}
Catch {
    throw $error[0].Exception.Message | Send-Mail $ScriptAdmin "FAILED CSV-File import"
}

Script block 2

try {
    if(!(Test-Path $LogFolder -PathType Container)) {throw "Can't find the log folder: '$LogFolder'"}
    $Credentials = Import-Credentials $UserName $PasswordFile
}
catch {
    throw $Error[0].Exception.Message | Send-Mail $ScriptAdmin "FAILURE"
}

Workaround

A possible solution would be to check first with test-path if the import file exists and then create a throw with a customized message. But I would like to know if it's possible to handle it in one line of code without using test-path first.

Best solution (thanks to mjolinor):

try {
    $File = (Import-Csv -Path $ImportFile -Header "A", "B", "C", "D" | Where { $_.A -NotLike "#*" })
    if(!(Test-Path $LogFolder -PathType Container)) {throw "Can't find the log folder: '$LogFolder'"}
    $Credentials = Import-Credentials $UserName $PasswordFile
}
catch {
    Switch -Wildcard ($Error[0].Exception)
        {
           "*$ImportFile*"
           { $FailType = "FAILED CSV-File import" }

           "*$LogFolder*"
           { $FailType = "FAILED Log folder not found" }

           "*Import-Credentials*"
           { $FailType = "FAILED Credential import" }

           Default
           { $FailType = "FAILED Unrecognized error" }

         }
       Write-Warning $Error[0].Exception.Message
       throw $Error[0].Exception.Message | Send-Mail $ScriptAdmin $FailType
}
  • Make sure that your advanced-function which you created (like Import-Credentials above) contains the function name in the throw section. So we can filter it out in the catchblock.

回答1:

Something like this, maybe?

Try {
      $File = (Import-Csv -Path c:\test.csv)

      if(!(Test-Path $LogFolder -PathType Container)) 
      { throw "Can't find the log folder: '$LogFolder'" }

      $Credentials = Import-Credentials $UserName $PasswordFile

      }

catch {
        Switch -Wildcard ($Error[0].CategoryInfo)
        {
           '*[Import-CSV]*' 
           { $FailType = 'Import CSV failed' }

           '*[Test-Path]*'
           { $FailType = 'LogFolder not found' }

           '*[Import-Credentials]*'
           { $FailType = 'Credential import failed' }

           Default
           { $FailType = 'Unrecognized error' }

         }

         $Error[0].Exception.Message | Send-Mail $ScriptAdmin $FailType

       }

Edit (for some reason I'm not able to post a comment):

I should have specified that it wasn't tested, and was intended more as a pattern than a finished solution, and it seems to have done what it was intended to do.

@BartekB - I habitually use $Error[0] instead of $_ because it seems more explicit and intuitive to read, and less likely to be misunderstood by someone less experienced who might inherit the code later.