TL;DR: If you have scripts that run server-command
on a regular basis, then consider using the Public web services API instead. You’ll get a five to ten times speedup, and it’s more powerful! This post discusses the PowerShell environment, but the information is relevant to other scripting and programming languages as well.
Introduction
The PaperCut MF/NG public web services API is the most widely used way to access the PaperCut Application Server using a script or program and it’s used for a wide variety of automation and integration purposes,
There are two ways to access the public API:
- With the
server-command
utility - Calling the public web services API using XML-RPC
This blog post explains some of the differences between the two and why you would use one over the other.
server-command
is a useful tool, but does suffer a number of limitations.
- When running multiple commands, performance is slow because each command results in the creation of a Java virtual machine to make the API connection (
server-command
is written in Java) - The utility only runs on the PaperCut application server system and you can’t copy the binary to another system. There are some workarounds , but they are not very elegant in my opinion.
- Because of the limitations of the command line when passing complex parameters, not all API calls can be used via
server-command
(e.g.setUserProperties()
– not to be confused withsetUserProperty()
) server-command
must be run under elevated privileges (userpapercut
on Linux orAdministrator
on Windows).
Using the XML-RPC based public web services API overcomes all of the limitations listed above.
- It runs approximately 5-10 times faster than
server-command
- You can connect from any machine to the application server, although extra security setup is required
- You can get access to all the API calls and features, for example
generateAdHocReport()
- The public API client program can run as any user. Security comes from the fact that the client must provide a secure secret on each API call and the client IP address must be whitelisted in the PaperCut MF/NG server.
The downside is that it’s more complex to use and you will need to write a client that can make XML-RPC calls to the server. However, for Java and .NET languages we provide a proxy to do some of the heavy lifting for you and PowerShell can also use the .NET support.
Examples
To see the difference in performance let’s look at some tests I ran on my laptop. Here I am creating 100 new internal user accounts:
- Using
server-command
: 2.1 minutes - Calling the public API: 0.14 minutes
The commands used to generate these numbers were:
measure-command {1..100 | ForEach-Object {pc-sc add-new-internal-user server-command-$_ password}}
and
measure-command {1..100 | ForEach-Object {$s.AddNewInternalUser("web-api-$_", "password","","","","")}}
For background information on how to use server-command
in PowerShell see
Handy PowerShell hacks for PaperCut MF/NG
and on calling the public API from PowerShell refer to
Administering PaperCut with PowerShell
.
server-command
does have the benefit that it’s simple to use and does not need much setup. For example, here’s a PowerShell script that swaps the primary and secondary card number for ALL users in the PaperCut system:
pc-sc list-user-accounts | Foreach-Object {
$primary=(pc-sc get-user-property $_ "secondary-card-number")
$secondary=(pc-sc get-user-property $_ "primary-card-number")
pc-sc set-user-property $_ "primary-card-number" '"'$primary'"'
pc-sc set-user-property $_ "secondary-card-number" '"'$secondary'"'
}
Five lines of code, plus the function definition (not shown), so super quick to write if you are used to how server-command
and PowerShell work. The only really tricky piece is the special quoting in case a card number is empty.
Handy Hint: As an aside, server-command
is a great way to configure PaperCut MF/NG via the set-config
sub-command.
Here is the same card swapping example again, but using the public API instead of server-command
:
# For dll set-up see
# https://www.papercut.com/kb/Main/AdministeringPaperCutWithPowerShell
#Import the dlls we need
Add-Type -Path "$env:USERPROFILE\.nuget\packages\kveer.xmlrpc\1.1.1\lib\netstandard2.0\Kveer.XmlRPC.dll"
Add-Type -Path "$PWD\ServerCommandProxy\bin\Release\netstandard2.0\ServerCommandProxy.dll"
$papercuthost = "localhost" # If not localhost then this address will
# need to be whitelisted in PaperCut
$auth = "token" # Value defined in advanced config property "auth.webservices.auth-token". Should be random
# Proxy object to call PaperCut Server API
$s = New-Object PaperCut.ServerCommandProxy($papercuthost, 9191, $auth);
$BATCH_SIZE = 100
$(do {
[array]$userList = $s.ListUserAccounts($intCounter, $BATCH_SIZE)
Write-Output $userList
$intCounter += $BATCH_SIZE;
} while ($userList.Length -eq $BATCH_SIZE) ) | ForEach-Object {
$primary = $s.GetUserProperty($_, "secondary-card-number");
$secondary = $s.GetUserProperty($_, "primary-card-number");
$s.SetUserProperty($_, "primary-card-number", $primary);
$s.SetUserProperty($_, "secondary-card-number", $secondary);
}
As you can see, this example is more complicated. Additional code is needed to:
- Set up the DLLs and connection details
- Use a loop to get the usernames in chunks (The API is designed not to return a potential list of hundreds of thousands of users)
But the performance gain is huge. For a few hundred users (assuming we only need to run this once) then the server-command
option probably makes more sense, but for a few thousand users (or for a process we need to run regularly), using the public API may be the only realistic option.
As I mentioned previously, using the public API gives you access to features that you can’t use with server-command
. For example the public API has additional methods getUserProperties()
and setUserProperties()
, which we can use in the main loop process as follows:
...| ForEach-Object {
$cardNumbers = $s.GetUserProperties($_, @("secondary-card-number","primary-card-number"))
$s.SetUserProperties($_, @(@("primary-card-number", $cardNumbers[0]), @("secondary-card-number", $cardNumbers[1])))
}
This is obviously even more efficient (each user account now only needs two API calls, not four). It’s harder to write, but again for large number of users, or jobs that run frequently, it’s often worth the extra work.
Using the Server Command Proxy class
In the introduction I mentioned the public API was XML-RPC based, but in the above examples we have not used any XML-RPC calls. This is because in .NET and Java based environments PaperCut Software provide a proxy class that hides the low-level details. For instance, if we wanted to implement the card swapping in Python then the code would need to make XML-RPC calls directly, something like this:
#!/usr/bin/env python3
import xmlrpc.client
import sys
auth="token" # Value defined in advanced config property "auth.webservices.auth-token". Should be random
proxy = xmlrpc.client.ServerProxy(http://localhost:9191/rpc/api/xmlrpc, verbose=False)
offset = 0
limit = 100 # Max number of usernames to retrieve on each call
while True:
try:
userList = proxy.api.listUserAccounts(auth, offset,limit)
except:
print("\nSomething went wrong. Return fault is {}".format(sys.exc_info()[0]))
sys.exit(1)
for user in userList:
try:
primary = proxy.api.getUserProperty(auth, user, "secondary-card-number")
secondary = proxy.api.getUserProperty(auth, user, "primary-card-number")
proxy.api.setUserProperty(auth, user, "primary-card-number", primary)
proxy.api.setUserProperty(auth, user, "secondary-card-number", secondary)
except:
print("\nSomething went wrong. Return fault is {}".format(sys.exc_info()[0]))
sys.exit(1)
if len(userList) < limit:
break # We have reached the end
offset += limit # We need to next slice of users
Note that this code has been simplified, the full version can be found on GitHub .
The C# proxy class will also work on macOS or Linux, and should support any language on the .NET Core runtime.
Conclusion
So for one-off scripts that aren’t too long, use server-command
, but for things that you run regularly (or would take a long time to run) use the API.
Further reading
More information about various API, server-command
and related topics are listed here:
- Top Tips for using the PaperCut MF/NG public web services API
- Handy PowerShell hacks for PaperCut MF/NG
- Administering PaperCut with PowerShell
- Powershell and the PaperCut MF/NG Health API
- More Code examples for the Public web services API and other integration technologies are on our GitHub examples repo , including all the code above.