> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abbyy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Exécution dans Azure Cloud Service

> Déployez ABBYY FineReader Engine 12 pour Windows dans Azure Cloud Service avec un projet de rôle Worker et une licence en ligne qui se connecte aux serveurs de licences ABBYY.

Cette section explique comment déployer une application FRE 12 pour Windows dans Azure Cloud Service. À titre d’exemple, un Worker qui traite des fichiers dans un conteneur d’un compte Azure Storage est présenté.

Pour mettre en œuvre ce scénario, une [licence en ligne](/fr/fine-reader/engine/licensing/online-licensing) se connectant au serveur de licences \*.abbyy.com est utilisée.

<Note>
  ABBYY Licensing Service ne peut fonctionner qu’avec une seule licence en ligne à la fois.
</Note>

Le déploiement de votre application dans Cloud Service comprend plusieurs étapes :

1. Configurer votre licence en ligne, votre machine locale et votre instance cloud en suivant les [prérequis](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#prerequisites)
2. Effectuer [les étapes préparatoires](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#preparatorysteps) avant de déployer votre application
3. [Déployer votre application dans Cloud Service](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#deployingabbyyfinereaderengineincloudservice)

Voir les [exemples de code](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#scripts) illustrant l’utilisation des méthodes d’ABBYY FineReader Engine pour le traitement des documents.

<div id="prerequisites">
  ## Prérequis
</div>

<div id="online-license">
  ### Licence en ligne
</div>

Pour utiliser une licence en ligne, vous devez recevoir les informations suivantes de la part du service commercial :

* votre [Customer Project ID](/fr/fine-reader/engine/api-reference/functions/initializeengine-function#customerprojectid)
* un fichier de jeton de licence en ligne
* le mot de passe du fichier de jeton de licence

Pour utiliser une licence en ligne sur tout système où ABBYY Licensing Service est installé, les conditions suivantes doivent être remplies :

* Une connexion Internet active
* Les connexions à \*.abbyy.com sur le port 443 (HTTPS) doivent être autorisées
* Le certificat racine GoDaddy de l’autorité de certification (il doit être installé dans le magasin de certificats Autorités de certification racines de confiance de l’ordinateur local. Consultez les informations détaillées sur le certificat sur le [site web](http://www.godaddy.com/) de GoDaddy.)

<div id="local-machine">
  ### Ordinateur local
</div>

Avant de créer votre Cloud Service, assurez-vous que votre machine locale répond aux exigences suivantes :

* Visual Studio 2019 et ses modules pour le développement d’applications Azure (consultez [Fonctionnalités Azure dans Visual Studio](http://visualstudio.microsoft.com/vs/features/azure/) ou utilisez Visual Studio Installer pour télécharger ces modules)
* Émulateurs Cloud Service et stockage pour faciliter le débogage (consultez les informations [ici](https://docs.microsoft.com/en-us/visualstudio/azure/vs-azure-tools-debug-cloud-services-virtual-machines?view=vs-2019) et téléchargez-les via Visual Studio Installer)
* Solution modèle pour Azure Cloud Service (extended preview) avec un seul projet de rôle Worker (consultez les informations [ici](https://docs.microsoft.com/en-us/visualstudio/azure/vs-azure-tools-debug-cloud-services-virtual-machines?view=vs-2019))
* .NET Framework 4.7.2
* SDK Azure (téléchargez-le [ici](https://azure.microsoft.com/en-us/downloads/))
* Package NuGet pour utiliser Azure Storage et les conteneurs Blob : Azure.Storage.Blobs (téléchargez-le [ici](https://www.nuget.org/packages/Azure.Storage.Blobs/))
* Wrapper ABBYY FineReader Engine pour .NET Framework 4.7 (dans le dossier C:\ProgramData\ABBYY\SDK\12\FineReader Engine\Inc.NET interops après une installation Developer)
* Interface [IFileWriter](/fr/fine-reader/engine/api-reference/supplementary-objects-and-methods/ifilewriter) remplacée pour fonctionner avec des conteneurs Blob (consultez l’[exemple](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#ifilewriter) ci-dessous)
* Azure Storage Explorer (facultatif - téléchargez-le [ici](http://azure.microsoft.com/en-us/features/storage-explorer/))

<div id="cloud-service-instance">
  ### Instance de Cloud Service
</div>

L’instance de Cloud Service sert à stocker votre projet WorkerRole dans Azure. Utilisez les spécifications suivantes pour configurer cette instance :

* version du .NET Framework de votre service
* PowerShell pour déployer ABBYY FineReader Engine
* NuGet 2.8.5.201 ou version ultérieure pour téléverser le SDK Azure
* SDK Azure pour travailler avec un compte Azure Storage via PowerShell

<div id="preparatory-steps">
  ## Étapes préparatoires
</div>

Les étapes préparatoires doivent être effectuées sur votre machine locale. En les réalisant, vous préparerez tous les paramètres et fichiers nécessaires au déploiement de votre application :

1. Créez deux archives contenant l’ABBYY FineReader Engine Library et le Licensing Service (par exemple, LibraryPackage.zip et LSPackage.zip). Vous pouvez générer automatiquement la liste des fichiers à l’aide du fichier FREngineDistribution.csv. Utilisez ABBYY FineReader Engine et License Server issus du même package ; sinon, la compatibilité n’est pas garantie.
2. Créez le compte de stockage Azure (frestorage dans cet article). Vous trouverez toutes les instructions nécessaires sur le site [Azure](http://docs.microsoft.com/en-us/azure/?product=featured).
3. Créez trois conteneurs Blob dans frestorage :

* fre-lib - pour les fichiers d’ABBYY FineReader Engine
* fre-input - pour les fichiers en entrée
* fre-output - pour les résultats du traitement

4. Téléversez LibraryPackage.zip et LSPackage.zip dans le conteneur fre-lib par la méthode de votre choix (à l’aide de .NET, Powershell, d’un script Python ou des applications Azure Storage Explorer/Azure Portal).

À titre d’exemple, un projet WorkerRole est utilisé dans un environnement configuré. Tous les fichiers de configuration nécessaires (.csdef et Cloud.cscfg) sont générés automatiquement après la création de votre projet.

<div id="deploying-abbyy-finereader-engine-to-cloud-service">
  ## Déploiement d’ABBYY FineReader Engine vers Cloud Service
</div>

Pour déployer ABBYY FineReader Engine dans votre nouveau projet WorkerRole :

1. Spécifiez les paramètres de Cloud.cscfg selon vos besoins.
2. Spécifiez les paramètres du fichier .csdef :

* (facultatif) les paramètres de votre WorkerRole
* (facultatif) la taille de votre machine virtuelle
* (obligatoire) le stockage local de votre rôle (section LocalStorage — dans cet article, le stockage nommé LocalStorage1). Définissez-le sur au moins 3 Go afin de garantir le déploiement correct du package ABBYY FineReader Engine.
* (obligatoire) l’ordre de démarrage de votre rôle (utilisez les exemples de code et les paramètres de la section [exemples de code](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#scripts))

3. Implémentez votre projet WorkerRole pour traiter les fichiers du conteneur fre-input et publier les résultats du traitement dans le conteneur fre-output :

* la méthode OnStart pour préparer votre Cloud Service au fonctionnement. Cette méthode sert à initialiser l’Engine et à configurer le protocole TLS.
* la méthode RunAsync pour traiter en boucle les fichiers récupérés du conteneur fre-input. Cette méthode détecte les fichiers dans le conteneur fre-input, les traite en mémoire, puis les place dans le conteneur fre-output (voir [Processor.cs](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#processor.cs), [IFileWriter.cs](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#ifilewriter) et [Config.cs](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#config)).
* la méthode OnStop pour arrêter Cloud Service. Cette méthode sert à désinitialiser l’Engine.

<div id="code-samples">
  ## Exemples de code
</div>

Cette section comprend des exemples de code utilisés pour configurer l’ordre de démarrage des rôles et les paramètres d’ABBYY FineReader Engine :

* CleanUpOnStart - supprime la version précédente d’ABBYY FineReader Engine et simplifie sa procédure de mise à jour (voir son contenu dans les fichiers [CleanUpOnStart.cmd](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#cleanuponstart.cmd) et [CleanUpOnStart.ps1](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#cleanuponstart.ps1) ci-dessous).
* PreparePoShModules - télécharge le SDK nécessaire pour que PowerShell fonctionne avec Azure Storage (voir son contenu dans les fichiers [PreparePoShModules.cmd](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#prepareposhmodules.cmd) et [PreparePoShModules.ps1](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#preparemodules.ps1) ci-dessous).
* PrepareLibrary - téléverse et décompresse la bibliothèque ABBYY FineReader Engine depuis le conteneur fre-lib vers le stockage local (voir son contenu dans les fichiers [PrepareLibrary.cmd](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#preparelibrary.cmd) et [PrepareLibrary.ps1](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#preparelibrary.ps1) ci-dessous).
* PrepareLS - téléverse, décompresse et lance le Licensing Service depuis le conteneur fre-lib (voir son contenu dans les fichiers [PrepareLS.cmd](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#preparels.cmd) et [PrepareLS.ps1](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#preparels.ps1) ci-dessous).

Les scripts listés ci-dessus doivent être exécutés exactement dans l’ordre indiqué, avant le lancement de votre application. Pour personnaliser l’ordre d’exécution des scripts, spécifiez les attributs suivants :

* taskType="simple" - les tâches sont exécutées de manière synchrone, une à la fois.
* executionContext="elevated" - exécution d’un script de démarrage avec des droits administrateur (requise pour pouvoir installer une application et exécuter LicensingService.exe)

Ainsi, un dossier que Cloud Service pourra gérer sera créé. Ce dossier est utilisé pour téléverser ABBYY FineReader Engine à l’aide des scripts listés ci-dessus et charger FREngine.dll en vue de son utilisation ultérieure dans l’[exemple](/fr/fine-reader/engine/distribution/distribution-windows/running-abbyy-finereader-engine-inside-azure-services/running-in-azure-cloud-service#processingsample).

<Accordion title="CleanUpOnStart.cmd">
  ```
  rem   Script pour nettoyer les packages précédents d’ABBYY FineReader Engine et du 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%
  ```
</Accordion>

<Accordion title="CleanUpOnStart.ps1">
  ```
  Write-Host "CleanUpOnStart.ps1 started...";
  # chemin vers le stockage local (voir 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('\\');
  # arrêt du processus Licensing Service s'il était en cours d'exécution
  $processes = Get-Process;
  foreach( $process in $processes ) {
      if( $process.Name -eq "LicesingService" ) {
          Stop-Process $process;
      }
  }
   
  # nettoyage et recréation du dossier fre_packages
  $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;
  # nettoyage et recréation du dossier Input
  $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;
  # nettoyage et recréation du dossier Results
  $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.");
  ```
</Accordion>

<Accordion title="PreparePoShModules.cmd">
  ```
  rem   Script pour préparer les modules afin de pouvoir se connecter au compte de stockage et télécharger les packages ABBYY FineReader Engine et Licensing Service
   
  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%
  ```
</Accordion>

<Accordion title="PreparePoShModules.ps1">
  ```bash theme={null}
  # installation des modules
  Write-Host "PreparePoShModules.ps1 started...";
  # installation du fournisseur de packages NuGet pour télécharger les modules Azure
  Write-Host "Installing NuGet package provider...";
  Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force;
   
  # installation du module Azure Storage pour utiliser l’objet blob
  Write-Host "Installing Az.Storage module...";
  Install-Module -Name Az.Storage -Scope CurrentUser -Repository PSGallery -Force -AllowClobber;
  Write-Host ("PoSh modules were prepared.");
  ```
</Accordion>

<Accordion title="PrepareLibrary.cmd">
  ```
  rem   Script pour préparer le package ABBYY FineReader Engine
  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%
  ```
</Accordion>

<Accordion title="PrepareLibrary.ps1">
  ```
  Write-Host "PrepareLibrary.ps1 started...";
  # conteneur avec les packages ABBYY FineReader Engine et Licensing Service
  $container_name = 'fre-lib';
  # chaîne de connexion au compte de stockage
  $connection_string = "<connection_string_to_frestorage>";
  Write-Host "Configuration";
  Write-Host ("Container name: " + $container_name);
  Write-Host ("Connection string: " + $storage_account);
  # connexion à l'objet de stockage
  Write-Host ("Connecting to storage account...");
  $storage_account = New-AzStorageContext -ConnectionString $connection_string;
  # récupération des blobs (c'est-à-dire des fichiers)
  Write-Host ("Getting blobs from container...");
  $fre_blobs = Get-AzStorageBlob -Container $container_name -Context $storage_account;
  # chemin d'accès au stockage local (voir 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';
  # téléchargement du seul blob requis
  Write-Host ("Downloading FRE package from container...");
  foreach( $blob in $fre_blobs ) {
      Write-Host $blob.Name;
      if( $blob.Name -eq "LibraryPackage.zip" ) {
          Write-Host ("Downloading blob: " + $blob.Name + "to " + $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 ("Downloading blob " + $blob.Name + " was skipped.");
      }
  }
  # décompression du package téléchargé (l'ancienne bibliothèque sera écrasée de force)
  Write-Host ("Unzipping library package...");
  Expand-Archive -Path (Join-Path -Path $destination_path -ChildPath "LibraryPackage.zip") `
      -DestinationPath (Join-Path -Path $destination_path -ChildPath "LibraryPackage") -Force;
  Write-Host ("Library package was prepared.");
  ```
</Accordion>

<Accordion title="PrepareLS.cmd">
  ```
  rem   Script pour préparer le package Licensing Service et démarrer LicensingService.exe
  echo Preparing LS >> ".\PrepareLS.log" 2>&1
  PowerShell -ExecutionPolicy Unrestricted .\StartupScripts\PrepareLS.ps1 >> ".\PrepareLS.log" 2>&1
  echo LS was prepared. >> ".\PrepareLS.log" 2>&1
  exit /B %errorlevel%
  ```
</Accordion>

<Accordion title="PrepareLS.ps1">
  ```
  Write-Host "Démarrage de PrepareLS.ps1...";
  # conteneur avec les packages ABBYY FineReader Engine et Licensing Service
  $container_name = 'fre-lib';
  # chaîne de connexion du compte de stockage
  $connection_string = "<connection_string_to_frestorage>";
  Write-Host "Configuration";
  Write-Host ("Nom du conteneur : " + $container_name);
  Write-Host ("Chaîne de connexion : " + $storage_account);
  # connexion à l’objet de stockage
  Write-Host ("Connexion au compte de stockage...");
  $storage_account = New-AzStorageContext -ConnectionString $connection_string;
  # récupération des blobs (essentiellement des fichiers)
  Write-Host ("Récupération des blobs depuis le conteneur...");
  $fre_blobs = Get-AzStorageBlob -Container $container_name -Context $storage_account;
  # chemin vers le stockage local (voir 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'; 
  # téléchargement du package Licensing Service
  Write-Host ("Téléchargement du package Licensing Service depuis le conteneur...");
  foreach( $blob in $fre_blobs ) {
      Write-Host $blob.Name;
      if( $blob.Name -eq "LSPackage.zip" ) {
          Write-Host ("Téléchargement du blob : " + $blob.Name + " vers " + $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 ("Le téléchargement du blob " + $blob.Name + " a été ignoré.");
      }
  }
  # décompression du package téléchargé
  Write-Host ("Décompression du package de bibliothèque...");
  Expand-Archive -Path (Join-Path -Path $destination_path -ChildPath "LSPackage.zip") `
      -DestinationPath (Join-Path -Path $destination_path -ChildPath "LSPackage") -Force;
  # création des dossiers pour les licences
  $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;
  # démarrage de Licensing Service en mode autonome
  Write-Host ("Démarrage de Licensing Service...");
   
  $licensing_service_app = Join-Path -Path $destination_path -ChildPath "LSPackage\LicensingService.exe";
  Start-Process -FilePath $licesing_service_app -ArgumentList "/standalone";
  Write-Host ("Le package LS a été préparé et LS a été démarré.");
  ```
</Accordion>

<Accordion title="Implémentation de l’interface IFileWriter">
  ```csharp theme={null}
  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() 
          {
              // Création d’une connexion à un nouveau blob dans <OutputContainerName>
              // Le résultat du traitement y sera stocké
              BlobClient resultBlobClient = new BlobClient(Config.ConnectionString, Config.OutputContainerName,
                  resultBlobName + fileExtension);
              // Remplacer le fichier existant
              resultBlobClient.DeleteIfExists();
              // Définir la position à 0 pour écrire le fichier depuis le début
              stream.Position = 0;
              resultBlobClient.Upload(stream);
   
              stream.Close();
          }
          public void Dispose()
          {
              // Fermer le flux mémoire lors de la libération pour pouvoir y accéder après l’écriture des données
              stream.Close();
          }
          private string resultBlobName;
          private string fileExtension;
          private MemoryStream stream;
      }
  }
  ```
</Accordion>

<Accordion title="Exemple de traitement des fichiers avec ABBYY FineReader Engine">
  ```csharp theme={null}
  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 est en cours d’exécution");
   
              try
              {
                  this.RunAsync(this.cancellationTokenSource.Token).Wait();
              }
              finally
              {
                  this.runCompleteEvent.Set();
              }
          }
          public override bool OnStart()
          {
              // Définir le nombre maximal de connexions simultanées
              ServicePointManager.DefaultConnectionLimit = 12;
   
              // Définir TLS sur 1.2 pour pouvoir se connecter au compte de stockage
              System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
   
              // Pour plus d’informations sur la gestion des changements de configuration
              // consultez la rubrique MSDN à l’adresse https://go.microsoft.com/fwlink/?LinkId=166357
   
              bool result = base.OnStart();
              Trace.TraceInformation("WorkerRole1 a démarré");
   
              processor.LoadEngine();
              return result;
          }
   
          public override void OnStop()
          {
              processor.UnloadEngine();
              Trace.TraceInformation("WorkerRole1 est en cours d’arrêt");
              this.cancellationTokenSource.Cancel();
              this.runCompleteEvent.WaitOne();
              base.OnStop();
              Trace.TraceInformation("WorkerRole1 s’est arrêté");
          }
   
          private async Task RunAsync(CancellationToken cancellationToken)
          {
              // TODO : remplacez ce qui suit par votre propre logique
              while (!cancellationToken.IsCancellationRequested)
              {
                  Trace.TraceInformation("En cours de traitement");
   
                  try
                  {
                      // Créer le conteneur et renvoyer un objet client de conteneur
                      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 Téléchargement du blob en mémoire : " + blobItem.Name);
                          MemoryStream memoryStream = new MemoryStream();
                          blobClient.DownloadTo(memoryStream);
                          Trace.TraceInformation("\t Traitement dans FRE : " + blobItem.Name);
                          string resultBlobName = processor.ProcessImage(memoryStream, blobItem.Name);
                          Trace.TraceInformation("\t Nom du blob de résultat dans le conteneur de sortie : " + resultBlobName);
                          Trace.TraceInformation("\t Suppression du conteneur d’entrée : " + blobItem.Name);
                          blobClient.Delete();
                      }
                  }
                  catch (Exception error)
                  {
                      Trace.TraceInformation("erreur : " + error.Message);
                  }
   
                  await Task.Delay(1000);
              }
          }
      }
  }
  ```
</Accordion>

<Accordion title="Processor.cs">
  ```csharp theme={null}
  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)
                  {
                      // Le même EngineLoader que dans l’exemple Hello
                      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;
   
                  // Ajouter le fichier image au document
                  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);
   
                  // Reconnaître le document
                  displayMessage("Recognizing...");
                  document.Process(null);
   
                  // Enregistrer les résultats
                  displayMessage("Saving results...");
                  // Enregistrer les résultats au format PDF avec le scénario « balanced »
                  // 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
              {
                  // Fermer le document
                  document.Close();
              }
   
              return resultBlobName;
          }
   
          public void Dispose()
          {
              UnloadEngine();
          }
      }
  }
  ```
</Accordion>

<Accordion title="Config.cs">
  ```
  class Config
  {
      // Stockage local tel que défini dans ServiceDefinition.csdef
      private static string LocalStorageName = "LocalStorage1";
      // Chaîne de connexion au conteneur Blob
      public static readonly string ConnectionString = "<connection_string_to_frestorage>";
      // Noms des conteneurs d’entrée et de sortie dans votre stockage
      public static readonly string InputContainerName = "fre-input";
      public static readonly string OutputContainerName = "fre-output";
   
      // Retourne le Customer Project ID pour ABBYY FineReader Engine
      public static String GetCustomerProjectId()
      {
          return "<Your_Customer_Project_ID>";
      }
   
      // Retourne le nom du jeton de licence
      public static String GetLicenseTokenName()
      {
          return "<Token_number>.ABBYY.ActivationToken";
      }
   
      // Retourne le mot de passe de la licence
      public static String GetLicensePassword()
      {
          return "<Your_Online_License_token_password>";
      }
      // Retourne le dossier du moteur
      public static String GetEngineFolder()
      {
          string engineSubfolder = "fre_packages\\LibraryPackage\\Bin64";
          string engineDllFolder = Path.Combine(RoleEnvironment.GetLocalResource(LocalStorageName).RootPath, engineSubfolder);
          return engineDllFolder;
      }
  }
  ```
</Accordion>
