create custom module for pdf manipulation

戏子无情 提交于 2019-12-11 06:48:55

问题


I want to create a custom Kofax module. When it comes to the batch processing the scanned documents get converted to PDF files. I want to fetch these PDF files, manipulate them (add a custom footer to the PDF document) and hand them back to Kofax.

So what I know so far:

  • create Kofax export scripts
  • add a custom module to Kofax

I have the APIRef.chm (Kofax.Capture.SDK.CustomModule) and the CMSplit as an example project. Unfortunately I struggle getting into it. Are there any resources out there showing step by step how to get into custom module development?

So I know that the IBatch interface represents one selected batch and the IBatchCollection represents the collection of all batches.

I would just like to know how to setup a "Hello World" example and could add my code to it and I think I don't even need a WinForms application because I only need to manipulate the PDF files and that's it...


回答1:


Since I realized that your question was rather about how to create a custom module in general, allow me to add another answer. Start with a C# Console Application.

Add Required Assemblies

Below assemblies are required by a custom module. All of them reside in the KC's binaries folder (by default C:\Program Files (x86)\Kofax\CaptureSS\ServLib\Bin on a server).

Setup Part

Add a new User Control and Windows Form for setup. This is purely optional - a CM might not even have a setup form, but I'd recommend adding it regardless. The user control is the most important part, here - it will add the menu entry in KC Administration, and initialize the form itself:

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ISetupForm
{
    [DispId(1)]
    AdminApplication Application { set; }
    [DispId(2)]
    void ActionEvent(int EventNumber, object Argument, out int Cancel);
}

[ClassInterface(ClassInterfaceType.None)]
[ProgId("Quipu.KC.CM.Setup")]
public class SetupUserControl : UserControl, ISetupForm
{
    private AdminApplication adminApplication;

    public AdminApplication Application
    {
        set
        {
            value.AddMenu("Quipu.KC.CM.Setup", "Quipu.KC.CM - Setup", "BatchClass");
            adminApplication = value;
        }
    }

    public void ActionEvent(int EventNumber, object Argument, out int Cancel)
    {
        Cancel = 0;

        if ((KfxOcxEvent)EventNumber == KfxOcxEvent.KfxOcxEventMenuClicked && (string)Argument == "Quipu.KC.CM.Setup")
        {
            SetupForm form = new SetupForm();
            form.ShowDialog(adminApplication.ActiveBatchClass);
        }
    }

}

Runtime Part

Since I started with a console application, I could go ahead and put all the logic into Program.cs. Note that is for demo-purposes only, and I would recommend adding specific classes and forms later on. The example below logs into Kofax Capture, grabs the next available batch, and just outputs its name.

class Program
{
    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.AssemblyResolve += (sender, eventArgs) => KcAssemblyResolver.Resolve(eventArgs);
        Run(args);
        return;
    }


    static void Run(string[] args)
    {
        // start processing here
        // todo encapsulate this to a separate class!

        // login to KC
        var login = new Login();
        login.EnableSecurityBoost = true;
        login.Login();
        login.ApplicationName = "Quipu.KC.CM";
        login.Version = "1.0";
        login.ValidateUser("Quipu.KC.CM.exe", false, "", "");

        var session = login.RuntimeSession;

        // todo add timer-based polling here (note: mutex!)
        var activeBatch = session.NextBatchGet(login.ProcessID);

        Console.WriteLine(activeBatch.Name);

        activeBatch.BatchClose(
            KfxDbState.KfxDbBatchReady,
            KfxDbQueue.KfxDbQueueNext,
            0,
            "");

        session.Dispose();
        login.Logout();

    }
}

Registering, COM-Visibility, and more

Registering a Custom Module is done via RegAsm.exe and ideally with the help of an AEX file. Here's an example - please refer to the documentation for more details and all available settings.

[Modules]
Minimal CM

[Minimal CM]
RuntimeProgram=Quipu/CM/Quipu.KC.CM/Quipu.KC.CM.exe
ModuleID=Quipu.KC.CM.exe
Description=Minimal Template for a Custom Module in C#
Version=1.0
SupportsTableFields=True
SupportsNonImageFiles=True
SetupProgram=Minimal CM Setup

[Setup Programs]
Minimal CM Setup

[Minimal CM Setup]
Visible=0
OCXFile=Quipu/CM/Quipu.KC.CM/Quipu.KC.CM.exe
ProgID=Quipu.KC.CM.Setup

Last but not least, make sure your assemblies are COM-visible:

I put up the entire code on GitHub, feel free to fork it. Hope it helps.




回答2:


Kofax exposes a batch as an XML, and DBLite is basically a wrapper for said XML. The structure is explained in AcBatch.htm and AcDocs.htm (to be found under the CaptureSV directory). Here's the basic idea (just documents are shown):

  • AscentCaptureRuntime
    • Batch
      • Documents
        • Document

A single document has child elements itself such as pages, and multiple properties such as Confidence, FormTypeName, and PDFGenerationFileName. This is what you want. Here's how you would navigate down the document collection, storing the filename in a variable named pdfFileName:

IACDataElement runtime = activeBatch.ExtractRuntimeACDataElement(0);

IACDataElement batch = runtime.FindChildElementByName("Batch");
var documents = batch.FindChildElementByName("Documents").FindChildElementsByName("Document");
for (int i = 0; i < documents.Count; i++)
{
    // 1-based index in kofax
    var pdfFileName = documents[i + 1]["PDFGenerationFileName"];
}

Personally, I don't like this structure, so I created my own wrapper for their wrapper, but that's up to you.

With regard to the custom module itself, the sample shipped is already a decent start. Basically, you would have a basic form that shows up if the user launches the module manually - which is entirely optional if work happens in the back, preferably as Windows Service. I like to start with a console application, adding forms only when needed. Here, I would launch the form as follows, or start the service. Note that I have different branches in case the user wants to install my Custom Module as service:

else if (Environment.UserInteractive)
{
    // run as module
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new RuntimeForm(args));

}
    else
    {
        // run as service
        ServiceBase.Run(new CustomModuleService());
    }
}

The runtime for itself just logs you into Kofax Capture, registers event handlers, and processes batch by batch:

// login to KC
cm = new CustomModule();
cm.Login("", "");

// add progress event handlers
cm.BatchOpened += Cm_BatchOpened;
cm.BatchClosed += Cm_BatchClosed;
cm.DocumentOpened += Cm_DocumentOpened;
cm.DocumentClosed += Cm_DocumentClosed;
cm.ErrorOccured += Cm_ErrorOccured;

// process in background thread so that the form does not freeze
worker = new BackgroundWorker();
worker.DoWork += (s, a) => Process();
worker.RunWorkerAsync();

Then, your CM fetches the next batch. This can either make use of Kofax' Batch Notification Service, or be based on a timer. For the former, just handle the BatchAvailable event of the session object:

session.BatchAvailable += Session_BatchAvailable;

For the latter, define a timer - preferrably with a configurable polling interval:

pollTimer.Interval = pollIntervalSeconds * 1000;
pollTimer.Elapsed += PollTimer_Elapsed;
pollTimer.Enabled = true;

When the timer elapses, you could do the following:

private void PollTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    mutex.WaitOne();
    ProcessBatches();
    mutex.ReleaseMutex();
}


来源:https://stackoverflow.com/questions/55709249/create-custom-module-for-pdf-manipulation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!