【问题标题】:create custom module for pdf manipulation为 pdf 操作创建自定义模块
【发布时间】:2019-04-23 19:51:03
【问题描述】:

我想创建一个自定义 Kofax 模块。在批处理方面,扫描的文档会转换为 PDF 文件。我想获取这些 PDF 文件,对其进行操作(为 PDF 文档添加自定义页脚)并将它们交还给 Kofax。

到目前为止我所知道的:

  • 创建 Kofax 导出脚本
  • 向 Kofax 添加自定义模块

我有 APIRef.chm (Kofax.Capture.SDK.CustomModule) 和 CMSplit 作为示例项目。不幸的是,我很难进入它。是否有任何资源逐步说明如何进入自定义模块开发?

所以我知道IBatch接口代表一个选定的批次,IBatchCollection代表所有批次的集合。

我只想知道如何设置“Hello World”示例并可以将我的代码添加到其中,我认为我什至不需要 WinForms 应用程序,因为我只需要操作 PDF 文件就可以了。 ..

【问题讨论】:

    标签: kofax


    【解决方案1】:

    由于我意识到您的问题通常是关于如何创建自定义模块,请允许我添加另一个答案。从 C# 控制台应用程序开始。

    添加所需的程序集

    自定义模块需要以下程序集。它们都位于 KC 的二进制文件夹中(默认情况下,C:\Program Files (x86)\Kofax\CaptureSS\ServLib\Bin 在服务器上)。

    设置部分

    添加新的User ControlWindows Form 进行设置。这纯粹是可选的 - CM 甚至可能没有设置表单,但我建议无论如何添加它。用户控件是最重要的部分,这里 - 它将在 KC Administration 中添加菜单条目,并初始化表单本身:

    [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);
            }
        }
    
    }
    

    运行时部分

    自从我开始使用控制台应用程序以来,我可以继续将所有逻辑放入Program.cs。请注意,这仅用于演示目的,我建议稍后添加特定的类和表单。下面的示例登录到 Kofax Capture,抓取下一个可用批次,然后输出其名称。

    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();
    
        }
    }
    

    注册、COM-Visibility 等

    注册自定义模块是通过RegAsm.exe 完成的,最好是借助 AEX 文件。这是一个示例 - 有关更多详细信息和所有可用设置,请参阅文档。

    [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
    

    最后但同样重要的是,确保您的程序集是 COM 可见的:

    我将整个代码放在GitHub 上,请随意分叉。希望对您有所帮助。

    【讨论】:

    • 我试图重现你的例子,我想我明白了 :) 如果你想看看这些是我的代码行 pastebin.com/BaTbz1Rb 。我测试了它,我想我现在只需要在BatchProcessor 中添加 PDF 操作。我会在这个问题上加一个赏金来奖励你的努力:)(但必须等待 24 小时......)
    • 我还有一个关于你的设置表单的问题,但我把这个问题移到另一个线程stackoverflow.com/questions/55813426/… 不确定我是否误解了你的概念:S
    【解决方案2】:

    Kofax 将批处理公开为 XML,DBLite 基本上是所述 XML 的包装器。该结构在 AcBatch.htm 和 AcDocs.htm 中进行了说明(可在 CaptureSV 目录下找到)。这是基本思想(仅显示文档):

    • AscentCapture 运行时
      • 批次
        • 文档
          • 文档

    单个文档本身具有子元素(例如页面)和多个属性(例如 ConfidenceFormTypeNamePDFGenerationFileName)。这就是你想要的。以下是向下导航文档集合的方法,将文件名存储在名为 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"];
    }
    

    就个人而言,我不喜欢这种结构,所以我为他们的包装器创建了自己的包装器,但这取决于你。

    关于自定义模块本身,交付的样品已经是一个不错的开始。基本上,如果用户手动启动模块,您将有一个基本表单显示 - 如果工作发生在后面,这完全是可选的,最好是作为 Windows 服务。我喜欢从控制台应用程序开始,仅在需要时添加表单。在这里,我将按如下方式启动表单,或启动服务。请注意,如果用户想要将我的自定义模块安装为服务,我有不同的分支:

    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());
        }
    }
    

    运行时本身只是将您登录到 Kofax Capture、注册事件处理程序并逐批处理:

    // 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();
    

    然后,您的 CM 获取下一批。这可以使用 Kofax 的批量通知服务,也可以基于计时器。对于前者,只需处理会话对象的BatchAvailable 事件即可:

    session.BatchAvailable += Session_BatchAvailable;
    

    对于后者,定义一个计时器 - 最好具有可配置的轮询间隔:

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

    当计时器结束时,您可以执行以下操作:

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

    【讨论】:

    • 非常感谢沃尔夫冈。您的 PDF sn-p 工作正常,我在“单独”示例中对其进行了测试。我刚刚看到代码示例提供了一个轮询来获取批次,但不幸的是我不理解您的应用程序示例。什么是CustomModule(您提供的课程)?
    • 编辑:有人告诉我计时器不好/危险。那么我真的必须使用计时器并尝试每 X 秒进行一次轮询吗?有没有“更好”的解决方案?
    • CustomModule 是我的自定义类,这完全是可选的。我更新了我的答案以包括轮询 - 有和没有批量通知服务 (BNS)。计时器一点也不差,BNS 是您的选择。希望这会有所帮助,请随时添加更多问题。
    • 再次感谢。我创建了一个显示当前项目的 sn-p pastebin.com/4z9XTV3h 您的解释非常好,但我正在努力设置基础知识。那么,当我只想操作每个生成的 PDF 文件时,您介意告诉我缺少什么吗?
    • 也许我不需要他们 BatchManager 类中的所有这些方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-12
    • 2014-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多