Monitor Print Server Activity

I was recently approached by management and asked to monitor an older print server to see who was still using it.  They wanted a report that would show which users and machines were still using this print server so they could correct old printer mappings.  Well of course Microsoft gives us no easy way to do this out of the box so it was time to get creative.  Here is the method I used to enable logging and generate a nice pretty TPS report from the data.

Enable Print service logging on the print server
1. Open the event viewer
2. Expand application and service logs > Microsoft > Windows > PrintService
3. Right-click the operational log, click enable log.

Now that logging is enabled you will begin to see the logs fill up with print jobs (Event 307). I let this run for about a week so we could get plenty of data. You may need to adjust the size of the log because I found it filled up way too quickly. The default is 1MB which is stupid low.
Now on to generate a pretty report for these guys. As it turns out this sounds so easy but in fact is a PITA. You can export the log to CSV but there are several issues with this, the biggest one is it exports the users SID instead of username, which of course makes sense because we all know the SID for each user right? There are also several formatting issues with exporting to CSV and long story short, it just didn’t work, you’re welcome to try that on your own if you think I am crazy. What I really needed was a way to pull the XML params out of the detail section of each event and export that to CSV. To accomplish this we turn to our friend, Powershell.

$PrinterList = @()
$StartTime = "04/10/2014 12:00:01 PM"
$EndTime = "04/18/2014 6:00:01 PM"
$Results = Get-WinEvent -FilterHashTable @{LogName="Microsoft-Windows-PrintService/Operational"; ID=307; StartTime=$StartTime; EndTime=$EndTime;} -ComputerName "localhost"

ForEach($Result in $Results){
$ProperyData = [xml][/xml]$Result.ToXml()
$PrinterName = $ProperyData.Event.UserData.DocumentPrinted.Param5
$hItemDetails = New-Object -TypeName psobject -Property @{
DocName = $ProperyData.Event.UserData.DocumentPrinted.Param2
UserName = $ProperyData.Event.UserData.DocumentPrinted.Param3
MachineName = $ProperyData.Event.UserData.DocumentPrinted.Param4
PrinterName = $PrinterName
PageCount = $ProperyData.Event.UserData.DocumentPrinted.Param8
TimeCreated = $Result.TimeCreated

$PrinterList += $hItemDetails

#Output results to CSV file
$PrinterList | Export-Csv -Path "C:PrintAudit.csv"


This script runs locally on the print server and pulls all the info I needed and dumps into a CSV that can then be fondled within excel.  Optionally, you can run this remotely by changing the –ComputerName param at the end of line 4.  Of course, you do need to modify the start and end times to your needs.

XenDesktop 7 BrowserName attribute incorrect

A user found this issue because on his mobile device (IPad) it said he was connected to an app that he did not open. Here is the scenario:

1. copy an existing app named “Calculator1″
2. Rename the copied app to “Calculator2″
3. The web interface and receivers will now show the new name. But when the user connects to calculator2 from an Ipad, goes to “switch apps” button on receiver, it will show connected to calculator1.

Looking into the problem further, I ran a Get-BrokerApplication -name calculator2.

ApplicationType : HostedOnDesktop
BrowserName : Calculator1
CommandLineExecutable : c:windowssystem32calc.exe
Name : Calculator2
PublishedName : Calculator2

This appears to be a bug in XenDesktop 7.  Whenever you copy or rename an app it does not update the BrowserName attribute to the new name.  To fix this you can run the below PowerShell script from a DDC.  This script will make the BrowserName match what is set for PublishedName for all apps in your farm/site.


Import-Module Citrix.XenDesktop.Admin
Add-PSSnapin Citrix.*
$apps = get-brokerapplication
foreach ($app in $apps){
$appname = $app.Name
Set-BrokerApplication -Name $appname -BrowserName $appname


Set DNS and Hostname on all ESXi Hosts in a Cluster

This script can be used to configure DNS settings on each host in the cluster.  It will set the DNS Server addresses and will also set the hostname to match what was used when adding it to vcenter.  If you added the host to vcenter by IP then you will want to comment that section out.

As with any VMWare script, you will need the latest version of VMWare PowerCLI installed to run this.

$Cluster = "Clustername"
$ESXHosts = Get-Cluster $Cluster | Get-VMHost

ForEach ($ESXHost in $ESXHosts){

#Set DNS Servers
Get-VMHost | Get-VMHostNetwork | Set-VMHostNetwork -DnsAddress [],[]

#Set DNS domain and search domains
Get-VMHost | Get-VMHostNetwork | Set-VMHostNetwork -Domain domain -SearchDomain,,

#Get hostname from vcenter, set Hostname
$hostnamearray = $".")
$hostname = $hostnamearray[0]
Get-VMHostNetwork -VMHost $ESXHost | Set-VMHostNetwork -HostName $hostname