PaperCut Blog

Tech & DevCoding

Powershell and the PaperCut MF/NG Health API

Powershell and the PaperCut MF/NG Health API

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.

Comments