Author Posts

March 26, 2018 at 1:29 pm

Hi All,

When using $_.Exception.Message to capture an error message within a TRY / CATCH I notice that the error from say an Exchange Commandlet is very different to what is captured by the $_.Exception.Message.

How do I allow ALL errors to be included and logged in my TRY /CATCH loop.

THanks

Stuart

March 26, 2018 at 1:50 pm

There are hundreds of different classes of Exchange messages. How do I catch them all?

March 26, 2018 at 2:27 pm

Example error message:

Cannot bind argument to parameter 'Identity' because it is null.
    + CategoryInfo          : InvalidData: (:) [Get-MailboxStatistics], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Get-MailboxStatistics
    + PSComputerName        : sh-vm-exch-01

Example TRY / CATCH

catch
                {
                $msg = $_.CategoryInfo.TargetName
                Write-Log -Code Error -CatchIndex 002 -ErrorMessage $msg
                }


Function Write-Log ([string]$Code,[string]$ObjectGuid,[string]$DisplayName,[string]$ErrorMessage,[string]$FriendlyText,[String]$CatchIndex) {

    If ($Code -eq "SUCCESS") {
        Write-Host "[SUCCESS]`t $($FriendlyText) `t ObjectGuid $($ObjectGuid) `t DisplayName $($DisplayName)" -ForegroundColor Green
        "[SUCCESS]`t $($FriendlyText) `t $($ObjectGuid) `t DisplayName $($DisplayName)`n"| Out-File $Log -Append  }

    If ($Code -eq "ERROR") {
        Write-Host "[ERROR]`t $CatchIndex ObjectGuid $($ObjectGuid) `t DisplayName $($DisplayName) ErrorMessage: $errorMessage" -BackgroundColor Red
        "[ERROR]`t`t CATCHINDEX: $CatchIndex`t`t $errorMessage`n"| Out-File $Log -Append  }
        }

March 26, 2018 at 4:26 pm

This seems to work:

 catch
                {
                $Name = $ADUser.name
                $GUID = $ADuser.ObjectGUID
                $DN = $ADuser.DistinguishedName
                $msg1 = $_.CategoryInfo.TargetName
                $msg2= $_.Exception.Message
                Write-Log -Code Error -CatchIndex 004 -ErrorMessage1 $msg1 -ErrorMessage2 -$msg2 -GUID $GUID -Name $Name -DN $DN
                }

But crude, but gets the job done

March 26, 2018 at 4:42 pm

As you found, you can catch everything using a non-specific catch clause. A slightly tidier way to have your function called and values passed in here would definitely take advantage of splatting:

$LoggingData = @{
    Name = $ADUser.name
    GUID = $ADuser.ObjectGUID
    DN = $ADuser.DistinguishedName
    msg1 = $_.CategoryInfo.TargetName
    msg2= $_.Exception.Message
    Code = 'Error'
    CatchIndex = 004
}
Write-Log @LoggingData

March 27, 2018 at 8:12 am

Thanks for the advice. I'll incorporate that.

One question, just as I thought I had provided a decent catch, I saw yet another error message which was not within the scope of $_.CategoryInfo.TargetName or $_.Exception.Message.

The only way I know how to include it is to debug the code and then just see what $_. variables exist at the time of the error. Seems pretty long winded, is there a better approach?

Many Thanks

Stuart

March 27, 2018 at 1:05 pm

Hi, I tried this CATCH:

 }
                    catch
                    { #CATCH002 FN-PM

                    $LoggingData =
                    @{

                        Name = $ADUser.name
                        GUID = $ADuser.ObjectGUID
                        DN = $ADuser.DistinguishedName
                        TargetName = $_.CategoryInfo.TargetName
                        Exception= $_.Exception.Message
                        Error0=$Error[0]
                        Error1=$Error[1]
                        Error2=$Error[2]
                        Code = 'Error'
                        TryIndex = '002 FN-PM'

                    }#End Splat

                    [Array]$Invocation= $_.InvocationInfo
                    Write-Log -ErrorData $LoggingData -InvocationError $Invocation
                    } #END #CATCH 002 FN-PM

Here is the log function:

Function Write-Log ([Array]$SuccessData,[array]$ErrorData,[Array]$InvocationError) {

    If ($SuccessData.Code -eq "SUCCESS") {
        Write-Host "[SUCCESS]`t $($SuccessData.FriendlyText) `t ObjectGuid $($SuccessData.GUID) `t DisplayName $($SuccessData.DisplayName)" -ForegroundColor Green
        "[SUCCESS]`t $($SuccessData.FriendlyText) `t $($SuccessData.GUID) `t DisplayName $($SuccessData.DisplayName)`n"| Out-File $Log -Append  }

    If ($ErrorData.Code -eq "ERROR") {
        Write-Host "[ERROR]`t TRY Index: $($ErrorData.TryIndex) Name: $($ErrorData.Name) TargetName: $($ErrorData.TargetName) Exception: $($ErrorData.Exception)" -BackgroundColor Red
        "[ERROR]`t TRY Index: $($ErrorData.TryIndex) ObjectGuid: $($ErrorData.GUID) Name: $($ErrorData.Name)`t TargetName: $($ErrorData.TargetName) Exception: $($ErrorData.Exception)" | Out-File $Log -Append
        "[ERROR]`t TRY Index: $($ErrorData.TryIndex) ObjectGuid: $($ErrorData.GUID) Name: $($ErrorData.Name) DN: $($ErrorData.DN)`t TargetName: $($ErrorData.TargetName) Exception:  $($ErrorData.Exception) Error0: $($ErrorData.Error0) Error1: $($ErrorData.Error1) Error2: $($ErrorData.Error2)" | Out-File $ErrorLog -Append
         $invocation | Out-File $ErrorLog -Append }
        }

Seems to work quite well. So this now seems to capture ALL errors, however it still dumps the errors out onto the screen which is really messy. How can I suppress that?

Also at the start I have put $ErrorActionPreference = 'SilentlyContinue' which in theory should stop the CATCH portion from working as the commendlets wont 'terminate' when they error, however it seems to work still, not sure why.

If I set $ErrorActionPreference = 'Stop' then the script fails as soon as one terminating error is detected. I think I am misunderstanding how TRY/CATCH works despite reading many articles about it.

Below is the full code in case it helps

Thanks

Stuart

$ScriptInfo = @"
================================================================================
Export-MailboxMigrationDetails.ps1 | v1.0.0
by Stuart Hendry
================================================================================
SAMPLE SCRIPT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
"@

#==========================Creating variables and paths==========================#
$ErrorActionPreference = 'SilentlyContinue'
$path=Test-Path c:\O365Reports
If ($path -like "False") {md c:\O365Reports} else {}
$second=(get-date).Second
$minute=(get-date).Minute
$hour=(get-date).Hour
$day=(get-date).Day
$month=(get-date).Month
$year=(get-date).Year
$time="$hour.$minute.$second"
$ReportPreText="AllMailboxSummary"
$DMY="$day.$Month.$year"
$report="$ReportPreText-$DMY-$time"
$Reportx=@()
$log="c:\O365Reports\$DMY-$Time-log.txt"
$ErrorLog="c:\O365Reports\$DMY-$Time-Errorlog.txt"
$i=0

$IncludeMailboxAccess = $true
$IncludeSendAs = $true
$IncludeSendOnBehalf = $true
$IncludeFolderDelegates = $true
$IncludeCommonFoldersOnly = $true
$DelegatesToSkip = "NT AUTHORITY\SELF","DOMAIN\BESADMIN","DOMAIN\Administrators"
$IncludeSecurityGroups = $True
$ExpandDistributionGroups = $false
$hash = @{} #This hash table is used by the Check-Delegates function



#==========================Functions==========================#

Function Connect-OnPremiseExchange{ 

    #Connects to Exchange On Premise, this will revive any existing sessions
    #Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File "C:\O365Reports\EXpassword.txt"
    $ComputerName = '*****' 
    $password=get-content "C:\O365Reports\EXpassword.txt" | ConvertTo-SecureString
    $userid='******'
    $UserCredential=New-Object System.Management.Automation.PSCredential $userid,$password

    $Sessions = @( Get-PSSession | Where-Object {
    ( $_.computername -EQ $ComputerName ) -AND ( $_.State -EQ 'Opened' ) } )

    If ( $Sessions )
    {
    If ( $Sessions.Count -GT 1 )
    {
        $Session   = $Sessions | Select-Object -First 1
        $LeftOvers = $Sessions | Where-Object { -Not ( $_.Id -EQ $Session.Id ) }
        $LeftOvers | Remove-PSSession -ErrorAction SilentlyContinue | Out-Null
    }

    Else { $Session = $Sessions }
    }
    Else
    {
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://$ComputerName/PowerShell/ -Authentication Kerberos -Credential $UserCredential # Create new session.
    }

    Import-PSSession $Session[0] -AllowClobber # Use this.
 } # Close Function

Function Write-Log ([Array]$SuccessData,[array]$ErrorData,[Array]$InvocationError) {

    If ($SuccessData.Code -eq "SUCCESS") {
        Write-Host "[SUCCESS]`t $($SuccessData.FriendlyText) `t ObjectGuid $($SuccessData.GUID) `t DisplayName $($SuccessData.DisplayName)" -ForegroundColor Green
        "[SUCCESS]`t $($SuccessData.FriendlyText) `t $($SuccessData.GUID) `t DisplayName $($SuccessData.DisplayName)`n"| Out-File $Log -Append  }

    If ($ErrorData.Code -eq "ERROR") {
        Write-Host "[ERROR]`t TRY Index: $($ErrorData.TryIndex) Name: $($ErrorData.Name) TargetName: $($ErrorData.TargetName) Exception: $($ErrorData.Exception)" -BackgroundColor Red
        "[ERROR]`t TRY Index: $($ErrorData.TryIndex) ObjectGuid: $($ErrorData.GUID) Name: $($ErrorData.Name)`t TargetName: $($ErrorData.TargetName) Exception: $($ErrorData.Exception)" | Out-File $Log -Append
        "[ERROR]`t TRY Index: $($ErrorData.TryIndex) ObjectGuid: $($ErrorData.GUID) Name: $($ErrorData.Name) DN: $($ErrorData.DN)`t TargetName: $($ErrorData.TargetName) Exception:  $($ErrorData.Exception) Error0: $($ErrorData.Error0) Error1: $($ErrorData.Error1) Error2: $($ErrorData.Error2)" | Out-File $ErrorLog -Append
         $invocation | Out-File $ErrorLog -Append }
        }

Function Check-Delegates ([string]$DelegateID,[string]$objectguid,[string]$DisplayName,[string]$DelegateAccess) {
    $CheckDelegate = Get-Recipient $DelegateID -ErrorAction SilentlyContinue

    If ($CheckDelegate -eq $null) {
        $CheckDelegate = Get-Group $DelegateID -ErrorAction SilentlyContinue }

    If ($CheckDelegate -ne $null) {
        If (($CheckDelegate.RecipientType -like "Mail*" -and $IncludeDistributionGroups -eq $false) -or $CheckDelegate.RecipientType -like "*Mailbox") {
            $DelegateName = $CheckDelegate.Name
            $DelegateEmail = $CheckDelegate.PrimarySmtpAddress

            $obj=new-object System.Object
            $obj|add-member -membertype NoteProperty -name "ObjectGuid" -value "$objectguid"
            $obj|add-member -membertype NoteProperty -name "ExchangeGuid" -value ""
            $obj|add-member -membertype NoteProperty -name "SamAccountName" -value ""
            $obj|add-member -membertype NoteProperty -name "UserPrincipalName" -value ""
            $obj|add-member -membertype NoteProperty -name "DisplayName" -value "$DisplayName"
            $obj|add-member -membertype NoteProperty -name "Company" -value ""
            $obj|add-member -membertype NoteProperty -name "Department" -value ""
            $obj|add-member -membertype NoteProperty -name "JobTitle" -value ""
            $obj|add-member -membertype NoteProperty -name "PrimarySmtpAddress" -value ""
            $obj|add-member -membertype NoteProperty -name "Database" -value ""
            $obj|add-member -membertype NoteProperty -name "ItemCount" -value ""
            $obj|add-member -membertype NoteProperty -name "TotalItemSize" -value ""
            $obj|add-member -membertype NoteProperty -name "ArchiveItemCount" -value ""
            $obj|add-member -membertype NoteProperty -name "ArchiveTotalItemSize" -value ""
            $obj|add-member -membertype NoteProperty -name "CombinedTotalSize" -value ""
            $obj|add-member -membertype NoteProperty -name "EA1" -value ""
            $obj|add-member -membertype NoteProperty -name "EA2" -value ""
            $obj|add-member -membertype NoteProperty -name "EA3" -value ""
            $obj|add-member -membertype NoteProperty -name "EA4" -value ""
            $obj|add-member -membertype NoteProperty -name "EA5" -value ""
            $obj|add-member -membertype NoteProperty -name "LastLogonDate" -value ""
            $obj|add-member -membertype NoteProperty -name "RecipientType" -value ""
            $obj|add-member -membertype NoteProperty -name "RecipientTypeDetails" -value ""
            $obj|add-member -membertype NoteProperty -name "DelegateName" -value $DelegateName
            $obj|add-member -membertype NoteProperty -name "DelegateEmail" -value $DelegateEmail
            $obj|add-member -membertype NoteProperty -name "DelegateAccess" -value $DelegateAccess
 
            Build-Report -obj $obj
            
            }

        If ($CheckDelegate.RecipientType -like "*Group") {
            Write-Log "ALERT: Group [$($CheckDelegate.Name)] found as delgate of $($DisplayName)."
                    $DelegateName = $DelegateID + ":" + $CheckMember.Name
                    $DelegateEmail = $CheckMember.PrimarySmtpAddress

            $obj=new-object System.Object

            $obj|add-member -membertype NoteProperty -name "ObjectGuid" -value "$objectguid"

            $obj|add-member -membertype NoteProperty -name "ExchangeGuid" -value ""

            $obj|add-member -membertype NoteProperty -name "SamAccountName" -value ""

            $obj|add-member -membertype NoteProperty -name "UserPrincipalName" -value ""

            $obj|add-member -membertype NoteProperty -name "DisplayName" -value "$DisplayName"

            $obj|add-member -membertype NoteProperty -name "Company" -value ""

            $obj|add-member -membertype NoteProperty -name "Department" -value ""

            $obj|add-member -membertype NoteProperty -name "JobTitle" -value ""
                           
            $obj|add-member -membertype NoteProperty -name "PrimarySmtpAddress" -value ""

            $obj|add-member -membertype NoteProperty -name "Database" -value ""

            $obj|add-member -membertype NoteProperty -name "ItemCount" -value ""

            $obj|add-member -membertype NoteProperty -name "TotalItemSize" -value ""

            $obj|add-member -membertype NoteProperty -name "ArchiveItemCount" -value ""

            $obj|add-member -membertype NoteProperty -name "ArchiveTotalItemSize" -value ""

            $obj|add-member -membertype NoteProperty -name "CombinedTotalSize" -value ""

            $obj|add-member -membertype NoteProperty -name "EA1" -value ""

            $obj|add-member -membertype NoteProperty -name "EA2" -value ""

            $obj|add-member -membertype NoteProperty -name "EA3" -value ""

            $obj|add-member -membertype NoteProperty -name "EA4" -value ""

            $obj|add-member -membertype NoteProperty -name "EA5" -value ""

            $obj|add-member -membertype NoteProperty -name "LastLogonDate" -value ""

            $obj|add-member -membertype NoteProperty -name "RecipientType" -value ""

            $obj|add-member -membertype NoteProperty -name "RecipientTypeDetails" -value ""
            
            $obj|add-member -membertype NoteProperty -name "DelegateName" -value $DelegateName

            $obj|add-member -membertype NoteProperty -name "DelegateEmail" -value $DelegateEmail

            $obj|add-member -membertype NoteProperty -name "DelegateAccess" -value $DelegateAccess
 
            Build-Report -obj $obj
                    } } 

  
 }

Function Process-Mailboxes { #FN-PM

[cmdletbinding()]
param([string]$Name)



        Get-Mailbox -ResultSize 1000 |?{!($_.DisplayName -like "*Discovery S*")} | select identity,DisplayName,DistinguishedName,guid,ExchangeGuid,ArchiveGuid,SamAccountName,UserprincipalName,DisplayName,PrimarySmtpAddress,Database,ServerName,RecipientType,RecipientTypeDetails| foreach-object{
        #Begin ForLoop

          #Try{ #TRY001 FN-PM


            
            #*** Increment Counters and Write to Screen
            $i++
            Write-Host "$($i) Mailbox(s) processed . . ."

            #*** Gather AD and Mailbox Attributes and send to reporting function ***

            $ADUser=(Get-ADUser $_.guid -Properties department,company,title,lastlogondate,extensionAttribute1,extensionAttribute2,extensionAttribute3,extensionAttribute4,extensionAttribute5)
            $Department=$Aduser.department
            $Company=$ADUser.company
            $JobTitle=$aduser.title
            $LastLogonDate=$Aduser.LastLogonDate
            $EA1=$Aduser.extensionAttribute1
            $EA2=$Aduser.extensionAttribute2
            $EA3=$Aduser.extensionAttribute3
            $EA4=$Aduser.extensionAttribute4
            $EA5=$Aduser.extensionAttribute5
            
            #*** Start Hash System Object for Report ***

            $obj=new-object System.Object
            $obj|add-member -membertype NoteProperty -name "ObjectGuid" -value $_.Guid
            $obj|add-member -membertype NoteProperty -name "ExchangeGuid" -value $_.ExchangeGuid
            $obj|add-member -membertype NoteProperty -name "SamAccountName" -value $_.SamAccountName
            $obj|add-member -membertype NoteProperty -name "UserPrincipalName" -value $_.UserPrincipalName
            $obj|add-member -membertype NoteProperty -name "DisplayName" -value $_.DisplayName
            $obj|add-member -membertype NoteProperty -name "Company" -value $Company
            $obj|add-member -membertype NoteProperty -name "Department" -value $Department
            $obj|add-member -membertype NoteProperty -name "JobTitle" -value $JobTitle
            $obj|add-member -membertype NoteProperty -name "PrimarySmtpAddress" -value $_.PrimarySMTPAddress
            $obj|add-member -membertype NoteProperty -name "Database" -value $_.Database
            $obj|add-member -membertype NoteProperty -name "EA1" -value $EA1
            $obj|add-member -membertype NoteProperty -name "EA2" -value $EA2
            $obj|add-member -membertype NoteProperty -name "EA3" -value $EA3
            $obj|add-member -membertype NoteProperty -name "EA4" -value $EA4
            $obj|add-member -membertype NoteProperty -name "EA5" -value $EA5
            $obj|add-member -membertype NoteProperty -name "LastLogonDate" -value $LastLogonDate
            $obj|add-member -membertype NoteProperty -name "RecipientType" -value $_.RecipientType
            $obj|add-member -membertype NoteProperty -name "RecipientTypeDetails" -value $_.RecipientTypeDetails

            #*** Gather Mailbox Statistics Attributes ***

                Try{ #TRY002 FN-PM

                    $ItemCount=(Get-MailboxStatistics -Identity $_.DisplayName).ItemCount
                    $TotalItemSize=(Get-MailboxStatistics -Identity $_.DisplayName).totalitemsize.value.ToMB()
                    $obj|add-member -membertype NoteProperty -name "ItemCount" -value $ItemCount
                    $obj|add-member -membertype NoteProperty -name "TotalItemSize" -value $TotalItemSize

                    }
                    catch
                    { #CATCH002 FN-PM

                    $LoggingData =
                    @{

                        Name = $ADUser.name
                        GUID = $ADuser.ObjectGUID
                        DN = $ADuser.DistinguishedName
                        TargetName = $_.CategoryInfo.TargetName
                        Exception= $_.Exception.Message
                        Error0=$Error[0]
                        Error1=$Error[1]
                        Error2=$Error[2]
                        Code = 'Error'
                        TryIndex = '002 FN-PM'

                    }#End Splat

                    [Array]$Invocation= $_.InvocationInfo
                    Write-Log -ErrorData $LoggingData -InvocationError $Invocation
                    } #END #CATCH 002 FN-PM
                

            #Check if the mailbox has an archive & Gather stats if exists

            if(($_.ArchiveGuid -ne "00000000-0000-0000-0000-000000000000")){

                Try{ #TRY003 FN-PM

                    $ArchiveItemCount=(Get-MailboxStatistics -Identity $_.DisplayName -Archive).ItemCount
                    $ArchiveTotalItemSize=(Get-MailboxStatistics –identity $_.DistinguishedName -Archive).totalitemsize.value.ToMB()
                    $obj|add-member -membertype NoteProperty -name "ArchiveItemCount" -value $ArchiveItemCount
                    $obj|add-member -membertype NoteProperty -name "ArchiveTotalItemSize" -value $ArchiveTotalItemSize

                    }
                    catch
                    { #CATCH003 FN-PM

                    $LoggingData = #Begin Splat
                    @{

                        Name = $ADUser.name
                        GUID = $ADuser.ObjectGUID
                        DN = $ADuser.DistinguishedName
                        TargetName = $_.CategoryInfo.TargetName
                        Exception= $_.Exception.Message
                        Error0=$Error[0]
                        Error1=$Error[1]
                        Error2=$Error[2]
                        Code = 'Error'
                        TryIndex = '003'

                    } #End Splat

                    [Array]$Invocation= $_.InvocationInfo
                    Write-Log -ErrorData $LoggingData -InvocationError $Invocation

                    } #END Catch003 FN-PM

            } #END IF (ArchiveGUID)

            $CombinedTotal=$TotalItemSize+$ArchiveTotalItemSize
            $obj|add-member -membertype NoteProperty -name "CombinedTotalSize" -value $CombinedTotal

            # *** These three are added so that the $obj template first committed to the log file report
            # *** by Build-Report has all headings added.  Later the Check-Delegates function will add these
            # *** three headings.  If they werent first added here then Check-Delegates could not subsequently 
            # *** add them in. 
            
            $obj|add-member -membertype NoteProperty -name "DelegateName" -value ""
            $obj|add-member -membertype NoteProperty -name "DelegateEmail" -value ""
            $obj|add-member -membertype NoteProperty -name "DelegateAccess" -value ""

            #*** Sends $OBJ array to the Build-Report function**

            Build-Report -Obj $obj

            # *** Export mailbox access permissions and log ***

            If ($IncludeMailboxAccess -eq $true) {

                $SuccessData=
                @{
                    Code="SUCCESS"
                    GUID=$_.Guid
                    DisplayName=$_.displayname
                    FriendlyText="Interrogating Mailbox:"

                 } #END Splat

                # *** Send to Log Function ***

                Write-Log $SuccessData

                $Delegates = @()
                $Delegates = (Get-MailboxPermission $_.DistinguishedName | Where { $DelegatesToSkip -notcontains $_.User -and $_.IsInherited -eq $false })
                    If ($Delegates -ne $null) {
                        ForEach ($Delegate in $Delegates) {
                            $DelegateAccess = $Delegate.AccessRights
                            Check-Delegates -DelegateID $Delegate.User -objectguid $_.guid -DisplayName $_.Displayname -DelegateAccess $DelegateAccess

                            } #END ForEach

                    } #END IF (Delegates)
              
            } #END IF (MailboxAccess Check)

      
        } #END ForLoop

    

} #END Function   

Function Build-Report{

    [CmdletBinding()]

Param(
    [Parameter(Mandatory=$False)]   
    [Array]$Obj,
    [Parameter(Mandatory=$False)]
    [String]$WriteToLog,
    [Parameter(Mandatory=$False)]
    [String]$ReceiveDelegates,
    [Parameter(Mandatory=$False)]
    [String]$PlaceHolder4,
    [Parameter(Mandatory=$False)]
    [String]$PlaceHolder5,
    [Parameter(Mandatory=$False)]
    [String]$PlaceHolder6,
    [Parameter(Mandatory=$False)]
    [String]$PlaceHolder7,
    [Parameter(Mandatory=$False)]
    [String]$PlaceHolder8,
    [Parameter(Mandatory=$False)]
    [String]$PlaceHolder9)

    TRY{
            #*** Building Report ***


            $obj|export-csv c:\O365Reports\$report.csv -Append

                }
                catch
                {
                $LoggingData =
                @{
                    Name = $ADUser.name
                    GUID = $ADuser.ObjectGUID
                    DN = $ADuser.DistinguishedName
                    TargetName = $_.CategoryInfo.TargetName
                    Exception= $_.Exception.Message
                    Error0=$Error[0]
                    Error1=$Error[1]
                    Error2=$Error[2]
                    Code = 'Error'
                    TryIndex = '004'
                }

                [Array]$Invocation= $_.InvocationInfo
                Write-Log -ErrorData $LoggingData -InvocationError $Invocation

                }

}

#==========================Script Body==========================#

Connect-OnPremiseExchange

Process-Mailboxes


March 27, 2018 at 3:58 pm

So, when catching an error, you'll get an ErrorRecord object: https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.errorrecord?view=powershellsdk-1.1.0

That page lists all the properties. Most commonly utilised is the Exception property, which contains an Exception-type object, with a specific type name based on how it was generated. https://msdn.microsoft.com/en-us/library/system.exception(v=vs.110).aspx

That page has a full list of all .NET exception types, but many custom types exist and are frequently in use in various code libraries, and I believe PowerShell itself also has some custom Exceptions built in. All exceptions generally have the same properties, though, and you can get whichever ones you deem relevant from that list and include those.

That said... Generally speaking, the most useful bits of information that I've found are:

$_.TargetObject
$_.ErrorDetails
$_.Exception
$_.Exception.Message
$_.Exception.InnerException

Do note that InnerException is itself another exception type, and may not always be present. As such, it has its own Message property as well. You can test for its existence using:

if ($_.Exception.InnerException) {}

And InnerExceptions themselves may also have their own inner exceptions, stacking all the way down to the very root cause of the error. However, in the vast, vast majority of cases, one or two levels deep is all that is useful. The surface level exceptions generally tell you what's actually going wrong, and the rest are mainly just technical errors caused by what you did wrong.

In large part, most of this isn't super necessary. Logging all of it is often a waste of time and disk space, so in most cases I'd recommend just taking the top-level exception and message, the error details, and the target object.

March 29, 2018 at 8:50 am

I put in a option to turn off more detailed logging as you were right, it started to chew up a lot of disk!