Print server – enable auditing and log gathering script – Event ID: 307

I was asked by my friend to install print server to his environment (Windows Server 2008 R2 SP1), enable auditing of print jobs and create report on weekly basis.

  • To install print server there is very nice video: on youtube
  • After printers are installed and deployed we should enable audit of PrinterService event. logs. On the print server Open Server Manager -> Diagnostics -> Event Logs -> Applications and services Logs -> Microsoft -> Windows -> PrintService

server_manager

  • Expand PrintService event. logs -> Right click Operational
  • Make sure Disable Log is present (Otherwise click Enable Log)

Log Enabled

  • Print test pages
  • Run the following script and it will go through event. logs, collect event. ID 307 for last 168 hours and gather you CSV file with the most important info about printed documents (What, where, when and by whom was printed)
$dat = get-date
$name="$($dat.day)_$($dat.month)_$($dat.year)"
start-transcript c:\scripts\printaudit_logs\log_$name.log
#print audit script
$pserv = "PrintServerName"
$AuFileRaw = "c:\scripts\printaudit_logs\Audit.csv"
$AuFileLRD = "c:\scripts\printaudit_logs\last_run.csv"
################################# Test mode - uncomment
$dat | Out-File $AuFileLRD 
############################################################################################################################################
#read_event_log daily from current
$a = Get-WinEvent -ProviderName "Microsoft-Windows-PrintService" -ComputerName $pserv |  where {(($_.id -eq 307) -and ($_.timecreated -ge $dat.addhours(-168)))} | select Message,TimeCreated

#read event from file
#$a = Get-WinEvent -Path 'C:\Scripts\PrintAudit_logs\system log.evtx' |  where {(($_.id -eq 307))} | | select Message,TimeCreated

$lr = "DocName;user;IP;Printer;IP Port;size;pages;Date"
$lr  | Out-File $AuFileLRD -Append
foreach ($rec in $a) {
$r = $rec.message -replace " owned by ",";"
$r = $r -replace " was printed on ",";"
$r = $r -replace " on ",";"
$r = $r -replace " through port ",";"
$r = $r -replace "  Size in bytes: ",";"
$r = $r -replace ". Pages printed: ",";"
$r = $r -replace ". No user action is required.",""
$r
$out = "$($r);$($rec.timecreated)"
#saving to raw file
$out | Out-File $AuFileRaw -Append
$out | Out-File $AuFileLRD -Append
}

#saving to raw file
#generate reports
#sending mail
Stop-Transcript

Update: I made new version of the script gathering print reports for selected period. It is also faster, because I have added additional conditions to not include empty lines in reports. Here is the new version. Blue lines are subject to change to alter period, logs placement and print server name:

#Version 1.1
$dat = get-date
$name="$($dat.day)_$($dat.month)_$($dat.year)"
start-transcript c:\scripts\printaudit_logs\log_$name.log
#print audit script
$pserv = "OPHQMS01"
$AuFileRaw = "c:\scripts\printaudit_logs\Audit.csv"
$AuFileLRD = "c:\scripts\printaudit_logs\last_run.csv"
$AuFileRep = "c:\scripts\printaudit_logs\Audit_$name.html"
$smtpserver = "smtp.domain.local"
$adminrecip = "zbynek.salon@salonovi.cz"
$month = $dat.addmonths(-1) | select month
################################# Test mode - uncomment
#$dat | Out-File $AuFileLRD 
############################################################################################################################################
#read_event_log daily from current
$b = @()
$a = Get-WinEvent -ProviderName "Microsoft-Windows-PrintService" -ComputerName $pserv | select id,Message,TimeCreated
#$a = Get-WinEvent -Path 'C:\scripts12013-082013.evtx' | select id,Message,TimeCreated
foreach ($line in $a){
$b += $line |  where {(($line.id -eq 307) -and ($line.timecreated.month -eq $month.month))} | select Message,TimeCreated
}

#read event from file
$lastm = "_$($dat.addmonths(-1).month)_$($dat.year)"
#creating folder structure
Remove-Item -Recurse -Force "c:\scripts\printaudit_logs\stats$($lastm)"
new-item -ItemType Directory -path "c:\scripts\printaudit_logs\stats$($lastm)" -erroraction SilentlyContinue
new-item -ItemType Directory -path "c:\scripts\printaudit_logs\stats$($lastm)\uzivatelske" -erroraction SilentlyContinue
new-item -ItemType Directory -path "c:\scripts\printaudit_logs\stats$($lastm)\tiskarny" -erroraction SilentlyContinue

$lr = "Dokument;Uživatel;IP;Tiskárna;IPPort;Velikost;Stran;Datum"
$lr  | Out-File $AuFileLRD
$lr  | Out-File $AuFileRaw
foreach ($rec in $b) {
if ( $rec.message -notlike $null) {
	$r = $rec.message -replace " owned by ",";"
	$r = $r -replace " was printed on ",";"
	$r = $r -replace " on ",";"
	$r = $r -replace " through port ",";"
	$r = $r -replace "  Size in bytes: ",";"
	$r = $r -replace ". Pages printed: ",";"
	$r = $r -replace ". No user action is required.",""
	$out = "$($r);$($rec.timecreated)"
#saving to raw file
	$out | Out-File $AuFileRaw -Append
	$out | Out-File $AuFileLRD -Append
	}
}

#saving to raw file

#generate reports
$Rep = Import-Csv $AuFileLRD -Delimiter ";"
$psum = @()
$usum = @()
$printers = $rep | group tiskárna | select name
$users = $rep | group uživatel | select name

# user stats
foreach ($us in $users){
$uout = "c:\scripts\printaudit_logs\stats$($lastm)\uzivatelske\$($us.name)$($lastm).csv"
$x = @(); $x +=$Rep | where {$_.uživatel -like "$($us.name)"}
$usum += $x | group uživatel,tiskárna,stran | select name,count
$x | select * -excludeproperty uživatel,ip,velikost,ipport |  Export-Csv $uout -Encoding unicode -Delimiter ";"
}
# printer stats
foreach ($pr in $printers){
$prout = "c:\scripts\printaudit_logs\stats$($lastm)\tiskarny\$($pr.name)$($lastm).csv"
$x = @(); $x +=$Rep | where {$_.tiskárna -like "$($pr.name)"}
$psum += $x | group tiskárna,stran | select name,count
$x | select * -excludeproperty tiskárna,ip,velikost,ipport | Export-Csv $prout -Encoding unicode -Delimiter ";"
}
$psum =  $rep | group tiskárna | sort count -Descending | select name,count
$usum =  $rep | group uživatel,tiskárna | sort count -Descending | select name,count
#sending mail
$body = "Zdravím,

Statistiky za měsíc $($lastm) naleznete v \\ophqms01\printaudit_logs .

S pozdravem
Admin" send-mailmessage -From zbynek.salon@domain.local -To $adminrecip -Subject "Print audit" -Body $body -BodyAsHtml -Encoding ([System.Text.Encoding]::unicode) -smtpserver $smtpserver Stop-Transcript

DNS monitoring via Powershell

There is a Microsoft service called ExRAP. (Exchange health check) and one of the errors in report, provided to you as a result of ExRAP is that internal DNS records are not checked automatically on all DNS servers. I have made a script, which will do DNS records monitoring for you and in case records differs from designed values, it will send e-mail to predefined e-mail address.
Prerequisites:
You must have rights to connect to DNS server and read DNS zones using WinRM.

How it works:

  • It uses powerful Powershell module called DNS Shell (downloadable here: http://dnsshell.codeplex.com/)
  • It connects to each DNS server in organization
  • It compares predefined (designed) values from CSV file with the values read from DNS servers (A and PTR) and if values of DNS records differs, it reports an error to e-mail message
  • Comparison is based on ODD / EVEN number of same records. If ODD record is found in field of read records, it stay that record on DNS server or CSV file is incorrect.

Preparation:

  • Implement DNSShell module to Powershell on server
    Extract DnsShell.zip to one of the paths shown by $Env:PSModulePath
  • Create CSV file with the following format (For each A record one line, for each PTR record one line)

“Name”;”RecordData”
“EXSERVER2″;”192.168.196.102”
“102.196.168.192.in-addr.arpa”;”EXSERVER2.yourdomain.com.”

  • Copy script to the same location as CSV file

# To make this work extract http://dnsshell.codeplex.com/ to C:Windowsystem32WindowsPowerShellv1.0Modules
# author: Zbynek.Salon@salonovi.cz
###################################################################################
$c = $null
$server =@()
$server = “DNS1″,”DNS2″,”DNS3”
foreach ($internalserver in $server){
#internal records check
import-module DNSShell
$tocomp = $null
$tocomp = import-csv .internal.csv -delimiter “;”
$data = @()
$data +=get-addnsrecord *exserver* | select name,recorddata
$data +=Get-DnsZone -Server $internalserver | where {$_.zonename -like “168.192*“} | get-dnsrecord | where {$_.recorddata -like “*exserver*“} | select name,recorddata
#$data | export-csv .tocompare.csv -delimiter “;”
$data +=$tocomp
$out = $data | sort name | group name,recorddata
$changed = @()
foreach ($rec in $out)
{
 $ev=$null
 $ev = [bool]!($rec.count%2)
 if ($ev -eq $false)
  {
  $changed +=”$($rec.name);”
  }
}
if ($changed -ne $null){
foreach ($chan in $changed){
$c +=”DNS server: $($internalserver)- Record: $($chan);<br />”}
}
}
if ($c -ne $null){send-mailmessage -From monitoring@yourdomain.com -To administrator@yourdomain.com,another.admin@yourdomain.com -Subject “Monitored DNS records changed – please check.” -Body “Hello,<br /> <br /> The following DNS records does not match with predefined values in’\SERVERNAMEd$ExchangeScriptsDNSrecordsMonitoringinternal.csv'<br />$(foreach($q in $c){$q;'<br />’})<br /> Please check accuracy. <br /> <br /> S pozdravem / Best regards, <br /> Zbynek” -BodyAsHtml -Encoding ([System.Text.Encoding]::unicode) -smtpserver SMTP.yourdomain.com
}

  • Green text in the script is subject to change
  • Do test run
  • In case of mismatch in DNSs records e-mail message is generated (Do not forget to use open relay connector and correct smtp server)

Hello,

The following DNS records does not match with predefined values in’\SERVERNAMEd$ExchangeScriptsDNSrecordsMonitoringinternal.csv’
DNS server: DNS1-Record: EXSERVER2, 192.168.196.111;;’
‘DNS server: DNS1-Record: EXSERVER2, 192.168.196.110;;’
‘DNS server: DNS2-Record: EXSERVER2, 192.168.196.111;;’
‘DNS server: DNS2-Record: EXSERVER2, 192.168.196.110;;’
‘DNS server: DNS3-Record: EXSERVER2, 192.168.196.111;;’
‘DNS server: DNS3-Record: EXSERVER2, 192.168.196.110;;’

Please check accuracy.

S pozdravem / Best regards,
Admin

  • Plan scheduled task to run the script as often as you want