Life of a techno-guru
Wednesday, March 25, 2009
  Parsing Windows 2003 Print Logs
Here is a Powershell script that parses event log ID 10 on a Windows 2003 print server. Normally, you'll have a message that looks something like this:

Document 172, C:\Documents and Settings\Trevor\W5QZ4XUR\MyFinanceReport.pdf owned by Trevor was printed on 4thFloorHpPrinter via port IP_10.1.1.50. Size in bytes: 168123; pages printed: 2

Now, how do you get that information into a usable format? The answer lies below:

#################################################################################
# #
# Author: Trevor Sullivan #
# #
# Date: February 10th, 2009 #
# #
# Purpose: This script is meant for running against a Windows 2003 event log. #
# The verbage for the print log entries has changed for Windows Vista. #
# #
#################################################################################

Function GetPrintEntriesFromTextFile($tFileName)
{
Get-Content $tFileName
}

Function GetPrintEntriesFromServer()
{
$PrintEntries = Get-EventLog -LogName System | Where-Object { $_.EventId -eq 10 -and $_.Source -eq "Print" }
return $PrintEntries
}

# Parses username from a Windows 2003 Print log message
Function GetUserName($PrintEntry)
{
If ($PrintEntry -eq "" -or $PrintEntry -eq $null) { return $null }

$rxUserName = [regex]"owned by ([0-9a-zA-Z]{7})"
$rxUserName = [regex]"owned by ([0-9a-zA-Z]{1,}) was"
$rxMatches = $rxUserName.Match($PrintEntry)
return $rxMatches.Groups[1].Value
}

Function GetPrinterName($PrintEntry)
{
If ($PrintEntry -eq "" -or $PrintEntry -eq $null) { return $null }

#Write-Host "Parsing printer name"
$rxPrinterName = [regex]"printed on ([0-9a-zA-Z-_\s]{5,}) via"
$rxMatches = $rxPrinterName.Match($PrintEntry)
return $rxMatches.Groups[1].Value
}

Function GetPrintSize($PrintEntry)
{
If ($PrintEntry -eq "" -or $PrintEntry -eq $null) { return $null }

#Write-Host "Getting print size"
$rxPrintSize = [regex]"Size in bytes: ([0-9]+);"
$rxMatches = $rxPrintSize.Match($PrintEntry)
return $rxMatches.Groups[1].Value
}

Function GetPageCount($PrintEntry)
{
If ($PrintEntry -eq "" -or $PrintEntry -eq $null) { return $null }

#Write-Host "Getting page count"
$rxPageCount = [regex]"pages printed\: ([0-9]+)"
$rxMatches = $rxPageCount.Match($PrintEntry)
return $rxMatches.Groups[1].Value
}

Function GetDocumentName($PrintEntry)
{
If ($PrintEntry -eq "" -or $PrintEntry -eq $null) { return $null }

#Write-Host "Getting print size"
$rxDocumentName = [regex]", ([a-zA-Z-_:/\[#\]\?\\\=\d\.\s\(\)&-,]{1,}) owned by"
$rxMatches = $rxDocumentName.Match($PrintEntry)
return $rxMatches.Groups[1].Value
}

# Retrieves user's full name from AD
Function GetUserFullName($UserId)
{
if ($UserId -gt "")
{
$DirectorySearcher = New-Object System.DirectoryServices.DirectorySearcher
$LdapFilter = "(&(objectClass=user)(samAccountName=${UserId}))"
#Write-Host "Filter is: ${LdapFilter}"
$DirectorySearcher.Filter = $LdapFilter
$UserEntry = [adsi]"$($DirectorySearcher.FindOne().Path)"
#Write-Host $UserEntry.displayName
return $UserEntry.displayName
}

return
}

Function CreatePrintJob()
{
$PrintJob = New-Object PsObject
Add-Member -Force -InputObject $PrintJob -MemberType NoteProperty -Name PageCount -Value $null
Add-Member -Force -InputObject $PrintJob -MemberType NoteProperty -Name UserName -Value $null
Add-Member -Force -InputObject $PrintJob -MemberType NoteProperty -Name DocumentName -Value $null
Add-Member -Force -InputObject $PrintJob -MemberType NoteProperty -Name Size -Value $null
Add-Member -Force -InputObject $PrintJob -MemberType NoteProperty -Name Printer -Value $null
Add-Member -Force -InputObject $PrintJob -MemberType NoteProperty -Name Time -Value $null
Add-Member -Force -InputObject $PrintJob -MemberType NoteProperty -Name UserFullName -Value $null
return $PrintJob
}

Function ParsePrintEntry($PrintEntry)
{
$NewPrintJob = CreatePrintJob

if ($PrintEntry.GetType() -eq [System.String])
{
$NewPrintJob.PageCount = GetPageCount $PrintEntry
$NewPrintJob.UserName = GetUserName $PrintEntry
$NewPrintJob.DocumentName = GetDocumentName $PrintEntry
$NewPrintJob.Size = GetPrintSize $PrintEntry
$NewPrintJob.Printer = GetPrinterName $PrintEntry
$NewPrintJob.UserFullName = GetUserFullName $NewPrintJob.UserName
}
elseif ($PrintEntry.GetType() -eq [System.Diagnostics.EventLogEntry])
{
$NewPrintJob.PageCount = GetPageCount $PrintEntry.Message
$NewPrintJob.UserName = GetUserName $PrintEntry.Message
$NewPrintJob.DocumentName = GetDocumentName $PrintEntry.Message
$NewPrintJob.Size = GetPrintSize $PrintEntry.Message
$NewPrintJob.Printer = GetPrinterName $PrintEntry.Message
$NewPrintJob.Time = $PrintEntry.Time
$NewPrintJob.UserFullName = GetUserFullName $NewPrintJob.UserName
}

return $NewPrintJob
}

Function Main()
{
#$PrintEntries = GetPrintEntriesFromServer
$PrintEntries = GetPrintEntriesFromTextFile "c:\Users\i081225\Desktop\Powershell Scripts\Print Log Parser\PrintLog.txt"
$Global:ParsedEntries = @{}; $i = 0

ForEach ($PrintEntry in $PrintEntries)
{
$ParsedEntries.Add($i, $(ParsePrintEntry $PrintEntry))
#$ParsedEntries += (ParsePrintEntry $PrintEntry)
$i++

if ($i % 100 -eq 0)
{ Write-Host "Processed $i records" }
}

WriteToExcel $ParsedEntries
}

Function WriteToExcel($tEntries)
{
# Load Excel interop assembly
[Void] [Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Excel")

# Create Excel application, workbook, and worksheet objects
$Excel = New-Object Microsoft.Office.Interop.Excel.ApplicationClass
$Workbook = $Excel.Workbooks.Add()
$Worksheet = $Workbook.Worksheets.Add()

# Write Excel worksheet headers
$Worksheet.Cells.Item(1, 1).Value2 = "Username"
$Worksheet.Cells.Item(1, 2).Value2 = "Full Name"
$Worksheet.Cells.Item(1, 3).Value2 = "Time"
$Worksheet.Cells.Item(1, 4).Value2 = "Page Count"
$Worksheet.Cells.Item(1, 5).Value2 = "Printer"
$Worksheet.Cells.Item(1, 6).Value2 = "Size (bytes)"
$Worksheet.Cells.Item(1, 7).Value2 = "Document Name"
# End writing Excel worksheet headers

# Iterate over each print entry
$row = 2
ForEach ($key in $tEntries.Keys)
{
$Worksheet.Cells.Item($row, 1).Value2 = $tEntries[$key].UserName
$Worksheet.Cells.Item($row, 2).Value2 = $tEntries[$key].UserFullName
$Worksheet.Cells.Item($row, 3).Value2 = $tEntries[$key].Time
$Worksheet.Cells.Item($row, 4).Value2 = $tEntries[$key].PageCount
$Worksheet.Cells.Item($row, 5).Value2 = $tEntries[$key].Printer
$Worksheet.Cells.Item($row, 6).Value2 = $tEntries[$key].Size
$Worksheet.Cells.Item($row, 7).Value2 = $tEntries[$key].DocumentName
$row++
}

# Do some formatting
# AutoFit the columns
[Void] $Excel.ActiveCell.CurrentRegion.Columns.AutoFit()

# Add table styling and auto-filtering
[Void] $Excel.ActiveCell.CurrentRegion.Select()
$ListObject = $Excel.ActiveSheet.ListObjects.Add([Microsoft.Office.Interop.Excel.XlListObjectSourceType]::xlSrcRange, $Excel.ActiveCell.CurrentRegion, $null ,[Microsoft.Office.Interop.Excel.XlYesNoGuess]::xlYes)
$ListObject.Name = "TableData"
$ListObject.TableStyle = "TableStyleLight9"

# Show the Excel window after writing data to spreadsheet
$Excel.Visible = $true
}

Main


I hope this helps someone out there :)

-Trevor Sullivan
 
Comments:
It sounds great, exactly what I need. but it doesn't work, just returns the following error.
The term 'printlogger.ps1' is not recognized as a cmdlet, function, operable program, or script file. Verify the term a
nd try again.
At line:1 char:15
+ printlogger.ps1 <<<<
 
Post a Comment



<< Home
My life of learning various things about technology including network administration, development, and 3D design

Name:
Location: Chicago, Illinois, United States
ARCHIVES
January 2006 / February 2006 / March 2006 / May 2006 / June 2006 / July 2006 / August 2006 / September 2006 / October 2006 / November 2006 / December 2006 / January 2007 / February 2007 / March 2007 / April 2007 / May 2007 / June 2007 / August 2007 / December 2007 / January 2008 / March 2008 / April 2008 / June 2008 / July 2008 / September 2008 / December 2008 / January 2009 / February 2009 / March 2009 / May 2009 /


Powered by Blogger