Ejemplo n.º 1
0
        /// <summary>
        /// This is our main loop where we issue commands to the TWAIN
        /// object on behalf of the caller.  This function runs in its
        /// own thread...
        /// </summary>
        private void TwainLocalOnTwainThread
        (
            object a_objectParameters
        )
        {
            TwainLocalOnTwain           twainlocalontwain;
            TwainLocalOnTwainParameters twainlocalontwainparameters = (TwainLocalOnTwainParameters)a_objectParameters;

            // Create our object...
            twainlocalontwain = new TwainLocalOnTwain
                                (
                twainlocalontwainparameters.m_szWriteFolder,
                twainlocalontwainparameters.m_szImagesFolder,
                twainlocalontwainparameters.m_szIpc,
                twainlocalontwainparameters.m_iPid,
                twainlocalontwainparameters.m_runinuithreaddelegate,
                twainlocalontwainparameters.m_formtwain,
                twainlocalontwainparameters.m_intptrHwnd
                                );

            // Run our object...
            twainlocalontwain.Run();

            // We're done...
            Invoke(new MethodInvoker(delegate() { CloseFormTwain(); }));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Select the mode for this session, batch or interactive,
        /// based on the arguments.  Don't be weirded out by this
        /// function calling TWAIN Local On Twain and then that function using
        /// Sword.  This is a static function, it's just a convenience
        /// to use the Sword object to hold it, it could go anywhere
        /// and later on probably will (like as a function inside of
        /// the Program module).
        /// </summary>
        /// <returns>true for batch mode, false for interactive mode</returns>
        public static bool SelectMode()
        {
            int    iPid = 0;
            string szIpc;
            string szTaskFile;
            string szImagesFolder;
            bool   blTestPdfRaster;
            string szTestDnssd;

            // Check the arguments...
            string szWriteFolder    = Config.Get("writeFolder", null);
            string szExecutableName = Config.Get("executableName", null);

            szTaskFile      = Config.Get("task", null);
            blTestPdfRaster = (Config.Get("testpdfraster", null) != null);
            szTestDnssd     = Config.Get("testdnssd", null);
            szIpc           = Config.Get("ipc", null);
            szImagesFolder  = Config.Get("images", null);
            if (string.IsNullOrEmpty(szImagesFolder))
            {
                szImagesFolder = Path.Combine(szWriteFolder, "images");
            }
            iPid = int.Parse(Config.Get("parentpid", "0"));

            // Run in IPC mode.  The caller has set up a 'pipe' for us, so we'll use
            // that to send commands back and forth.  This is the normal mode when
            // we're running with a scanner...
            if (szIpc != null)
            {
                // With Windows we need a window for the driver, but we can hide it...
                if (TWAIN.GetPlatform() == TWAIN.Platform.WINDOWS)
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new FormTwain(szWriteFolder, szImagesFolder, szIpc, iPid));
                    return(true);
                }

                // Linux and Mac OS X are okay without a window...
                else
                {
                    TwainLocalOnTwain twainlocalontwain;

                    // Create our object...
                    twainlocalontwain = new TwainLocalOnTwain(szWriteFolder, szImagesFolder, szIpc, iPid, null, null, IntPtr.Zero);

                    // Run our object...
                    twainlocalontwain.Run();

                    // All done...
                    return(true);
                }
            }

            // Handle the TWAIN list, we use this during registration to find out
            // what drivers we can use, and collect some info about them...
            string szTwainList = Config.Get("twainlist", null);

            if (szTwainList != null)
            {
                string szTwainListAction = Config.Get("twainlistaction", null);
                string szTwainListData   = Config.Get("twainlistdata", null);
                if (szTwainList == "")
                {
                    szTwainList = Path.Combine(Config.Get("writeFolder", ""), "twainlist.txt");
                }
                System.IO.File.WriteAllText(szTwainList, ProcessSwordTask.TwainListDrivers(szTwainListAction, szTwainListData));
                return(true);
            }

            /// Test DNS-SD...
            if (!string.IsNullOrEmpty(szTestDnssd))
            {
                if (szTestDnssd == "monitor")
                {
                    int   ii;
                    int   jj;
                    Dnssd dnssd;
                    bool  blServiceIsAvailable;
                    Interpreter.CreateConsole();
                    List <Dnssd.DnssdDeviceInfo> ldnssddeviceinfo = new List <Dnssd.DnssdDeviceInfo>();
                    dnssd = new Dnssd(Dnssd.Reason.Monitor, out blServiceIsAvailable);
                    if (blServiceIsAvailable)
                    {
                        dnssd.MonitorStart(null, IntPtr.Zero);
                        for (ii = 0; ii < 60; ii++)
                        {
                            bool blUpdated   = false;
                            bool blNoMonitor = false;
                            Thread.Sleep(1000);
                            ldnssddeviceinfo = dnssd.GetSnapshot(ldnssddeviceinfo, out blUpdated, out blNoMonitor);
                            if (blUpdated)
                            {
                                Console.Out.WriteLine("");
                                if ((ldnssddeviceinfo == null) || (ldnssddeviceinfo.Count == 0))
                                {
                                    Console.Out.WriteLine("***empty***");
                                }
                                else
                                {
                                    for (jj = 0; jj < ldnssddeviceinfo.Count; jj++)
                                    {
                                        Console.Out.WriteLine(ldnssddeviceinfo[jj].GetInterface() + " " + ldnssddeviceinfo[jj].GetServiceName());
                                    }
                                }
                            }
                        }
                        dnssd.MonitorStop();
                    }
                    dnssd.Dispose();
                    dnssd = null;
                }
                else if (szTestDnssd == "register")
                {
                    Dnssd dnssd;
                    bool  blServiceIsAvailable;
                    Interpreter.CreateConsole();
                    dnssd = new Dnssd(Dnssd.Reason.Register, out blServiceIsAvailable);
                    if (blServiceIsAvailable)
                    {
                        dnssd.RegisterStart("Instance", 55556, "Ty", "", "", "", "Note");
                        Thread.Sleep(60000);
                        dnssd.RegisterStop();
                    }
                    dnssd.Dispose();
                    dnssd = null;
                }

                // All done...
                return(true);
            }

            // Otherwise let the user interact with us...
            TWAINWorkingGroup.Log.Info("Interactive mode...");
            return(false);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Test our ability to run the TWAIN driver using the TWAIN Direct Client-Scanner
        /// API as the controlling API.  This is easier to debug than running stuff across
        /// more than one process with the network involved...
        /// </summary>
        /// <returns></returns>
        public bool Test()
        {
            int ii;

            int[]      aiImageBlockNum;
            long       lResponseCharacterOffset;
            bool       blSts;
            bool       blEndOfJob;
            string     szJson;
            Thread     thread;
            Ipc        ipc;
            JsonLookup jsonlookup;

            // Create our objects...
            m_twainlocalontwain = new TwainLocalOnTwain(m_szWriteFolder, m_szIpc, Process.GetCurrentProcess().Id, null, null, IntPtr.Zero);
            jsonlookup          = new JsonLookup();
            ipc = new Ipc(m_szIpc, true);

            // Run in a thread...
            thread = new Thread(RunTest);
            thread.Start();

            // Wait for a connection...
            ipc.Accept();

            // Create Session...
            #region Create Session...

            // Open the scanner...
            blSts = ipc.Write
                    (
                "{" +
                "\"method\":\"createSession\"," +
                "\"scanner\":\"" + m_szScanner + "\"" +
                "}"
                    );
            if (!blSts)
            {
                TWAINWorkingGroup.Log.Error("Lost our process...");
                goto ABORT;
            }

            // Get the result...
            szJson = ipc.Read();

            // Analyze the result...
            try
            {
                jsonlookup.Load(szJson, out lResponseCharacterOffset);
                if (jsonlookup.Get("status") != "success")
                {
                    TWAINWorkingGroup.Log.Error("createSession failed: " + jsonlookup.Get("status"));
                    return(false);
                }
            }
            catch
            {
                TWAINWorkingGroup.Log.Error("createSession failed: JSON error");
                return(false);
            }

            #endregion


            // Set TWAIN Direct Options...
            #region Set TWAIN Direct Options...

            // Read the file as a sequence of UTF-8 bytes, and convert the data
            // to base64 for transmission to the TwainDirectOnTwain process...
            string szTask = File.ReadAllText(m_szTaskFile);

            // Send the data...
            blSts = ipc.Write
                    (
                "{" +
                "\"method\":\"setTwainDirectOptions\"," +
                "\"task\":" + szTask +
                "}"
                    );
            if (!blSts)
            {
                TWAINWorkingGroup.Log.Error("Lost our process...");
                goto ABORT;
            }

            // Get the result...
            szJson = ipc.Read();
            if (szJson == null)
            {
                TWAINWorkingGroup.Log.Error("Lost our process...");
                goto ABORT;
            }

            #endregion


            // Start Capturing...
            #region Start Capturing...

            blSts = ipc.Write
                    (
                "{" +
                "\"method\":\"startCapturing\"" +
                "}"
                    );
            if (!blSts)
            {
                TWAINWorkingGroup.Log.Error("Lost our process...");
                goto ABORT;
            }

            // Get the result...
            szJson = ipc.Read();
            if (szJson == null)
            {
                TWAINWorkingGroup.Log.Error("Lost our process...");
                goto ABORT;
            }

            #endregion


            // Loop until we run out of images...
            blEndOfJob      = false;
            aiImageBlockNum = null;
            while (true)
            {
                // Get Session (wait for image)...
                #region GetSession (wait for images)...

                // Stay in this loop unti we get an image or an error...
                while (true)
                {
                    // Get the current session info...
                    blSts = ipc.Write
                            (
                        "{" +
                        "\"method\":\"getSession\"" +
                        "}"
                            );
                    if (!blSts)
                    {
                        TWAINWorkingGroup.Log.Error("Lost our process...");
                        goto ABORT;
                    }

                    // Get the result...
                    szJson = ipc.Read();
                    if (szJson == null)
                    {
                        TWAINWorkingGroup.Log.Error("Lost our process...");
                        goto ABORT;
                    }

                    // Parse it...
                    jsonlookup = new JsonLookup();
                    jsonlookup.Load(szJson, out lResponseCharacterOffset);

                    // Bail if we're end of job...
                    if (jsonlookup.Get("endOfJob") == "true")
                    {
                        blEndOfJob = true;
                        break;
                    }

                    // Collect the data...
                    try
                    {
                        aiImageBlockNum = null;
                        for (ii = 0; ; ii++)
                        {
                            // Get the data...
                            string szNum = jsonlookup.Get("session.imageBlocks[" + ii + "]");
                            if ((szNum == null) || (szNum == ""))
                            {
                                break;
                            }

                            // Convert it...
                            int iTmp = int.Parse(szNum);

                            // Add it to the list...
                            if (aiImageBlockNum == null)
                            {
                                aiImageBlockNum    = new int[1];
                                aiImageBlockNum[0] = iTmp;
                            }
                            else
                            {
                                int[] aiTmp = new int[aiImageBlockNum.Length + 1];
                                aiImageBlockNum.CopyTo(aiTmp, 0);
                                aiTmp[aiTmp.Length - 1] = iTmp;
                                aiImageBlockNum         = aiTmp;
                            }
                        }
                    }
                    catch
                    {
                        // don't need to do anything...
                    }

                    // We got one!
                    if (aiImageBlockNum != null)
                    {
                        break;
                    }

                    // Snooze a bit...
                    Thread.Sleep(100);
                }

                // Bail if we're end of job...
                if (blEndOfJob)
                {
                    break;
                }

                #endregion


                // Read Image Block Metadata...
                #region Read Image Block Metadata...

                // Get this image's metadata...
                blSts = ipc.Write
                        (
                    "{" +
                    "\"method\":\"readImageBlockMetadata\"," +
                    "\"imageBlockNum\":" + aiImageBlockNum[0] +
                    "}"
                        );
                if (!blSts)
                {
                    TWAINWorkingGroup.Log.Error("Lost our process...");
                    goto ABORT;
                }

                // Get the result...
                szJson = ipc.Read();
                if (szJson == null)
                {
                    TWAINWorkingGroup.Log.Error("Lost our process...");
                    goto ABORT;
                }

                #endregion


                // Read Image Block...
                #region Read Image Block...

                // Get this image...
                blSts = ipc.Write
                        (
                    "{" +
                    "\"method\":\"readImageBlock\"," +
                    "\"imageBlockNum\":" + aiImageBlockNum[0] +
                    "}"
                        );
                if (!blSts)
                {
                    TWAINWorkingGroup.Log.Error("Lost our process...");
                    goto ABORT;
                }

                // Get the result...
                szJson = ipc.Read();
                if (szJson == null)
                {
                    TWAINWorkingGroup.Log.Error("Lost our process...");
                    goto ABORT;
                }

                #endregion


                // Release Image Block...
                #region Release Image Block...

                // Release this image...
                blSts = ipc.Write
                        (
                    "{" +
                    "\"method\":\"releaseImageBlocks\"," +
                    "\"imageBlockNum\":" + aiImageBlockNum[0] + "," +
                    "\"lastImageBlockNum\":" + aiImageBlockNum[0] +
                    "}"
                        );
                if (!blSts)
                {
                    TWAINWorkingGroup.Log.Error("Lost our process...");
                    goto ABORT;
                }

                // Get the result...
                szJson = ipc.Read();
                if (szJson == null)
                {
                    TWAINWorkingGroup.Log.Error("Lost our process...");
                    goto ABORT;
                }

                #endregion
            }


            // Stop Capturing...
            #region Stop Capturing...

            blSts = ipc.Write
                    (
                "{" +
                "\"method\":\"stopCapturing\"" +
                "}"
                    );
            if (!blSts)
            {
                TWAINWorkingGroup.Log.Error("Lost our process...");
                goto ABORT;
            }

            // Get the result...
            szJson = ipc.Read();
            if (szJson == null)
            {
                TWAINWorkingGroup.Log.Error("Lost our process...");
                goto ABORT;
            }

            #endregion


            // Close Session...
            #region Close Session...

            // Close the scanner...
            blSts = ipc.Write
                    (
                "{" +
                "\"method\":\"closeSession\"" +
                "}"
                    );
            if (!blSts)
            {
                TWAINWorkingGroup.Log.Error("Lost our process...");
                goto ABORT;
            }

            // Get the result...
            szJson = ipc.Read();
            if (szJson == null)
            {
                TWAINWorkingGroup.Log.Error("Lost our process...");
                goto ABORT;
            }

            // Exit the process...
            blSts = ipc.Write
                    (
                "{" +
                "\"method\":\"exit\"" +
                "}"
                    );
            if (!blSts)
            {
                TWAINWorkingGroup.Log.Error("Lost our process...");
                goto ABORT;
            }

            #endregion


            // All done...
ABORT:
            thread.Join();
            return(true);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Select the mode for this session, batch or interactive,
        /// based on the arguments.  Don't be weirded out by this
        /// function calling TWAIN Local On Twain and then that function using
        /// Sword.  This is a static function, it's just a convenience
        /// to use the Sword object to hold it, it could go anywhere
        /// and later on probably will (like as a function inside of
        /// the Program module).
        /// </summary>
        /// <returns>true for batch mode, false for interactive mode</returns>
        public static bool SelectMode()
        {
            int    iPid = 0;
            long   lResponseCharacterOffset;
            string szIpc;
            string szTaskFile;
            bool   blTestPdfRaster;
            bool   blTestTwainLocalOnTwain;
            bool   blTestJson;
            bool   blTestDnssd;

            // Check the arguments...
            string szWriteFolder    = Config.Get("writeFolder", null);
            string szExecutableName = Config.Get("executableName", null);

            szTaskFile              = Config.Get("task", null);
            blTestPdfRaster         = (Config.Get("testpdfraster", null) != null);
            blTestTwainLocalOnTwain = (Config.Get("testtwainlocalontwain", null) != null);
            blTestJson              = (Config.Get("testjson", null) != null);
            blTestDnssd             = (Config.Get("testdnssd", null) != null);
            szIpc = Config.Get("ipc", null);
            iPid  = int.Parse(Config.Get("parentpid", "0"));

            // Run in IPC mode.  The caller has set up a 'pipe' for us, so we'll use
            // that to send commands back and forth.  This is the normal mode when
            // we're running with a scanner...
            if (szIpc != null)
            {
                // With Windows we need a window for the driver, but we can hide it...
                if (TWAINCSToolkit.GetPlatform() == "WINDOWS")
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new FormTwain(szWriteFolder, szIpc, iPid, RunInUiThread));
                    return(true);
                }

                // Linux and Mac OS X are okay without a window...
                else
                {
                    TwainLocalOnTwain twainlocalontwain;

                    // Create our object...
                    twainlocalontwain = new TwainLocalOnTwain(szWriteFolder, szIpc, iPid, null, null, IntPtr.Zero);

                    // Run our object...
                    twainlocalontwain.Run();

                    // All done...
                    return(true);
                }
            }

            // Handle the TWAIN list, we use this during registration to find out
            // what drivers we can use, and collect some info about them...
            string szTwainList = Config.Get("twainlist", null);

            if (szTwainList != null)
            {
                if (szTwainList == "")
                {
                    szTwainList = Path.Combine(Config.Get("writeFolder", ""), "twainlist.txt");
                }
                System.IO.File.WriteAllText(szTwainList, Sword.TwainListDrivers());
                return(true);
            }

            // Test PDF/Raster...
            if (blTestPdfRaster)
            {
                TestPdfRaster testpdfraster;

                // Create our object...
                testpdfraster = new TestPdfRaster();

                // Do the test...
                testpdfraster.Test();

                // All done...
                TWAINWorkingGroup.Log.Close();
                return(true);
            }

            // Test TWAIN Local on TWAIN...
            if (blTestTwainLocalOnTwain)
            {
                TestTwainLocalOnTwain testtwainlocalontwain;

                // Create our object...
                testtwainlocalontwain = new TestTwainLocalOnTwain(Config.Get("scanner", null), szWriteFolder, iPid, szTaskFile);

                // Do the test...
                testtwainlocalontwain.Test();

                // All done...
                return(true);
            }

            // Test JSON...
            if (blTestJson)
            {
                TwainDirectSupport.JsonLookup jsonlookup = new TwainDirectSupport.JsonLookup();

                string szTest =
                    "{\n" +
                    "    \"array\": [\n" +
                    "        {\n" +
                    "            \\\"aaa\\\": 0,\n" +
                    "            'bbb': 1\n" +
                    "        },\n" +
                    "        {\n" +
                    "            ccc : 2,\n" +
                    "            'ddd' : 3,\n" +
                    "            \"xxx\": [\n" +
                    "                {\n" +
                    "                    \"mmm\": 111\n" +
                    "                },\n" +
                    "                {\n" +
                    "                    \"nnn\": 222\n" +
                    "                },\n" +
                    "                {\n" +
                    "                    \"ooo\": 333\n" +
                    "                }\n" +
                    "            ]\n" +
                    "        },\n" +
                    "        {\n" +
                    "            \"eee\": 4,\n" +
                    "            \"fff\": 5\n" +
                    "        }\n" +
                    "    ],\n" +
                    "    \"string\": \"value\"\n" +
                    "}";

                // Load something interesting...
                bool blSuccess = jsonlookup.Load(szTest, out lResponseCharacterOffset);
                if (!blSuccess)
                {
                    string sz = szTest.Substring(0, (int)lResponseCharacterOffset);
                }

                NativeMethods.AllocConsole();
                jsonlookup.Dump();

                // Find something interesting...
                string szValue;
                TwainDirectSupport.JsonLookup.EPROPERTYTYPE epropertytype;
                blSuccess = jsonlookup.GetCheck("array[0].aaa", out szValue, out epropertytype, true);

                // Test...
                string[] aszFile = Directory.GetFiles("C:/Users/l252353/Desktop/TwainDirect/source/TwainDirectOnTwain/bin/x86/Debug/data");
                if (aszFile != null)
                {
                    foreach (string szFile in aszFile)
                    {
                        // Skip non-.json files...
                        if (!szFile.Contains("pass0.json"))
                        {
                            continue;
                        }

                        // Read it...
                        string szJson = File.ReadAllText(szFile);

                        // Load it...
                        blSuccess = jsonlookup.Load(szJson, out lResponseCharacterOffset);

                        // File we're working on...
                        Console.WriteLine("\r\n*******************************************************************************");
                        Console.WriteLine(szFile);

                        // Fail file results...
                        if (szFile.Contains("fail"))
                        {
                            if (blSuccess)
                            {
                                Console.WriteLine("FAILED ON THE FAIL...");
                            }
                            else
                            {
                                Console.WriteLine("Error at offset: " + lResponseCharacterOffset);
                                Console.WriteLine(szJson.Substring(0, (int)lResponseCharacterOffset) + "^ERROR^" + szJson.Substring((int)lResponseCharacterOffset));
                            }
                        }

                        // Pass file results...
                        else
                        {
                            if (blSuccess)
                            {
                                jsonlookup.Dump();
                                jsonlookup.GetCheck("devices[0].id", out szValue, out epropertytype, true);
                            }
                            else
                            {
                                Console.WriteLine("Error at offset: " + lResponseCharacterOffset);
                                Console.WriteLine(szJson.Substring(0, (int)lResponseCharacterOffset) + "^ERROR^" + szJson.Substring((int)lResponseCharacterOffset));
                            }
                        }
                    }
                }

                // All done...
                return(true);
            }

            /// Test DNS-SD...
            if (blTestDnssd)
            {
                // Do the test...
                int tt;
                int jj;
                TwainDirectSupport.Dnssd.DnssdDeviceInfo[] adnssddeviceinfo = null;
                NativeMethods.AllocConsole();
                TwainDirectSupport.Dnssd dnssd = new TwainDirectSupport.Dnssd(TwainDirectSupport.Dnssd.Reason.Monitor);
                dnssd.MonitorStart();
                for (tt = 0; tt < 6000000; tt++)
                {
                    bool blUpdated;
                    TwainDirectSupport.Dnssd.DnssdDeviceInfo[] adnssddeviceinfoNew;
                    TwainDirectSupport.Dnssd.DnssdDeviceInfo[] adnssddeviceinfoCompare = adnssddeviceinfo;
                    adnssddeviceinfoNew = dnssd.GetSnapshot(adnssddeviceinfoCompare, out blUpdated);
                    adnssddeviceinfo    = adnssddeviceinfoNew;
                    adnssddeviceinfoNew = null;
                    if (adnssddeviceinfo == null)
                    {
                        if (blUpdated)
                        {
                            Console.Out.WriteLine("");
                            Console.Out.WriteLine("*** empty list ***");
                        }
                        System.Threading.Thread.Sleep(1000);
                        continue;
                    }
                    if (blUpdated)
                    {
                        Console.Out.WriteLine("");
                        for (jj = 0; jj < adnssddeviceinfo.Length; jj++)
                        {
                            Console.Out.WriteLine
                            (
                                adnssddeviceinfo[jj].szServiceName + Environment.NewLine +
                                "  " + adnssddeviceinfo[jj].szLinkLocal +
                                " " + adnssddeviceinfo[jj].lInterface +
                                ((adnssddeviceinfo[jj].szIpv4 == null) ? " NoIpv4" : (" " + adnssddeviceinfo[jj].szIpv4)) +
                                ((adnssddeviceinfo[jj].szIpv6 == null) ? " NoIpv6" : (" " + adnssddeviceinfo[jj].szIpv6)) +
                                " " + adnssddeviceinfo[jj].lPort +
                                ((adnssddeviceinfo[jj].aszText == null) ? "" : (Environment.NewLine + "  " + string.Join(" ", adnssddeviceinfo[jj].aszText)))
                            );
                        }
                    }
                    System.Threading.Thread.Sleep(1000);
                }
                dnssd.MonitorStop();

                // All done...
                return(true);
            }

            // Execute the specified task...
            if (File.Exists(szTaskFile))
            {
                bool      blSetAppCapabilities = false;
                Sword     sword;
                SwordTask swordtask;

                // Init stuff...
                swordtask = new SwordTask();

                // Create our object...
                sword = new Sword(null);

                // Run our task...
                sword.BatchMode(Config.Get("scanner", null), szTaskFile, false, ref swordtask, ref blSetAppCapabilities);

                // All done...
                return(true);
            }

            // Otherwise let the user interact with us...
            TWAINWorkingGroup.Log.Info("Interactive mode...");
            return(false);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Select the mode for this session, batch or interactive,
        /// based on the arguments.  Don't be weirded out by this
        /// function calling TWAIN Local On Twain and then that function using
        /// Sword.  This is a static function, it's just a convenience
        /// to use the Sword object to hold it, it could go anywhere
        /// and later on probably will (like as a function inside of
        /// the Program module).
        /// </summary>
        /// <returns>true for batch mode, false for interactive mode</returns>
        public static bool SelectMode()
        {
            int    iPid = 0;
            string szIpc;
            string szTask;
            string szTaskFile;
            string szImagesFolder;
            bool   blTestPdfRaster;
            string szTestDnssd;
            bool   blSuccess;

            // Check the arguments...
            string szWriteFolder    = Config.Get("writeFolder", null);
            string szExecutableName = Config.Get("executableName", null);

            szTaskFile      = Config.Get("task", null);
            blTestPdfRaster = (Config.Get("testpdfraster", null) != null);
            szTestDnssd     = Config.Get("testdnssd", null);
            szIpc           = Config.Get("ipc", null);
            szImagesFolder  = Config.Get("images", null);
            if (string.IsNullOrEmpty(szImagesFolder))
            {
                szImagesFolder = Path.Combine(szWriteFolder, "images");
            }
            iPid = int.Parse(Config.Get("parentpid", "0"));

            // Test ProcessSwordTask...
            if (!string.IsNullOrEmpty(Config.Get("testtask", null)))
            {
                // Create our object...
                ProcessSwordTask processswordtask = new ProcessSwordTask(szImagesFolder, null, null);

                // Did we get a valid filename?
                if ((szTaskFile == null) || !File.Exists(szTaskFile))
                {
                    Console.Out.WriteLine("");
                    Console.Out.WriteLine("Please provide a valid task=file argument...");
                    return(false);
                }

                // Load the file...
                szTask = File.ReadAllText(szTaskFile);

                // Handle certification files...
                string[] aszTask = szTask.Split(new string[] { "***DATADATADATA***" }, StringSplitOptions.RemoveEmptyEntries);
                if ((aszTask == null) || (aszTask.Length == 0))
                {
                    Console.Out.WriteLine("");
                    Console.Out.WriteLine("Please provide a task file with data...");
                    return(false);
                }

                // Get our task data...
                if (aszTask.Length == 1)
                {
                    szTask = aszTask[0];
                }
                else
                {
                    szTask = aszTask[1];
                }

                // Run a test...
                bool blSetAppCapabilities = true;
                blSuccess = processswordtask.BatchMode(null, szTask, true, ref blSetAppCapabilities);
                //blSuccess = processswordtask.Deserialize(szTask, "211a1e90-11e1-11e5-9493-1697f925ec7b");
                if (blSuccess)
                {
                    //blSuccess = processswordtask.ProcessAndRun();
                }

                // All done...
                return(true);
            }

            // Run in IPC mode.  The caller has set up a 'pipe' for us, so we'll use
            // that to send commands back and forth.  This is the normal mode when
            // we're running with a scanner...
            if (szIpc != null)
            {
                // With Windows we need a window for the driver, but we can hide it...
                if (TWAINCSToolkit.GetPlatform() == "WINDOWS")
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new FormTwain(szWriteFolder, szImagesFolder, szIpc, iPid, RunInUiThread));
                    return(true);
                }

                // Linux and Mac OS X are okay without a window...
                else
                {
                    TwainLocalOnTwain twainlocalontwain;

                    // Create our object...
                    twainlocalontwain = new TwainLocalOnTwain(szWriteFolder, szImagesFolder, szIpc, iPid, null, null, IntPtr.Zero);

                    // Run our object...
                    twainlocalontwain.Run();

                    // All done...
                    return(true);
                }
            }

            // Handle the TWAIN list, we use this during registration to find out
            // what drivers we can use, and collect some info about them...
            string szTwainList = Config.Get("twainlist", null);

            if (szTwainList != null)
            {
                if (szTwainList == "")
                {
                    szTwainList = Path.Combine(Config.Get("writeFolder", ""), "twainlist.txt");
                }
                System.IO.File.WriteAllText(szTwainList, ProcessSwordTask.TwainListDrivers());
                return(true);
            }

            /// Test DNS-SD...
            if (!string.IsNullOrEmpty(szTestDnssd))
            {
                if (szTestDnssd == "monitor")
                {
                    int   ii;
                    int   jj;
                    Dnssd dnssd;
                    Interpreter.CreateConsole();
                    Dnssd.DnssdDeviceInfo[] adnssddeviceinfo = null;
                    dnssd = new Dnssd(Dnssd.Reason.Monitor);
                    dnssd.MonitorStart(null, IntPtr.Zero);
                    for (ii = 0; ii < 60; ii++)
                    {
                        bool blUpdated = false;
                        Thread.Sleep(1000);
                        adnssddeviceinfo = dnssd.GetSnapshot(adnssddeviceinfo, out blUpdated);
                        if (blUpdated)
                        {
                            Console.Out.WriteLine("");
                            if ((adnssddeviceinfo == null) || (adnssddeviceinfo.Length == 0))
                            {
                                Console.Out.WriteLine("***empty***");
                            }
                            else
                            {
                                for (jj = 0; jj < adnssddeviceinfo.Length; jj++)
                                {
                                    Console.Out.WriteLine(adnssddeviceinfo[jj].GetInterface() + " " + adnssddeviceinfo[jj].GetServiceName());
                                }
                            }
                        }
                    }
                    dnssd.MonitorStop();
                    dnssd.Dispose();
                }
                else if (szTestDnssd == "register")
                {
                    Dnssd dnssd;
                    Interpreter.CreateConsole();
                    dnssd = new Dnssd(Dnssd.Reason.Register);
                    dnssd.RegisterStart("Instance", 55556, "Ty", "", "Note");
                    Thread.Sleep(60000);
                    dnssd.RegisterStop();
                    dnssd.Dispose();
                }

                // All done...
                return(true);
            }

            // Execute the specified task...
            if (File.Exists(szTaskFile))
            {
                bool             blSetAppCapabilities = false;
                ProcessSwordTask processswordtask;

                // Init stuff...
                processswordtask = new ProcessSwordTask(szImagesFolder, null, null);

                // Run our task...
                processswordtask.BatchMode(Config.Get("scanner", null), szTaskFile, false, ref blSetAppCapabilities);

                // All done...
                return(true);
            }

            // Otherwise let the user interact with us...
            TWAINWorkingGroup.Log.Info("Interactive mode...");
            return(false);
        }