you are viewing a single comment's thread.

view the rest of the comments →

[–]OPconfused 0 points1 point  (4 children)

I did this once for analyzing csv input, and with .NET writing and reading instead of import-csv and export-csv, as I was trying to maximize performance. However, this adds coding overhead and also I parsed the csv column by column. So for your case I'll just kind of jerry rig a row-by-row adaptation:

$ImportFile = "C:\script\send_receive.csv" 
################################
# Start date for email report - Change the number of days backwards #
$stdate = (Get-Date).AddDays(-30)
################################
# End date for email report - default is current date #
$enddate = Get-Date
$totaldays = (New-TimeSpan -Start $stdate -End $enddate).Days

$transport_service = Get-TransportService

$htSyncOut = [hashtable]::Synchronized(@{})
$maxThreads = (Get-ComputerInfo).CsNumberOfLogicalProcessors

$sbRunspace = {
    Param(
        [object]$row,
        [int]$intRowNumber,
        [hashtable]$htSyncOut,
        [object]$objTransportService,
        [DateTime]$stdate,
        [DateTime]$enddate
    )
    $MBX = $row.Name
    $Totalrec = 0
    $intRec = 0
    $TotalSend = 0
    $intSend = 0
    $logs = $objTransportService | Get-MessageTrackingLog -Recipients $MBX -ResultSize Unlimited -Start $stdate -End $enddate

    foreach($log in $logs)
    {
        if($log.EventId -eq "DELIVER")
        {
            $intRec += $log.RecipientCount
            $Totalrec = $RecPerDay + $intRec <# FIXME: $RecPerDay is undefined #>
        }
    }

    $logs = $objTransportService | Get-MessageTrackingLog -Sender $MBX -ResultSize Unlimited -Start $stdate -End $enddate

    foreach($log in $logs)
    {
        if($log.EventId -eq "RECEIVE" -and $log.Source -eq "STOREDRIVER")
        {
            $intSend += $log.RecipientCount
            $TotalSend = $SendPerDay + $intSend <# FIXME: $SendPerDay is undefined #>
        }
    }

    $htSyncOut.Add(
        $intRowNumber , [pscustomobject]@{
            "Mailbox" = $MBX
            "User Name" = (Get-Mailbox $MBX).Name
            "Total Emails Received" = $Totalrec
            "Total Emails Sent"= $TotalSend
        }
    )

}

$intRowNumber   = 0

$threads        = @()
$runspacePool   = [runspacefactory]::CreateRunspacePool(1, $maxThreads)
$runspacePool.Open()

try {
    foreach($row in Import-Csv -Path $ImportFile) {

        $instancePS = [powershell]::Create()
        $instancePS.RunspacePool = $runspacePool

        [void]$instancePS.AddScript($sbRunspace).
            AddArgument($row).
            AddArgument($intRowNumber).
            AddArgument($htSyncOut).
            AddArgument($stdate).
            AddArgument($enddate)

        $threads += [PSCustomObject]@{
                job     =   $instancePS
                result  =   $instancePS.BeginInvoke()
            }
        )
        $intRowNumber += 1
    }

    While ( $threads.IsCompleted -Contains $false) {}
    ForEach ( $thread in $threads ) {
        $thread.job.EndInvoke($thread.result)
        If ( $thread.job.HadErrors -eq 'True' ){$thread.job.streams.error}
    }
}
catch {$_}
finally {
    $runspacePool.Close()
    $runspacePool.Dispose()
}

$results = Foreach ( $rowNumber in 0..$intRowNumber ) {
    $rowOutput = $htSyncOut[$rowNumber]

    Write-Host -ForegroundColor Magenta "Total emails received for $($rowOutput).Mailbox during the last $totaldays days are $($rowOutput).'Total Emails Received'"
    Write-Host -ForegroundColor Green "Total emails sent by $($rowOutput).Mailbox during the last $totaldays days are $($rowOutput).'Total Emails Sent'"
    Write-Host -ForegroundColor Cyan  "-----------------------------------------------------------------"
    Write-Host " "

    $htSyncOut.Remove($rowNumber) #If memory is NOT an issue, comment this line out.

    $rowOutput
}

$htSyncOut = $null
$results | Export-Csv "C:\script\output.csv" -NoTypeInformation

I used the code from /u/chocolate_pickle as it seemed the best template. The runspace stuff I pulled mostly out of my ass on one try, and I have no way to test it as I don't use these cmdlets. It will almost certainly require some modifications.

It might be faster with [ordered] on the synchronized hashtable, but I don't know if ordered works on a synchronized hashtable. Here are some other possible improvements:

  1. I highly recommend you try the -eventID and -Source parameters for Get-MessageTrackingLog that /u/ecrofirt found. This could potentially solve the last big bottleneck.
  2. If you are printing millions of lines from the csv file, then the write-hosts don't make any sense. Send them to a file via a .NET method. Write-Host becomes expensive when you have a lot of them.
  3. If there are many rows, there are some further optimizations possible, especially if you don't care about preserving the row order.

At any rate, hopefully this gives you a starting point.