Case Status
Log In


Developing DMS plugins for the…
  • RSS Feed

Last modified on 3/12/2014 4:55 PM by User.


Developing DMS plugins for the PrintSequencer


To simplify the programming development of DMS plugins that work with the Kappris PrintSequencer, we've added a special diagnostic Standalone mode to the KapprisPrint assembly. Instead of forwarding each call to a PrintSequencer process running somewhere else in the domain, KapprisPrint will throw dialogs indicating what it has been called to do, and will also run some rudimentary checks on the data. Since all the processing takes place on the local machine, there's no need to devote and set up a separate PrintSequencer machine.

Once development is complete and all the dialogs are indicating that the passed data is well formed, the programmer can have confidence that on a domain where there is a PrintSequencer process running somewhere, the Standalone mode can be turned off and the PrintSequencer will correctly process the print job.

Before the sample code here was called ConsoleTestApp, and as its name suggests, it was a console app that allowed a Group defined as a list of printable files to be submitted to the PrintSequencer. from onwards the app has been renamed Print Bundle. It still allows you to specify a file containing a list of files at the command line, but it also supports an interactive mode. You can select multiple printable files from a folder and submit those as a Group to the PrintSequencer.

Initial Project Setup and Configuration

  1. Expand the supplied file to a new folder.
  2. Run Register.cmd file in the new folder. This calls regasm on some of the assemblies in the folder. Note there's a corresponding Unregister.cmd for when you've finished all the development work. Before you delete the parent folder, remember to run Unregister.cmd or you'll end up with orphaned items in your registry.
  3. Create a shared folder on your machine. The shared folder is where the PrintSequencer would expect to find job files. Open the xml file KapprisPrint.dll.config and set SharedFolder. Also check that StandaloneTest is true.
  4. Expand the supplied to a new folder.
  5. Open PrintBundle.csproj inside VS2008 or later. At this point the Reference to the KapprisPrint assembly will be undefined, hence the warning yellow triangle icon in the snap. In the project, expand the References node, r-click the KapprisPrint child node and delete its Reference. Then add it anew, pointing at the KapprisPrint.dll in the folder you unzipped KapprisPrintBundle to earlier:

Once you've done this you should be able to build PrintBundle. If you get a build error complaining that the keypair.snk file does not exist you will need to create your own new one (or use your existing company one). Double-click the Properties node in the PrintBundle window and visit the Signing tab. There's an option to create a new keypair file on the dropdown list.

Step the code with a debugger to see how it constructs the file list for printing. Running PrintBundle with no arguments makes it run interactively. If you open the Help » About dialog it displays a usage message:

App to submit files to the PrintSequencer.

   PrintBundle filelist.txt {-q}

filelist.txt is a multi-line text file containing
one filepath per line.

-q means quickprint (no UI), else the UI appears.

If there are no switches app runs interactively.
You can use the supplied files.txt as an argument to PrintBundle. The list of file extensions that the standalone mode considers printable are ".doc", ".docx", ".xls", ".xlsx", ".pdf". This list is fixed inside the standalone test code inside the KapprisPrintManager dll and cannot be modified by you.

The intention is that you use the PrintBundle sources as the starting point for your DMS plugin development. PrintBundle contains code illustrating:

  • how to construct a hierarchy of C# objects for printing. Look for the implementation of CreateFileList in Program.cs  Your plugin will take the list of files from the DMS you are developing for.
  • how to call Utils.SerializeToXML to convert a hierarchy of objects into well-formed XML. The serialization code is auto-generated for us by the XSD tool from an XML schema document, and it just works.
  • how to call the KapprisPrint.PrintFiles and KapprisPrint.QuickPrintFiles methods.
  • a sample implementation of IKapprisFileSource.ExportFiles which copies each file in turn from its source location to the shared folder, and incorporating calls to ReportProgress and check for cancellation.

It should be possible to paste parts of the source code of PrintBundle directly into your plugin source code and get it working for you with minimal changes.


KapprisPrint sits between the DMS (and your plugin) and the PrintSequencer. In order to be able to print a file, the PrintSequencer needs to be able to open it, so it relies on KapprisPrint to copy each document file out of the DMS to a shared folder. KapprisPrint doesn't know the inner workings of each and every DMS, but the plugin does - KapprisPrint calls the IKapprisFileSource.ExportFiles function to copy each file out of the DMS into the shared folder so the PrintSequencer can open and print it.

Starting at, the ExportFiles prototype has a second argument of type IKapprisExportProgress* ip. The purpose of this is to allow your implementation of ExportFiles to call the ReportProgress and CancellationPending methods as part of each file copy operation. The KapprisPrintManager contains a Progress bar that reports how the export operation is progressing. Also, pressing Cancel will halt any Export operation currently in progress. The sample implementation of ExportFiles in PrintBundle shows how best to call these methods. Although you can ignore the ip argument, doing so means the Progress bar will not update and the export operation cannot be Cancelled. The Standalone mode will exercise these methods if you have used them.

The list of files to be printed is passed between plugin, KapprisPrint and the Print Sequencer as an XML chunk. This is because the PrintSequencer is addressed via WSDL. The XML conforms to an XSD schema which is available from Kutana. The very best way of constructing well-formed XML is to write .NET code that has the KapprisPrint.dll as a Reference, then construct a hierarchy of objects. This is exactly what PrintBundle does. When the hierarchy of objects is serialized to XML, the code that does the serialization is auto-generated from the schema, and the resulting XML is guaranteed to be well formed. Kutana does not recommend constructing suitable XML by any other means.

As PrintBundle runs you will see the 'Diagnostic Form for xxx' forms whose snaps appear in the following section. Your code needs to prepare a list of files for printing and then call IKapprisPrint.PrintFiles or IKapprisPrint.QuickPrintFiles. There's also an IKapprisPrint.Printable method that trims your supplied list down to one that can be printed.

iManage Example

Here's a snap of an iManage folder inside Outlook. I've already made a multiple selection containing six documents:

Calling the Print method

If you r-click any file in the selected group and select 'Kappris Print', the following dialog will appear. Note that for each document in the list, KapprisPrint has already constructed a unique destination path, but the target folder has not been created and no file has yet been copied from source (OriginalID) to destination (FilePath). That is why the Comment indicates for each file that 'FilePath value does not exist'.

The 'Copy ListView contents' button puts the listview contents onto the clipboard where they can be pasted into Excel or expressed as html for further analysis.

FilePath Description Original ID Comment
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\vnfsdl42.doc Metadata Word Sample !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:1006,1: FilePath value does not exist
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\npk3tl4n.pdf 090810 Title Search (text pdf, 2 pages) !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:990,1: FilePath value does not exist
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\wwtcl2zx.pdf Fillable Form_UK !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:951,1: FilePath value does not exist
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\e1jj1vkd.doc Modified document !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:944,1: FilePath value does not exist
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\o14rrbhh.doc Original document !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:943,2: FilePath value does not exist
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\r14quupk.doc Covering Letter with letterhead !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:970,1: FilePath value does not exist


Pressing the 'Call ExportFiles function' button causes KapprisPrint to call your implementation of the IKapprisFileSource.ExportFiles function. The behaviour of this function changes depending on which DMS the source files live in. In this example, the DMS is iManage, which refers to each file by a unique OriginalID (sample values in the above table). The implementation of IKapprisFileSource.ExportFiles works with iManage to copy each file from its OriginalID location to the destination FilePath constructed by KapprisPrint.

Once the IKapprisFileSource.ExportFiles function returns, the listview in the dialog is refreshed. If the export has succeeded, each file named in the FilePath column will now actually exist, and the Comment will reflect this. Note too that the 'Call ExportFiles function' button is now disabled, so you can't press it a second time.

FilePath Description Original ID Comment
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\vnfsdl42.doc Metadata Word Sample !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:1006,1: FilePath value exists
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\npk3tl4n.pdf 090810 Title Search (text pdf, 2 pages) !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:990,1: FilePath value exists
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\wwtcl2zx.pdf Fillable Form_UK !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:951,1: FilePath value exists
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\e1jj1vkd.doc Modified document !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:944,1: FilePath value exists
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\o14rrbhh.doc Original document !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:943,2: FilePath value exists
\\xp-test\ps\C8C128ED-0881-42A1-9FD7-F1AE668C6A10\r14quupk.doc Covering Letter with letterhead !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:970,1: FilePath value exists


Calling the Quick Print method

Instead of selecting 'Kappris Print' for a group of documents, you can select 'Kappris QuickPrint'. This call the ExportFiles function before the dialog first appears:

FilePath Description Original ID Comment
\\xp-test\ps\240EA860-A402-48C2-B7CF-BAACC6033D00\xbhtfuun.doc Metadata Word Sample !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:1006,1: FilePath value exists
\\xp-test\ps\240EA860-A402-48C2-B7CF-BAACC6033D00\jcpszcnt.pdf 090810 Title Search (text pdf, 2 pages) !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:990,1: FilePath value exists
\\xp-test\ps\240EA860-A402-48C2-B7CF-BAACC6033D00\vdvoft0g.pdf Fillable Form_UK !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:951,1: FilePath value exists
\\xp-test\ps\240EA860-A402-48C2-B7CF-BAACC6033D00\c4zgj0xm.doc Modified document !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:944,1: FilePath value exists
\\xp-test\ps\240EA860-A402-48C2-B7CF-BAACC6033D00\qvx2zyor.doc Original document !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:943,2: FilePath value exists
\\xp-test\ps\240EA860-A402-48C2-B7CF-BAACC6033D00\wae34bxd.doc Covering Letter with letterhead !nrtdms:0:!session:WORKSITE:!database:LIVE:!document:970,1: FilePath value exists


Calling the Printable method

The Standalone code has a short list of file types it considers printable. It determines file type just by looking at the extension. Remember this is just for illustration - the actual PrintSequencer will be able to print using any apps installed on the PrintSequencer machine, and uses the registry to determine file type, not just a naive extension check.

In the Standalone code, the acceptable file extension list is:

extensions = new System.Collections.Generic.List() { ".doc", ".docx", ".xls", ".xlsx", ".pdf" };

If you call the Printable method including a file extension not in this list then this will be reflected in the dialog: