Passer au contenu principal
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 se connectant au serveur de licences *.abbyy.com est utilisée.
ABBYY Licensing Service ne peut fonctionner qu’avec une seule licence en ligne à la fois.
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
  2. Effectuer les étapes préparatoires avant de déployer votre application
  3. Déployer votre application dans Cloud Service
Voir les exemples de code illustrant l’utilisation des méthodes d’ABBYY FineReader Engine pour le traitement des documents.

Prérequis

Licence en ligne

Pour utiliser une licence en ligne, vous devez recevoir les informations suivantes de la part du service commercial :
  • votre Customer Project ID
  • 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 de GoDaddy.)

Ordinateur local

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 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 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)
  • .NET Framework 4.7.2
  • SDK Azure (téléchargez-le ici)
  • Package NuGet pour utiliser Azure Storage et les conteneurs Blob : Azure.Storage.Blobs (téléchargez-le ici)
  • 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 remplacée pour fonctionner avec des conteneurs Blob (consultez l’exemple ci-dessous)
  • Azure Storage Explorer (facultatif - téléchargez-le ici)

Instance de Cloud Service

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

Étapes préparatoires

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.
  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
  1. 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.

Déploiement d’ABBYY FineReader Engine vers Cloud Service

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)
  1. 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, IFileWriter.cs et Config.cs).
  • la méthode OnStop pour arrêter Cloud Service. Cette méthode sert à désinitialiser l’Engine.

Exemples de code

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 et 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 et PreparePoShModules.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 et 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 et 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.
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%
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.");
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%
# 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.");
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%
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.");
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%
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é.");
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;
    }
}
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);
            }
        }
    }
}
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();
        }
    }
}
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;
    }
}