Vai al contenuto principale
Questa sezione fornisce istruzioni su come distribuire un’applicazione FRE 12 per Windows in Azure Cloud Service. Come esempio, viene mostrato un Worker che elabora file tramite un contenitore in un account di archiviazione di Azure. Per implementare questo scenario, viene utilizzata una licenza online che si connette al server di licenze *.abbyy.com.
ABBYY Licensing Service può funzionare solo con una licenza online alla volta.
La distribuzione dell’applicazione in Cloud Service comprende diversi passaggi:
  1. Configurare la licenza online, il computer locale e l’istanza cloud usando i prerequisiti
  2. Eseguire i passaggi preparatori prima di distribuire l’applicazione
  3. Distribuire l’applicazione in Cloud Service
Consulta gli esempi di codice che illustrano come utilizzare i metodi di ABBYY FineReader Engine per l’elaborazione dei documenti.

Prerequisiti

Licenza online

Per usare una licenza online, dovresti ricevere dal reparto vendite le seguenti informazioni:
  • il tuo Customer Project ID
  • un file token della licenza online
  • la password del file token di licenza
Per usare una licenza online su qualsiasi computer in cui sia installato ABBYY Licensing Service, devono essere soddisfatte le seguenti condizioni:
  • Connessione Internet attiva
  • Connessioni consentite a *.abbyy.com sulla porta 443 (HTTPS)
  • Certificato radice GoDaddy per l’autorità di certificazione (deve essere installato nell’archivio certificati Autorità di certificazione radice attendibili del computer locale. Per informazioni dettagliate sul certificato, vedi il sito web di GoDaddy).

Computer locale

Prima di creare il tuo Cloud Service, usa le specifiche seguenti per predisporre il computer locale:
  • Visual Studio 2019 e i relativi moduli per sviluppare applicazioni per Azure (consulta la funzionalità Azure in Visual Studio oppure usa Visual Studio Installer per scaricare questi moduli)
  • Emulatori e spazio di archiviazione di Cloud Service per semplificare il debug (vedi le informazioni qui e scarica tramite Visual Studio Installer)
  • Soluzione modello per Azure Cloud Service (extended preview) con un singolo progetto Worker role (vedi le informazioni qui)
  • .NET Framework 4.7.2
  • Azure SDK (scarica qui)
  • Pacchetto NuGet per lavorare con Azure Storage e i blob contenitori - Azure.Storage.Blobs (scarica qui)
  • Wrapper di ABBYY FineReader Engine per .NET Framework 4.7 (nella cartella C:\ProgramData\ABBYY\SDK\12\FineReader Engine\Inc.NET interops dopo l’installazione per sviluppatori)
  • Interfaccia IFileWriter con override per lavorare con i blob contenitori (vedi l’esempio sotto)
  • Azure Storage Explorer (facoltativo - scarica qui)

Istanza di Cloud Service

L’istanza di Cloud Service serve a ospitare il progetto WorkerRole in Azure. Usa le specifiche seguenti per configurare questa istanza:
  • versione di .NET Framework del servizio
  • PowerShell per distribuire ABBYY FineReader Engine
  • NuGet 2.8.5.201 o versioni successive per caricare Azure SDK
  • Azure SDK per lavorare con un account di archiviazione di Azure tramite PowerShell

Passaggi preparatori

I passaggi preparatori devono essere eseguiti sul computer locale. Completandoli, predisporrai tutte le impostazioni e i file necessari per iniziare la distribuzione dell’applicazione:
  1. Crea due archivi contenenti ABBYY FineReader Engine Library e Licensing Service (ad esempio, LibraryPackage.zip e LSPackage.zip). Puoi generare automaticamente l’elenco dei file con l’aiuto del file FREngineDistribution.csv. Usa ABBYY FineReader Engine e License Server dello stesso pacchetto; in caso contrario, la compatibilità non è garantita.
  2. Crea l’account di archiviazione di Azure (frestorage in questo articolo). Tutte le istruzioni necessarie sono disponibili sul sito web di Azure.
  3. Crea tre contenitori Blob all’interno di frestorage:
  • fre-lib - per i file di ABBYY FineReader Engine
  • fre-input - per i file in ingresso
  • fre-output - per i risultati dell’elaborazione
  1. Carica LibraryPackage.zip e LSPackage.zip nel contenitore fre-lib nel modo che ritieni più pratico (usando .NET, Powershell, uno script Python oppure le applicazioni Azure Storage Explorer/Azure Portal).
Come esempio, viene usato un progetto WorkerRole per operare in un ambiente configurato. Tutti i file di configurazione necessari (.csdef e Cloud.cscfg) vengono generati automaticamente dopo la creazione del progetto.

Distribuire ABBYY FineReader Engine in Cloud Service

Per distribuire ABBYY FineReader Engine nel nuovo progetto WorkerRole:
  1. Specifica i parametri di Cloud.cscfg in base alle esigenze.
  2. Specifica i parametri del file .csdef:
  • (facoltativo) le impostazioni di WorkerRole
  • (facoltativo) le dimensioni della macchina virtuale
  • (obbligatorio) l’archiviazione locale del ruolo (sezione LocalStorage; in questo articolo, l’archiviazione denominata LocalStorage1). Impostala ad almeno 3 GB per garantire la corretta distribuzione del pacchetto ABBYY FineReader Engine.
  • (obbligatorio) l’ordine di avvio del ruolo (usa gli esempi di codice e le impostazioni della sezione code samples)
  1. Implementa il progetto WorkerRole per elaborare i file dal contenitore fre-input e pubblicare i risultati dell’elaborazione nel contenitore fre-output:
  • il metodo OnStart per preparare Cloud Service all’esecuzione. Questo metodo viene usato per inizializzare l’Engine e configurare il protocollo TLS.
  • il metodo RunAsync per elaborare ciclicamente i file prelevati dal contenitore fre-input. Questo metodo rileva i file nel contenitore fre-input, li elabora in memoria e li colloca nel contenitore fre-output (vedi Processor.cs, IFileWriter.cs e Config.cs).
  • il metodo OnStop per terminare l’esecuzione di Cloud Service. Questo metodo viene usato per deinizializzare l’Engine.

Esempi di codice

Questa sezione include esempi di codice usati per configurare l’ordine di avvio dei ruoli e le impostazioni di ABBYY FineReader Engine:
  • CleanUpOnStart - elimina la versione precedente di ABBYY FineReader Engine e ne semplifica la procedura di aggiornamento (vedi il relativo contenuto nei file CleanUpOnStart.cmd e CleanUpOnStart.ps1 riportati di seguito).
  • PreparePoShModules - scarica l’SDK necessario affinché PowerShell possa funzionare con Azure Storage (vedi il relativo contenuto nei file PreparePoShModules.cmd e PreparePoShModules.ps1 riportati di seguito).
  • PrepareLibrary - carica ed estrae ABBYY FineReader Engine Library dal contenitore fre-lib nell’archiviazione locale (vedi il relativo contenuto nei file PrepareLibrary.cmd e PrepareLibrary.ps1 riportati di seguito).
  • PrepareLS - carica, estrae e avvia il Licensing Service dal contenitore fre-lib (vedi il relativo contenuto nei file PrepareLS.cmd e PrepareLS.ps1 riportati di seguito).
È necessario che gli script elencati sopra vengano eseguiti esattamente nell’ordine proposto, prima di avviare l’applicazione. Per definire l’ordine di esecuzione degli script, specifica i seguenti attributi:
  • taskType=“simple” - le attività vengono eseguite in modo sincrono, una alla volta.
  • executionContext=“elevated” - esegue uno script di avvio con diritti di amministratore (necessario per poter installare qualsiasi applicazione ed eseguire LicensingService.exe)
In questo modo, verrà creata una cartella che Cloud Service può gestire. Questa cartella viene usata per caricare ABBYY FineReader Engine tramite gli script elencati sopra e per caricare FREngine.dll in vista del suo successivo utilizzo nell’esempio.
rem   Script to clean up previous ABBYY FineReader Engine and Licensing Service packages
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...";
# percorso dell'archiviazione locale (vedere 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('\\');
# arresta il processo Licensing Service se è in esecuzione
$processes = Get-Process;
foreach( $process in $processes ) {
    if( $process.Name -eq "LicesingService" ) {
        Stop-Process $process;
    }
}
 
# pulisce e ricrea la cartella 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;
# pulisce e ricrea la cartella 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;
# pulisce e ricrea la cartella 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 per preparare i moduli, in modo da potersi connettere all'account di archiviazione di Azure e scaricare i pacchetti di ABBYY FineReader Engine e 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%
# installazione dei moduli
Write-Host "PreparePoShModules.ps1 started...";
# installazione del provider di pacchetti NuGet per scaricare i moduli Azure
Write-Host "Installing NuGet package provider...";
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force;
 
# installazione del modulo Azure Storage per usare il 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 per preparare il pacchetto 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 avviato...";
# contenitore con i pacchetti di ABBYY FineReader Engine e Licensing Service
$container_name = 'fre-lib';
# stringa di connessione dell'account di archiviazione di Azure 
$connection_string = "<connection_string_to_frestorage>";
Write-Host "Configurazione";
Write-Host ("Nome del contenitore: " + $container_name);
Write-Host ("Stringa di connessione: " + $storage_account);
# connessione all'oggetto di archiviazione
Write-Host ("Connessione all'account di archiviazione di Azure...");
$storage_account = New-AzStorageContext -ConnectionString $connection_string;
# recupero dei blob (in pratica, file)
Write-Host ("Recupero dei blob dal contenitore...");
$fre_blobs = Get-AzStorageBlob -Container $container_name -Context $storage_account;
# percorso dell'archiviazione locale (vedere 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';
# download dell'unico blob necessario
Write-Host ("Download del pacchetto FRE dal contenitore...");
foreach( $blob in $fre_blobs ) {
    Write-Host $blob.Name;
    if( $blob.Name -eq "LibraryPackage.zip" ) {
        Write-Host ("Download del blob: " + $blob.Name + " in " + $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 ("Download del blob " + $blob.Name + " ignorato.");
    }
}
# decompressione del pacchetto scaricato (la libreria precedente verrà sovrascritta forzatamente)
Write-Host ("Decompressione del pacchetto della libreria...");
Expand-Archive -Path (Join-Path -Path $destination_path -ChildPath "LibraryPackage.zip") `
    -DestinationPath (Join-Path -Path $destination_path -ChildPath "LibraryPackage") -Force;
Write-Host ("Pacchetto della libreria preparato.");
rem   Script per preparare il pacchetto Licensing Service e avviare LicensingService.exe
echo Preparazione di LS >> ".\PrepareLS.log" 2>&1
PowerShell -ExecutionPolicy Unrestricted .\StartupScripts\PrepareLS.ps1 >> ".\PrepareLS.log" 2>&1
echo LS è stato preparato. >> ".\PrepareLS.log" 2>&1
exit /B %errorlevel%
Write-Host "PrepareLS.ps1 avviato...";
# contenitore con i pacchetti di ABBYY FineReader Engine e Licensing Service
$container_name = 'fre-lib';
# stringa di connessione dell'account di archiviazione di Azure
$connection_string = "<connection_string_to_frestorage>";
Write-Host "Configurazione";
Write-Host ("Nome del contenitore: " + $container_name);
Write-Host ("Stringa di connessione: " + $storage_account);
# connessione all'oggetto di archiviazione
Write-Host ("Connessione all'account di archiviazione di Azure in corso...");
$storage_account = New-AzStorageContext -ConnectionString $connection_string;
# recupero dei blob (in pratica, file)
Write-Host ("Recupero dei blob dal contenitore in corso...");
$fre_blobs = Get-AzStorageBlob -Container $container_name -Context $storage_account;
# percorso dell'archiviazione locale (vedere 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'; 
# download del pacchetto Licensing Service
Write-Host ("Download del pacchetto Licensing Service dal contenitore in corso...");
foreach( $blob in $fre_blobs ) {
    Write-Host $blob.Name;
    if( $blob.Name -eq "LSPackage.zip" ) {
        Write-Host ("Download del blob: " + $blob.Name + " in " + $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 ("Download del blob " + $blob.Name + " ignorato.");
    }
}
# decompressione del pacchetto scaricato
Write-Host ("Decompressione del pacchetto della libreria in corso...");
Expand-Archive -Path (Join-Path -Path $destination_path -ChildPath "LSPackage.zip") `
    -DestinationPath (Join-Path -Path $destination_path -ChildPath "LSPackage") -Force;
# creazione delle cartelle per le licenze
$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;
# avvio di Licensing Service in modalità standalone
Write-Host ("Avvio di Licensing Service in corso...");
 
$licensing_service_app = Join-Path -Path $destination_path -ChildPath "LSPackage\LicensingService.exe";
Start-Process -FilePath $licesing_service_app -ArgumentList "/standalone";
Write-Host ("Il pacchetto LS è stato preparato e LS è stato avviato.");
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() 
        {
            // Crea una connessione a un nuovo blob in <OutputContainerName>
            // Il risultato dell'elaborazione verrà archiviato qui
            BlobClient resultBlobClient = new BlobClient(Config.ConnectionString, Config.OutputContainerName,
                resultBlobName + fileExtension);
            // Sovrascrive il file esistente
            resultBlobClient.DeleteIfExists();
            // Imposta la posizione su 0 per scrivere il file dall'inizio
            stream.Position = 0;
            resultBlobClient.Upload(stream);
 
            stream.Close();
        }
        public void Dispose()
        {
            // Chiude lo stream di memoria durante il rilascio per renderlo accessibile dopo la scrittura dei dati
            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 è in esecuzione");
 
            try
            {
                this.RunAsync(this.cancellationTokenSource.Token).Wait();
            }
            finally
            {
                this.runCompleteEvent.Set();
            }
        }
        public override bool OnStart()
        {
            // Imposta il numero massimo di connessioni simultanee
            ServicePointManager.DefaultConnectionLimit = 12;
 
            // Imposta TLS 1.2 per potersi connettere all'account di archiviazione di Azure
            System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
 
            // Per informazioni sulla gestione delle modifiche di configurazione
            // vedere l'argomento MSDN all'indirizzo https://go.microsoft.com/fwlink/?LinkId=166357
 
            bool result = base.OnStart();
            Trace.TraceInformation("WorkerRole1 è stato avviato");
 
            processor.LoadEngine();
            return result;
        }
 
        public override void OnStop()
        {
            processor.UnloadEngine();
            Trace.TraceInformation("WorkerRole1 è in arresto");
            this.cancellationTokenSource.Cancel();
            this.runCompleteEvent.WaitOne();
            base.OnStop();
            Trace.TraceInformation("WorkerRole1 è stato arrestato");
        }
 
        private async Task RunAsync(CancellationToken cancellationToken)
        {
            // TODO: sostituisci quanto segue con la tua logica
            while (!cancellationToken.IsCancellationRequested)
            {
                Trace.TraceInformation("Elaborazione in corso");
 
                try
                {
                    // Crea il contenitore e restituisce un oggetto client del contenitore
                    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 Download del blob in memoria: " + blobItem.Name);
                        MemoryStream memoryStream = new MemoryStream();
                        blobClient.DownloadTo(memoryStream);
                        Trace.TraceInformation("\t Elaborazione in FRE: " + blobItem.Name);
                        string resultBlobName = processor.ProcessImage(memoryStream, blobItem.Name);
                        Trace.TraceInformation("\t Nome del blob risultante nel contenitore di output: " + resultBlobName);
                        Trace.TraceInformation("\t Eliminazione dal contenitore di input: " + blobItem.Name);
                        blobClient.Delete();
                    }
                }
                catch (Exception error)
                {
                    Trace.TraceInformation("errore: " + 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("Caricamento del profilo predefinito...");
            loadProfile();
        }
        public void LoadEngine()
        {
            try {
                if (engineLoader == null)
                {
                    // Lo stesso EngineLoader dell'esempio Hello
                    engineLoader = new EngineLoader();
                }
                setupFREngine();
            }
            catch (Exception error)
            {
                displayMessage("errore: " + error.Message);
            }
        }
        public void UnloadEngine()
        {
            try
            {
                if (engineLoader != null)
                {
                    engineLoader.Dispose();
                    engineLoader = null;
                }
            }
            catch (Exception error)
            {
                displayMessage("errore: " + error.Message);
            }
        }
 
        public string ProcessImage( MemoryStream inputMemoryStream, string inputBlobName )
        {
            FRDocument document = engineLoader.Engine.CreateFRDocument();
            string resultBlobName = "";
            try
            {
               document.PageFlushingPolicy = FREngine.PageFlushingPolicyEnum.PFP_KeepInMemory;
 
                // Aggiunge il file immagine al documento
                displayMessage("Caricamento dell'immagine...");
                IntPtr handle = Marshal.AllocHGlobal(inputMemoryStream.GetBuffer().Length);
                Marshal.Copy(inputMemoryStream.GetBuffer(), 0, handle, inputMemoryStream.GetBuffer().Length);
                document.AddImageFileFromMemory(handle.ToInt64(), null, null);
 
                // Riconosce il documento
                displayMessage("Riconoscimento in corso...");
                document.Process(null);
 
                // Salva i risultati
                displayMessage("Salvataggio dei risultati...");
                // Salva i risultati in PDF usando lo scenario '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("errore: " + error.Message);
            }
            finally
            {
                // Chiude il documento
                document.Close();
            }
 
            return resultBlobName;
        }
 
        public void Dispose()
        {
            UnloadEngine();
        }
    }
}
class Config
{
    // Archiviazione locale come definita in ServiceDefinition.csdef
    private static string LocalStorageName = "LocalStorage1";
    // Stringa di connessione al contenitore BLOB
    public static readonly string ConnectionString = "<connection_string_to_frestorage>";
    // Nomi dei contenitori di input e output nello spazio di archiviazione
    public static readonly string InputContainerName = "fre-input";
    public static readonly string OutputContainerName = "fre-output";
 
    // Restituisce il Customer Project ID per ABBYY FineReader Engine
    public static String GetCustomerProjectId()
    {
        return "<Your_Customer_Project_ID>";
    }
 
    // Restituisce il nome del token di licenza
    public static String GetLicenseTokenName()
    {
        return "<Token_number>.ABBYY.ActivationToken";
    }
 
    // Restituisce la password della licenza
    public static String GetLicensePassword()
    {
        return "<Your_Online_License_token_password>";
    }
    // Restituisce il percorso del motore
    public static String GetEngineFolder()
    {
        string engineSubfolder = "fre_packages\\LibraryPackage\\Bin64";
        string engineDllFolder = Path.Combine(RoleEnvironment.GetLocalResource(LocalStorageName).RootPath, engineSubfolder);
        return engineDllFolder;
    }
}