Zum Hauptinhalt springen
Dieser Abschnitt enthält Anweisungen zum Bereitstellen einer FRE 12 for Windows-Anwendung in Azure Cloud Service. Als Beispiel dient ein Worker, der Dateien in einem Container eines Azure Speicherkontos verarbeitet. Zur Implementierung dieses Szenarios wird eine Online-Lizenz verwendet, die eine Verbindung zum Lizenzserver unter *.abbyy.com herstellt.
ABBYY Licensing Service kann jeweils nur eine Online-Lizenz gleichzeitig verwenden.
Das Bereitstellen Ihrer Anwendung in Cloud Service umfasst mehrere Schritte:
  1. Einrichten Ihrer Online-Lizenz, Ihres lokalen Computers und Ihrer Cloud-Instanz anhand der Voraussetzungen
  2. Durchführen der vorbereitenden Schritte vor dem Bereitstellen Ihrer Anwendung
  3. Bereitstellen Ihrer Anwendung in Cloud Service
Siehe die Codebeispiele, die veranschaulichen, wie die Methoden von ABBYY FineReader Engine für die Dokumentverarbeitung verwendet werden.

Voraussetzungen

Online-Lizenz

Um eine Online-Lizenz zu verwenden, sollten Sie die folgenden Informationen vom Vertrieb erhalten:
  • Ihre Customer Project ID
  • eine Token-Datei für die Online-Lizenz
  • das Kennwort für die Token-Datei der Online-Lizenz
Für die Verwendung einer Online-Lizenz müssen an allen Orten, an denen der ABBYY Licensing Service installiert ist, die folgenden Bedingungen erfüllt sein:
  • Aktive Internetverbindung
  • Erlaubte Verbindungen zu *.abbyy.com über Port 443 (HTTPS)
  • GoDaddy-Root-Zertifikat für die Zertifizierungsstelle (Es muss im Zertifikatsspeicher „Vertrauenswürdige Stammzertifizierungsstellen“ des lokalen Computers installiert sein. Ausführliche Informationen zum Zertifikat finden Sie auf der GoDaddy-Website.)

Lokaler Rechner

Bevor Sie Ihren Cloud Service erstellen, verwenden Sie die folgende Spezifikation, um Ihren lokalen Rechner vorzubereiten:
  • Visual Studio 2019 und die zugehörigen Module für die Entwicklung von Anwendungen für Azure (siehe Azure-Features in Visual Studio oder verwenden Sie das Visual Studio-Installationsprogramm, um diese Module herunterzuladen)
  • Cloud Service-Emulatoren und Speicher für einfaches Debugging (weitere Informationen hier; Download über das Visual Studio-Installationsprogramm)
  • Vorlagenlösung für Azure Cloud Service (Extended Preview) mit einem einzelnen Worker-Rollenprojekt (weitere Informationen hier)
  • .NET Framework 4.7.2
  • Azure SDK (Download hier)
  • NuGet-Paket für die Arbeit mit Azure Storage und Blob-Containern – Azure.Storage.Blobs (Download hier)
  • ABBYY FineReader Engine-Wrapper für .NET Framework 4.7 (im Ordner C:\ProgramData\ABBYY\SDK\12\FineReader Engine\Inc.NET interops nach der Developer-Installation)
  • Für die Arbeit mit Blob-Containern überschriebene IFileWriter-Schnittstelle (siehe das Beispiel unten)
  • Azure Storage Explorer (optional – Download hier)

Cloud Service-Instanz

Die Cloud Service-Instanz dient zum Speichern Ihres WorkerRole-Projekts in Azure. Verwenden Sie die folgende Spezifikation, um diese Instanz einzurichten:
  • .NET Framework-Version für Ihren Service
  • PowerShell zum Bereitstellen von ABBYY FineReader Engine
  • NuGet 2.8.5.201 oder höher zum Hochladen des Azure SDK
  • Azure SDK für die Arbeit mit einem Azure Speicherkonto mithilfe von PowerShell

Vorbereitungsschritte

Die Vorbereitungsschritte sind auf Ihrem lokalen Rechner durchzuführen. Wenn Sie diese Schritte abschließen, bereiten Sie alle erforderlichen Einstellungen und Dateien vor, um mit der Bereitstellung Ihrer Anwendung zu beginnen:
  1. Erstellen Sie zwei Archive mit der ABBYY FineReader Engine-Bibliothek und dem Licensing Service (zum Beispiel LibraryPackage.zip und LSPackage.zip). Sie können die Dateiliste mithilfe der Datei FREngineDistribution.csv automatisch erstellen. Verwenden Sie ABBYY FineReader Engine und License Server aus demselben Paket; andernfalls ist die Kompatibilität nicht gewährleistet.
  2. Erstellen Sie das Azure Speicherkonto (in diesem Artikel frestorage). Alle erforderlichen Anleitungen finden Sie auf der Azure-Website.
  3. Erstellen Sie drei Blob-Container in frestorage:
  • fre-lib - für die Dateien von ABBYY FineReader Engine
  • fre-input - für eingehende Dateien
  • fre-output - für die Verarbeitungsergebnisse
  1. Laden Sie LibraryPackage.zip und LSPackage.zip auf die für Sie bequemste Weise in den Container fre-lib hoch (mit .NET, PowerShell, einem Python-Skript oder den Anwendungen Azure Storage Explorer/Azure Portal).
Als Beispiel wird ein WorkerRole-Projekt für die Ausführung in einer konfigurierten Umgebung verwendet. Alle erforderlichen Konfigurationsdateien (.csdef und Cloud.cscfg) werden nach dem Erstellen Ihres Projekts automatisch generiert.

Bereitstellen von ABBYY FineReader Engine in Cloud Service

So stellen Sie ABBYY FineReader Engine in Ihrem neuen WorkerRole-Projekt bereit:
  1. Geben Sie die Parameter in Cloud.cscfg wie gewünscht an.
  2. Geben Sie die Parameter der Datei .csdef an:
  • (optional) Ihre WorkerRole-Einstellungen
  • (optional) die Größe Ihrer virtuellen Maschine
  • (erforderlich) den lokalen Speicher Ihrer Rolle (Abschnitt LocalStorage – in diesem Artikel der Speicher mit dem Namen LocalStorage1). Legen Sie ihn auf mindestens 3 GB fest, damit das ABBYY FineReader Engine-Paket ordnungsgemäß bereitgestellt werden kann.
  • (erforderlich) die Startreihenfolge Ihrer Rolle (verwenden Sie die Codebeispiele und Einstellungen aus dem Abschnitt Codebeispiel)
  1. Implementieren Sie Ihr WorkerRole-Projekt so, dass es Dateien aus dem Container fre-input verarbeitet und die Verarbeitungsergebnisse im Container fre-output ablegt:
  • die Methode OnStart, um Ihren Cloud Service für den Betrieb vorzubereiten. Diese Methode wird verwendet, um die Engine zu initialisieren und das TLS-Protokoll einzurichten.
  • die Methode RunAsync zur zyklischen Verarbeitung der Dateien aus dem Container fre-input. Diese Methode erkennt die Dateien im Container fre-input, verarbeitet sie im Speicher und legt sie im Container fre-output ab (siehe Processor.cs, IFileWriter.cs und Config.cs).
  • die Methode OnStop, um den Betrieb des Cloud Service zu beenden. Diese Methode wird verwendet, um die Engine zu deinitialisieren.

Codebeispiele

Dieser Abschnitt enthält Codebeispiele zum Konfigurieren der Startreihenfolge von Rollen und der Einstellungen von ABBYY FineReader Engine:
  • CleanUpOnStart - löscht die vorherige Version von ABBYY FineReader Engine und vereinfacht deren Aktualisierung (siehe die Auflistung unten in den Dateien CleanUpOnStart.cmd und CleanUpOnStart.ps1).
  • PreparePoShModules - lädt das SDK herunter, das benötigt wird, damit PowerShell mit Azure Storage arbeiten kann (siehe die Auflistung unten in den Dateien PreparePoShModules.cmd und PreparePoShModules.ps1).
  • PrepareLibrary - lädt die ABBYY FineReader Engine-Bibliothek aus dem Container fre-lib in den lokalen Speicher und entpackt sie dort (siehe die Auflistung unten in den Dateien PrepareLibrary.cmd und PrepareLibrary.ps1).
  • PrepareLS - lädt den Licensing Service aus dem Container fre-lib, entpackt ihn und startet ihn (siehe die Auflistung unten in den Dateien PrepareLS.cmd und PrepareLS.ps1).
Die oben aufgeführten Skripte müssen vor dem Starten Ihrer Anwendung genau in der angegebenen Reihenfolge ausgeführt werden. Um die Ausführungsreihenfolge der Skripte festzulegen, geben Sie die folgenden Attribute an:
  • taskType=“simple” - Aufgaben werden synchron nacheinander ausgeführt.
  • executionContext=“elevated” - Ausführen eines Startskripts mit Administratorrechten (erforderlich, um Anwendungen installieren und LicensingService.exe ausführen zu können)
Dadurch wird ein Ordner erstellt, den Cloud Service verwalten kann. Dieser Ordner wird verwendet, um ABBYY FineReader Engine mithilfe der oben aufgeführten Skripte hochzuladen und die FREngine.dll zur weiteren Verwendung im Beispiel zu laden.
rem   Skript zum Bereinigen vorheriger Pakete von ABBYY FineReader Engine und Licensing Service
echo Cleaning up before launching service >> ".\CleanUpOnStart.log" 2>&1
PowerShell -ExecutionPolicy Unrestricted .\StartupScripts\CleanUpOnStart.ps1 >> ".\CleanUpOnStart.log" 2>&1
echo Cleaning up beafore launching service. >> ".\CleanUpOnStart.log" 2>&1
 
exit /B %errorlevel%
Write-Host "CleanUpOnStart.ps1 started...";
# Pfad zum lokalen Speicher (siehe ServiceDefinition.csdef)
$local_storage_name = "LocalStorage1";
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime");
$local_storage_path = ([Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::GetLocalResource($local_storage_name)).RootPath.TrimEnd('\\');
# Licensing Service-Prozess beenden, falls er ausgeführt wird
$processes = Get-Process;
foreach( $process in $processes ) {
    if( $process.Name -eq "LicesingService" ) {
        Stop-Process $process;
    }
}
 
# den Ordner fre_packages bereinigen und neu erstellen
$destination_path = Join-Path -Path $local_storage_path -ChildPath 'fre_packages';
if( Test-Path -Path $destination_path ) {
    Remove-Item $destination_path -Recurse -Force;
}
New-Item -ItemType Directory -Path $destination_path;
# den Eingabeordner bereinigen und neu erstellen
$destination_path = Join-Path -Path $local_storage_path -ChildPath 'Input';
if( Test-Path -Path $destination_path ) {
    Remove-Item $destination_path -Recurse -Force;
}
New-Item -ItemType Directory -Path $destination_path;
# den Ordner Results bereinigen und neu erstellen
$destination_path = Join-Path -Path $local_storage_path -ChildPath 'Results';
if( Test-Path -Path $destination_path ) {
    Remove-Item $destination_path -Recurse -Force;
}
New-Item -ItemType Directory -Path $destination_path;
Write-Host ("Resource folder was cleaned up.");
rem   Skript zum Vorbereiten von Modulen, um eine Verbindung mit dem Speicherkonto herzustellen und ABBYY FineReader Engine- und Licensing Service-Pakete herunterzuladen
 
echo Preparing PoSh Modules >> ".\PreparePoShModules.log" 2>&1
PowerShell -ExecutionPolicy Unrestricted .\StartupScripts\PreparePoShModules.ps1 >> ".\PreparePoShModules.log" 2>&1
echo PoSh Modules wer prepared. >> ".\PreparePoShModules.log" 2>&1
 
exit /B %errorlevel%
# Module installieren
Write-Host "PreparePoShModules.ps1 started...";
# NuGet-Paketanbieter zum Herunterladen von Azure-Modulen installieren
Write-Host "Installing NuGet package provider...";
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force;
 
# Az.Storage-Modul für die Arbeit mit Blob Storage installieren
Write-Host "Installing Az.Storage module...";
Install-Module -Name Az.Storage -Scope CurrentUser -Repository PSGallery -Force -AllowClobber;
Write-Host ("PoSh modules were prepared.");
rem   Skript zum Vorbereiten des ABBYY FineReader Engine-Pakets
echo Preparing Library >> ".\PrepareLibrary.log" 2>&1
PowerShell -ExecutionPolicy Unrestricted .\StartupScripts\PrepareLibrary.ps1 >> ".\PrepareLibrary.log" 2>&1
echo Library was prepared. >> ".\PrepareLibrary.log" 2>&1
exit /B %errorlevel%
Write-Host "PrepareLibrary.ps1 gestartet...";
# Container mit Paketen für ABBYY FineReader Engine und Licensing Service
$container_name = 'fre-lib';
# Verbindungszeichenfolge für das Speicherkonto 
$connection_string = "<connection_string_to_frestorage>";
Write-Host "Konfiguration";
Write-Host ("Containername: " + $container_name);
Write-Host ("Verbindungszeichenfolge: " + $storage_account);
# Verbindung mit dem Speicherkonto herstellen
Write-Host ("Verbindung mit dem Speicherkonto wird hergestellt...");
$storage_account = New-AzStorageContext -ConnectionString $connection_string;
# Blobs abrufen (im Wesentlichen Dateien)
Write-Host ("Blobs aus dem Container werden abgerufen...");
$fre_blobs = Get-AzStorageBlob -Container $container_name -Context $storage_account;
# Pfad zum lokalen Speicher (siehe ServiceDefinition.csdef)
$local_storage_name = "LocalStorage1";
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime");
$local_storage_path = ([Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::GetLocalResource($local_storage_name)).RootPath.TrimEnd('\\');
$destination_path = Join-Path -Path $local_storage_path -ChildPath 'fre_packages';
# nur den benötigten Blob herunterladen
Write-Host ("FRE-Paket aus dem Container wird heruntergeladen...");
foreach( $blob in $fre_blobs ) {
    Write-Host $blob.Name;
    if( $blob.Name -eq "LibraryPackage.zip" ) {
        Write-Host ("Blob wird heruntergeladen: " + $blob.Name + " nach " + $destination_path);
        Get-AzStorageBlobContent -Container $container_name -Blob $blob.Name `
            -Destination (Join-Path -Path $destination_path -ChildPath $blob.Name) -Context $storage_account;
    } else {
        Write-Host ("Blob " + $blob.Name + " wird nicht heruntergeladen.");
    }
}
# heruntergeladenes Paket entpacken (die vorhandene Bibliothek wird dabei zwangsweise überschrieben)
Write-Host ("Bibliothekspaket wird entpackt...");
Expand-Archive -Path (Join-Path -Path $destination_path -ChildPath "LibraryPackage.zip") `
    -DestinationPath (Join-Path -Path $destination_path -ChildPath "LibraryPackage") -Force;
Write-Host ("Bibliothekspaket wurde vorbereitet.");
rem   Skript zum Vorbereiten des Licensing Service-Pakets und zum Starten von LicensingService.exe
echo LS wird vorbereitet >> ".\PrepareLS.log" 2>&1
PowerShell -ExecutionPolicy Unrestricted .\StartupScripts\PrepareLS.ps1 >> ".\PrepareLS.log" 2>&1
echo LS wurde vorbereitet. >> ".\PrepareLS.log" 2>&1
exit /B %errorlevel%
Write-Host "PrepareLS.ps1 wurde gestartet...";
# Container mit Paketen für ABBYY FineReader Engine und Licensing Service
$container_name = 'fre-lib';
# Verbindungszeichenfolge für das Speicherkonto
$connection_string = "<connection_string_to_frestorage>";
Write-Host "Konfiguration";
Write-Host ("Containername: " + $container_name);
Write-Host ("Verbindungszeichenfolge: " + $storage_account);
# Verbindung mit dem Speicherobjekt herstellen
Write-Host ("Verbindung mit dem Speicherkonto wird hergestellt...");
$storage_account = New-AzStorageContext -ConnectionString $connection_string;
# Blobs abrufen (im Grunde Dateien)
Write-Host ("Blobs aus dem Container werden abgerufen...");
$fre_blobs = Get-AzStorageBlob -Container $container_name -Context $storage_account;
# Pfad zum lokalen Speicher (siehe ServiceDefinition.csdef)
$local_storage_name = "LocalStorage1";
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime");
$local_storage_path = ([Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::GetLocalResource($local_storage_name)).RootPath.TrimEnd('\\');
$destination_path = Join-Path -Path $local_storage_path -ChildPath 'fre_packages'; 
# Licensing Service-Paket herunterladen
Write-Host ("Licensing Service-Paket wird aus dem Container heruntergeladen...");
foreach( $blob in $fre_blobs ) {
    Write-Host $blob.Name;
    if( $blob.Name -eq "LSPackage.zip" ) {
        Write-Host ("Blob wird heruntergeladen: " + $blob.Name + " nach " + $destination_path);
        Get-AzStorageBlobContent -Container $container_name -Blob $blob.Name `
            -Destination (Join-Path -Path $destination_path -ChildPath $blob.Name) -Context $storage_account;
    } else {
        Write-Host ("Herunterladen von Blob " + $blob.Name + " wurde übersprungen.");
    }
}
# Heruntergeladenes Paket entpacken
Write-Host ("Bibliothekspaket wird entpackt...");
Expand-Archive -Path (Join-Path -Path $destination_path -ChildPath "LSPackage.zip") `
    -DestinationPath (Join-Path -Path $destination_path -ChildPath "LSPackage") -Force;
# Ordner für Lizenzen erstellen
$program_data_path = [System.Environment]::ExpandEnvironmentVariables("%programdata%");
$path = Join-Path -Path $program_data_path -ChildPath "ABBYY\SDK\12\Licenses";
New-Item -ItemType Directory -Path $path -Force;
# Licensing Service im Standalone-Modus starten
Write-Host ("Licensing Service wird gestartet...");
 
$licensing_service_app = Join-Path -Path $destination_path -ChildPath "LSPackage\LicensingService.exe";
Start-Process -FilePath $licesing_service_app -ArgumentList "/standalone";
Write-Host ("LS-Paket wurde vorbereitet und LS wurde gestartet.");
namespace WorkerRole1.Engine
{
    public class FileWriter : FREngine.IFileWriter, IDisposable
    {
        public FileWriter(string _resultBlobName, string _fileExtension)
        {
            resultBlobName = _resultBlobName;
            fileExtension = _fileExtension;
        }
        public void Open(string fileName, ref int bufferSize)
        {
            stream = new MemoryStream();
        }
        public void Write(byte[] data)
        {
            stream.Write(data, 0, data.Length);
        }
        public void Close() 
        {
            // Verbindung mit einem neuen Blob in <OutputContainerName> herstellen
            // Das Verarbeitungsergebnis wird dort gespeichert
            BlobClient resultBlobClient = new BlobClient(Config.ConnectionString, Config.OutputContainerName,
                resultBlobName + fileExtension);
            // Vorhandene Datei überschreiben
            resultBlobClient.DeleteIfExists();
            // Position auf 0 setzen, damit die Datei von Anfang an geschrieben wird
            stream.Position = 0;
            resultBlobClient.Upload(stream);
 
            stream.Close();
        }
        public void Dispose()
        {
            // MemoryStream beim Freigeben schließen, damit nach dem Schreiben der Daten darauf zugegriffen werden kann
            stream.Close();
        }
        private string resultBlobName;
        private string fileExtension;
        private MemoryStream stream;
    }
}
namespace WorkerRole1
{
    public class WorkerRole : RoleEntryPoint
    {
        private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        private readonly ManualResetEvent runCompleteEvent = new ManualResetEvent(false);
        Processor processor = new Processor();
 
        public override void Run()
        {
            Trace.TraceInformation("WorkerRole1 is running");
 
            try
            {
                this.RunAsync(this.cancellationTokenSource.Token).Wait();
            }
            finally
            {
                this.runCompleteEvent.Set();
            }
        }
        public override bool OnStart()
        {
            // Legen Sie die maximale Anzahl gleichzeitiger Verbindungen fest
            ServicePointManager.DefaultConnectionLimit = 12;
 
            // Setzen Sie TLS auf 12, damit eine Verbindung mit dem Speicherkonto hergestellt werden kann
            System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
 
            // Informationen zum Umgang mit Konfigurationsänderungen
            // finden Sie im entsprechenden MSDN-Thema unter https://go.microsoft.com/fwlink/?LinkId=166357
 
            bool result = base.OnStart();
            Trace.TraceInformation("WorkerRole1 has been started");
 
            processor.LoadEngine();
            return result;
        }
 
        public override void OnStop()
        {
            processor.UnloadEngine();
            Trace.TraceInformation("WorkerRole1 is stopping");
            this.cancellationTokenSource.Cancel();
            this.runCompleteEvent.WaitOne();
            base.OnStop();
            Trace.TraceInformation("WorkerRole1 has stopped");
        }
 
        private async Task RunAsync(CancellationToken cancellationToken)
        {
            // TODO: Ersetzen Sie den folgenden Code durch Ihre eigene Logik
            while (!cancellationToken.IsCancellationRequested)
            {
                Trace.TraceInformation("Working");
 
                try
                {
                    // Erstellen Sie den Container und geben Sie ein Container-Clientobjekt zurück
                    BlobContainerClient inputContainerClient = new BlobContainerClient(Config.ConnectionString, Config.InputContainerName);
                    foreach (BlobItem blobItem in inputContainerClient.GetBlobs())
                    {
                        Trace.TraceInformation("\t" + blobItem.Name);
                        BlobClient blobClient = new BlobClient(Config.ConnectionString, Config.InputContainerName, blobItem.Name);
 
                        Trace.TraceInformation("\t Downloading blob to memory: " + blobItem.Name);
                        MemoryStream memoryStream = new MemoryStream();
                        blobClient.DownloadTo(memoryStream);
                        Trace.TraceInformation("\t Processing in FRE: " + blobItem.Name);
                        string resultBlobName = processor.ProcessImage(memoryStream, blobItem.Name);
                        Trace.TraceInformation("\t Result blob name in output container: " + resultBlobName);
                        Trace.TraceInformation("\t Deleting from input container: " + blobItem.Name);
                        blobClient.Delete();
                    }
                }
                catch (Exception error)
                {
                    Trace.TraceInformation("error: " + error.Message);
                }
 
                await Task.Delay(1000);
            }
        }
    }
}
namespace WorkerRole1
{
    class Processor : IDisposable
    {
        EngineLoader engineLoader = null;
        private void displayMessage(string text)
        {
            File.AppendAllText(".\\FRE.log", text + "\n");
            Trace.TraceInformation("\t" + text );
        }        
        private void loadProfile()
        {
            engineLoader.Engine.LoadPredefinedProfile("DocumentConversion_Accuracy");
        }        
        private void setupFREngine()
        {
            displayMessage("Loading predefined profile...");
            loadProfile();
        }
        public void LoadEngine()
        {
            try {
                if (engineLoader == null)
                {
                    // Derselbe EngineLoader wie im Hello-Beispiel
                    engineLoader = new EngineLoader();
                }
                setupFREngine();
            }
            catch (Exception error)
            {
                displayMessage("error: " + error.Message);
            }
        }
        public void UnloadEngine()
        {
            try
            {
                if (engineLoader != null)
                {
                    engineLoader.Dispose();
                    engineLoader = null;
                }
            }
            catch (Exception error)
            {
                displayMessage("error: " + error.Message);
            }
        }
 
        public string ProcessImage( MemoryStream inputMemoryStream, string inputBlobName )
        {
            FRDocument document = engineLoader.Engine.CreateFRDocument();
            string resultBlobName = "";
            try
            {
               document.PageFlushingPolicy = FREngine.PageFlushingPolicyEnum.PFP_KeepInMemory;
 
                // Bilddatei zum Dokument hinzufügen
                displayMessage("Loading image...");
                IntPtr handle = Marshal.AllocHGlobal(inputMemoryStream.GetBuffer().Length);
                Marshal.Copy(inputMemoryStream.GetBuffer(), 0, handle, inputMemoryStream.GetBuffer().Length);
                document.AddImageFileFromMemory(handle.ToInt64(), null, null);
 
                // Dokument erkennen
                displayMessage("Recognizing...");
                document.Process(null);
 
                // Ergebnisse speichern
                displayMessage("Saving results...");
                // Ergebnisse mit dem Szenario 'balanced' als PDF speichern
                // FREngine.PDFExportParams pdfParams = engineLoader.Engine.CreatePDFExportParams();
                // pdfParams.Scenario = FREngine.PDFExportScenarioEnum.PES_Balanced;
 
                WorkerRole1.Engine.FileWriter fileWriter = new WorkerRole1.Engine.FileWriter(inputBlobName, ".pdf");
                resultBlobName = inputBlobName + ".pdf";
                document.ExportToMemory(fileWriter, FREngine.FileExportFormatEnum.FEF_PDF, null);
 
            }
            catch (Exception error)
            {
                displayMessage("error: " + error.Message);
            }
            finally
            {
                // Dokument schließen
                document.Close();
            }
 
            return resultBlobName;
        }
 
        public void Dispose()
        {
            UnloadEngine();
        }
    }
}
class Config
{
    // Lokaler Speicher, wie in ServiceDefinition.csdef definiert
    private static string LocalStorageName = "LocalStorage1";
    // Verbindungszeichenfolge für den Blob-Container
    public static readonly string ConnectionString = "<connection_string_to_frestorage>";
    // Namen der Eingabe- und Ausgabe-Container in Ihrem Speicher
    public static readonly string InputContainerName = "fre-input";
    public static readonly string OutputContainerName = "fre-output";
 
    // Customer Project ID für ABBYY FineReader Engine zurückgeben
    public static String GetCustomerProjectId()
    {
        return "<Your_Customer_Project_ID>";
    }
 
    // Name des Lizenz-Tokens zurückgeben
    public static String GetLicenseTokenName()
    {
        return "<Token_number>.ABBYY.ActivationToken";
    }
 
    // Lizenz-Kennwort zurückgeben
    public static String GetLicensePassword()
    {
        return "<Your_Online_License_token_password>";
    }
    // Engine-Pfad zurückgeben
    public static String GetEngineFolder()
    {
        string engineSubfolder = "fre_packages\\LibraryPackage\\Bin64";
        string engineDllFolder = Path.Combine(RoleEnvironment.GetLocalResource(LocalStorageName).RootPath, engineSubfolder);
        return engineDllFolder;
    }
}