Verschiedene Möglichkeiten zum Laden des Engine-Objekts
Dieses Thema gilt für FRE unter Windows.
Es gibt drei Möglichkeiten, das Engine-Objekt in ABBYY FineReader Engine 12 zu laden. Jede dieser Methoden hat ihre eigenen Besonderheiten, die sich je nach Einsatzszenario auf die Verwendung des Objekts auswirken. Die ersten beiden Methoden eignen sich am besten für interaktive Anwendungen, die nicht für die gleichzeitige Verarbeitung mehrerer Anfragen ausgelegt sind. Die dritte Methode eignet sich am besten für Serverlösungen.
FREngine.dll manuell laden und mit „nackten“ Schnittstellen arbeiten
Dies ist die Standardmethode zum Laden des Engine-Objekts. Um eine Referenz auf das Engine-Objekt zu erhalten, rufen Sie die Funktion InitializeEngine auf.
Bei der Arbeit mit höheren Programmiersprachen (z. B. .NET) müssen Low-Level-Methoden verwendet werden, um dynamische Bibliotheken zu laden und die darin exportierten Funktionen aufzurufen.
C#-Code
public class EngineLoader : IDisposable{ public EngineLoader() { // Initialisieren Sie diese Variablen mit dem vollständigen Pfad zu FREngine.dll, Ihrer Customer Project ID // und gegebenenfalls dem Pfad zu Ihrer Online-Lizenz-Token-Datei sowie dem Kennwort der Online-Lizenz string enginePath = ""; string customerProjectId = ""; string licensePath = ""; string licensePassword = ""; // Die Bibliothek FREngine.dll laden dllHandle = LoadLibraryEx(enginePath, IntPtr.Zero, LOAD_WITH_ALTERED_SEARCH_PATH); try { if (dllHandle == IntPtr.Zero) { throw new Exception("Can't load " + enginePath); } IntPtr initializeEnginePtr = GetProcAddress(dllHandle, "InitializeEngine"); if (initializeEnginePtr == IntPtr.Zero) { throw new Exception("Can't find InitializeEngine function"); } IntPtr deinitializeEnginePtr = GetProcAddress(dllHandle, "DeinitializeEngine"); if (deinitializeEnginePtr == IntPtr.Zero) { throw new Exception("Can't find DeinitializeEngine function"); } IntPtr dllCanUnloadNowPtr = GetProcAddress(dllHandle, "DllCanUnloadNow"); if (dllCanUnloadNowPtr == IntPtr.Zero) { throw new Exception("Can't find DllCanUnloadNow function"); } // Zeiger in Delegaten umwandeln initializeEngine = (InitializeEngine)Marshal.GetDelegateForFunctionPointer( initializeEnginePtr, typeof(InitializeEngine)); deinitializeEngine = (DeinitializeEngine)Marshal.GetDelegateForFunctionPointer( deinitializeEnginePtr, typeof(DeinitializeEngine)); dllCanUnloadNow = (DllCanUnloadNow)Marshal.GetDelegateForFunctionPointer( dllCanUnloadNowPtr, typeof(DllCanUnloadNow)); // Die Funktion InitializeEngine aufrufen // und dabei den Pfad zur Online-Lizenz-Datei und das Kennwort der Online-Lizenz übergeben int hresult = initializeEngine(customerProjectId, licensePath, licensePassword, "", "", false, ref engine); Marshal.ThrowExceptionForHR(hresult); } catch (Exception) { // Die Bibliothek FREngine.dll freigeben engine = null; // Alle Objekte vor dem Aufruf von FreeLibrary löschen GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); FreeLibrary(dllHandle); dllHandle = IntPtr.Zero; initializeEngine = null; deinitializeEngine = null; dllCanUnloadNow = null; throw; } } // Funktionen aus Kernel32.dll [DllImport("kernel32.dll")] private static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr reserved, uint flags); private const uint LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008; [DllImport("kernel32.dll")] private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); [DllImport("kernel32.dll")] private static extern bool FreeLibrary(IntPtr hModule); // Funktionen aus FREngine.dll [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)] private delegate int InitializeEngine(string customerProjectId, string licensePath, string licensePassword, string tempFolder, string dataFolder, bool isSharedCPUCoresMode, ref FREngine.IEngine engine); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int DeinitializeEngine(); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int DllCanUnloadNow(); // Private Variablen private FREngine.IEngine engine = null; // Handle für FREngine.dll private IntPtr dllHandle = IntPtr.Zero; private InitializeEngine initializeEngine = null; private DeinitializeEngine deinitializeEngine = null; private DllCanUnloadNow dllCanUnloadNow = null;}
Laden des Engine-Objekts per COM in den aktuellen Prozess
Die Engine wird als In-Process-Server in denselben Prozess geladen, in dem die Anwendung ausgeführt wird. Das Engine-Objekt wird über das Objekt InprocLoader geladen, das die Schnittstelle IEngineLoader implementiert.
Vorteile
Einschränkungen
Alle Objekte von ABBYY FineReader Engine sind vollständig thread-sicher und können in verschiedenen Threads erstellt und verwendet werden.
Bei der Arbeit aus dem Main-STA-Apartment entspricht die Leistung der Arbeit mit den nackten Schnittstellen. Beim Zugriff aus verschiedenen Threads kann Marshalling-Overhead auftreten, dieser ist in den meisten Szenarien jedoch vernachlässigbar.
Bei der Installation der fertigen Anwendung auf dem Computer eines Endbenutzers muss FREngine.dll registriert werden.
Um FREngine.dll bei der Installation Ihrer Anwendung auf dem Computer eines Endbenutzers zu registrieren, verwenden Sie das Dienstprogramm regsvr32. Wenn Sie ein 64-Bit-Betriebssystem verwenden, wird standardmäßig die 64-Bit-Version von regsvr32 ausgeführt. Verwenden Sie die folgende Befehlszeile:
regsvr32 /s /n /i:"<path to the Inc folder>" "<path to FREngine.dll>"
Laden des Engine-Objekts mithilfe von COM in einen separaten Prozess
Die Engine wird als Out-of-Process-Server in einen separaten Prozess geladen. Das Engine-Objekt wird mithilfe des Objekts OutprocLoader geladen, das die Schnittstelle IEngineLoader implementiert.
Vorteile
Einschränkungen
Alle Objekte von ABBYY FineReader Engine sind vollständig threadsicher. Jede Instanz der Engine wird parallel zu den anderen in einem separaten Prozess ausgeführt.
Es kann ein Pool von Prozessoren eingerichtet werden, um die CPU-Leistung des Computers vollständig auszuschöpfen.
Es entsteht ein geringer Marshalling-Overhead.
Bei der Installation der fertigen Anwendung auf dem Computer eines Endbenutzers muss FREngine.dll registriert werden.
Bei der Arbeit unter Konten mit eingeschränkten Berechtigungen müssen die erforderlichen Berechtigungen erteilt werden.
Es ist nicht möglich, auf ein Seitenbild als HBITMAP zuzugreifen.
Kann nicht mit Visual Components verwendet werden, da diese nicht mit mehreren Prozessen funktionieren.
Diese Art, das Engine-Objekt zu laden, wird insbesondere im Codebeispiel EnginesPool verwendet, das eine wiederverwendbare Lösung für Multithreading-Anwendungen bietet.
Kontoberechtigungen können mit dem Dienstprogramm DCOM Config eingerichtet werden (geben Sie entweder DCOMCNFG in der Befehlszeile ein oder wählen Sie Control Panel > Administrative Tools > Component Services). Suchen Sie in der Konsolenstruktur den Ordner Component Services > Computers > My Computer > DCOM Config, klicken Sie mit der rechten Maustaste auf ABBYY FineReader Engine 12.5 Loader (Local Server), und klicken Sie auf Properties. Ein Dialogfeld wird geöffnet. Klicken Sie auf die Registerkarte Security. Klicken Sie unter Launch Permissions auf Customize und dann auf Edit, um die Konten anzugeben, die die Anwendung starten dürfen.
Beachten Sie, dass auf einem 64-Bit-Betriebssystem die registrierte DCOM-Anwendung in der 32-Bit-MMC-Konsole verfügbar ist, die mit der folgenden Befehlszeile ausgeführt werden kann:
"mmc comexp.msc /32"
Um FREngine.dll bei der Installation Ihrer Anwendung auf dem Computer des Endbenutzers zu registrieren, verwenden Sie das Tool regsvr32. Wenn Sie ein 64-Bit-Betriebssystem verwenden, wird standardmäßig die 64-Bit-Version von regsvr32 ausgeführt. Verwenden Sie die folgende Befehlszeile:
regsvr32 /s /n /i:"<path to the Inc folder>" "<path to FREngine.dll>"
Wir empfehlen, zum Debuggen und Ausführen Ihrer Serveranwendung eine Netzwerklizenz zu verwenden.
Außerdem können Sie über die Schnittstelle IHostProcessControl die Priorität eines Hostprozesses festlegen und steuern, ob er ausgeführt wird.