It’s easy to get information from the PaperCut MF/NG Health API using the Invoke-RestMethod command
PaperCut MF/NG has a handy RESTful API that allows administrators to discover lots of useful information about the PaperCut MF/NF Application Server, and PowerShell helps glue all the data together with other APIs and sources of information.
You can find lots of information about the health API in the PaperCut NG/MF system health monitoring overview topic in the Help Centre , including examples to help you connect PaperCut MF/NG to dashboards and other tools. However, sometimes it’s useful to use the API with a local script to do something specific, and if you use the PaperCut MF/NG health API and public web services API together with some of the other handy PowerShell cmdlets , you can get really creative.
For example, here’s a simple script that creates a short html report with basic information about PaperCut MF/NG Windows services and the Application Server. One important note is that I have built and installed the PaperCut ServerCommandProxy library so I can also use the
web services API
. This is a step up from using the server-command
utility described in my previous PowerShell
blog post
— you can find information on how to build and use the library in the Administering PaperCut with PowerShell knowledge base
article
. You should probably look at those first.
# Report some simple PaperCut MF/NF information
# Setup and use the PaperCut web services API. More information at
# https://www.papercut.com/kb/Main/AdministeringPaperCutWithPowerShell
Add-Type -Path "$env:USERPROFILE\.nuget\packages\kveer.xmlrpc\1.1.1\lib\netstandard2.0\Kveer.XmlRPC.dll"
Add-Type -Path "$PWD\bin\Release\netstandard2.0\ServerCommandProxy.dll"
# Create a proxy object so we can call web services API XML-RPC methods
$s = New-Object PaperCut.ServerCommandProxy("localhost",9191,"token")
# Find the value of the Auth key in the PaperCut MF/NG config database
$authString = $s.GetConfigValue("health.api.key")
# Set up the http header for the health API
$headers = @{'Authorization' = $authString}
$uri = [Uri]"http://localhost:9191/api/health"
# Generate the report
&{
# Get a list of the processes running
Get-Service -DisplayName *PaperCut* | Select-Object -Property name,status |
ConvertTo-Html -Fragment -PreContent '<h2>PaperCut Processes</h2>'
$rsp = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers
$rsp.applicationServer.systemInfo |
ConvertTo-Html -As List -Fragment -PreContent '<h2>PaperCut Services Info</h2>'
Write-Output "<p>Total Printers = $($rsp.printers.count)</p>"
Write-Output "<p>Total Devices = $($rsp.devices.count)</p>"
} | Out-File -FilePath .\report1.html
Invoke-Expression .\report1.html
On my machine my browser opens and I see this:
[]
Let’s find out something about those printers. There are a couple of ways of doing that …
Get all the data at once (assuming $uri and and $headers are set up as per previous example)
Invoke-RestMethod -Uri "$uri/printers" -Method Get -Headers $headers | ConvertTo-Json
So one thing seems a bit strange — The health API already returns JSON. Why do we need to convert it to JSON again with the ConvertTo-Json
cmdlet?
The reason is that the Invoke-RestMethod cmdlet converts the JSON returned by the PaperCut MF/NG health API into a PSObject, which is not great for display purposes (a lot of the information gets truncated on my system) so to display the JSON, as documented in the PaperCut MF/NG help centre, it needs to be converted back to JSON.
When I run the pipeline above on my machine I get the following output (assuming that $uri
and $headers
still have the correct values):
{
"printers": [
{
"name": "l-alecc\\HP Photosmart 5520 series (Network)",
"status": "OK",
"heldJobsCount": 0,
"physicalPrinterId": "local://l-alecc/CN27B1913105ST"
},
{
"name": "l-alecc\\Muratec MFX-35x0 PCL6",
"status": "OK",
"heldJobsCount": 0,
"physicalPrinterId": "net://10.100.64.84/LPR"
},
{
"name": "l-alecc\\RISO ComColor GD9630",
"status": "OK",
"heldJobsCount": 0,
"physicalPrinterId": "net://10.100.63.78"
}
],
"heldJobCountTotal": 0,
"heldJobsCountMax": 0
}
But let’s go back to using the PSObject
and skip ConvertTo-Json
. We can then access the object attributes as follows:
(Invoke-RestMethod -Uri "$uri/printers" -Method Get -Headers $headers).printers
Which returns the array of printer information:
name status heldJobsCount physicalPrinterId
---- ------ ------------- -----------------
l-alecc\HP Photosmart 5520 series (Network) OK 0 local://l-alecc/CN27B1913105ST
l-alecc\Muratec MFX-35x0 PCL6 OFFLINE 0 net://10.100.64.84/LPR
l-alecc\RISO ComColor GD9630 OK 0 net://10.100.63.78
or
(Invoke-RestMethod -Uri "$uri/printers" -Method Get -Headers $headers).heldJobCountTotal
which returned the number 0
when I ran it.
So you can now process health API data as native PowerShell object. In fact if you use my tip from the previous blog post you try this:
Invoke-RestMethod -Uri "$uri/printers" -Method Get -Headers $headers | Get-Member
returns
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
heldJobCountTotal NoteProperty long heldJobCountTotal=0
heldJobsCountMax NoteProperty long heldJobsCountMax=0
printers NoteProperty Object[] printers=System.Object[]
and
(Invoke-RestMethod -Uri "$uri/printers" -Method Get -Headers $headers).printers| Get-Member
returns
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
heldJobsCount NoteProperty long heldJobsCount=0
name NoteProperty string name=l-alecc\HP Photosmart 5520 series (Network)
physicalPrinterId NoteProperty string physicalPrinterId=local://l-alecc/CN27B1913105ST
status NoteProperty string status=OK
Now you can use your PowerShell command line fu to slice and dice the data to your heart’s content, especially if you combine it with information from the PaperCut MF/NG web services API and other PowerShell cmdlets.
Here is the complete script (bit more compact than the first example):
# Setup and use the PaperCut web services API
Add-Type -Path "$env:USERPROFILE\.nuget\packages\kveer.xmlrpc\1.1.1\lib\netstandard2.0\Kveer.XmlRPC.dll"
Add-Type -Path "$env:USERPROFILE\PaperCut\ServerCommandProxy\bin\Release\netstandard2.0\ServerCommandProxy.dll"
$s = New-Object PaperCut.ServerCommandProxy("localhost",9191,"token")
# Set up the http header for the health API
$headers = @{'Authorization' = $s.GetConfigValue("health.api.key")}
$uri = [Uri]"http://localhost:9191/api/health"
Invoke-RestMethod -Uri "$uri/printers" -Method Get -Headers $headers | Write-Output
Save this in a file listPrinterInfo.ps1
for instance and you can run command like:
(.\listPrintersInfo.ps1).printers
Got any feedback or suggestions? Let us know in the comments below.