source/public/Get-ExCmdLog.ps1

Function Get-ExCmdLog {
    <#
    .SYNOPSIS
        Get Exchange Online admin audit log events
    .DESCRIPTION
 
    .EXAMPLE
        Get-ExCmdLog -searchParamHash @{StartDate='10/10/2018';EndDate='10/12/2018';ExternalAccess=$false}
 
        The example show that you created a hashtable parameter of StartDate, EndDate, and ExternalAccess
    #>

    [cmdletbinding()]
    param (
        <#
            Hashtable of valid parameters for the cmdLet Search-AdminAuditLog.
            eg. @{StartDate='10/10/2018';EndDate='10/12/2018';ExternalAccess=$false}
        #>

        [parameter()]
        [hashtable]$searchParamHash = @{
            StartDate = ((Get-Date).AddHours(-24))
            EndDate   = ((Get-Date))
        },
        [parameter()]
        [switch]$resolveAdminName
    )

    if (!(Get-PSSession | Where-Object {$_.ConfigurationName -eq 'Microsoft.Exchange'})) {
        throw "Get-ExCmdLog: Remote Exchange PowerShell session is required. Please establish a remote PowerShell session first."
    }
    Write-Verbose '.........................................'
    Write-Verbose 'Search Parameters:'
    foreach ($i in $searchParamHash.Keys) {
        Write-Verbose "$($i) = $($searchParamHash.Item($i))"
    }
    Write-Verbose '.........................................'
    $startIndex = 0
    Write-Verbose "Index: $($startIndex+1)"
    $searchParamHash += @{StartIndex = $startIndex }

    $auditLogs = Search-AdminAuditLog @searchParamHash

    if ($auditLogs.count -eq 1000) {
        Do {
            $startIndex += 1000
            $searchParamHash.StartIndex = $startIndex
            Write-Verbose "Index: $($startIndex+1)"
            $temp = Search-AdminAuditLog @searchParamHash
            if ($temp.count -gt 0) {
                $auditLogs += $temp
            }
        }
        While ($temp.count -eq 1000)
    }
    $auditLogs | Add-Member -MemberType NoteProperty -Name CallerAdminName -Value $null
    Write-Verbose "Total Events: $($auditLogs.count)"

    if ($auditLogs.count -gt 0) {
        if ($resolveAdminName) {
            Write-Verbose 'resolveAdminName is enabled. Please wait while the admin names are being resolved.'
            Write-Verbose '.........................................'
            $uniqueCallerAdminName = @()

            # Get unique caller id from the result
            $uniqueCaller = $auditLogs | Select-Object caller -Unique

            # Create a hashtable of Caller and CallerAdminName
            $uniqueCaller | ForEach-Object {
                try {
                    $CallerAdminName = (Get-User ($_.Caller) -ErrorAction Stop).Name
                }
                catch {
                    $CallerAdminName = $null
                }

                $callerObj = New-Object psobject -Property @{
                    Caller          = $_.Caller
                    CallerAdminName = $CallerAdminName
                }
                $uniqueCallerAdminName += $callerObj
            }

            foreach ($i in $auditLogs) {
                $i.CallerAdminName = ($uniqueCallerAdminName | Where-Object { $_.Caller -eq $i.Caller }).CallerAdminName
            }
        }
        # return the results
        return $auditLogs
    }
    else {
        # throw error and terminate
        throw "$($MyInvocation.MyCommand.Name): There are ZERO admin audit log entries retrieved."
    }
}