Erro de Implantação do OcrInternals em Aplicativos x86
IronTesseract.ReadScreenShot() roda pelo pipeline AdvancedScan do IronOCR, que é suportado apenas em um processo Windows x64. Chamando-o de um aplicativo x86 falha com um erro de implantação OcrInternals, mesmo quando o pacote IronOcr.Extensions.AdvancedScan está instalado.
Error while reading a screenshot, Error while deploying OcrInternals for IronOcr:
'Unable to locate 'OcrInternals' in
...\bin\Debug\runtimes\win-x86\native,
...\bin\Debug\runtimes\win.6.2-x86\native,
...\bin\Debug\runtimes\win.6-x86\native,
...\bin\Debug\,
...
nor in an embedded resource.'
Please install the NuGet Package 'IronOcr.Extension.AdvancedScan' when using IronOcr on Windows.
[Issue Code IRONOCR-OCRINTERNALS-DEPLOYMENT-ERROR-WIN]
A falha surge na própria chamada ReadScreenShot():
var ocr = new IronOcr.IronTesseract();
using (var input = new IronOcr.OcrInput())
{
input.LoadImage("Step_1-5.jpg");
var result = ocr.ReadScreenShot(input);
Console.WriteLine(result.Text);
}Dim ocr = New IronOcr.IronTesseract()
Using input = New IronOcr.OcrInput()
input.LoadImage("Step_1-5.jpg")
Dim result = ocr.ReadScreenShot(input)
Console.WriteLine(result.Text)
End UsingDim ocr = New IronOcr.IronTesseract()
Using input = New IronOcr.OcrInput()
input.LoadImage("Step_1-5.jpg")
Dim result = ocr.ReadScreenShot(input)
Console.WriteLine(result.Text)
End UsingOs componentes nativos AdvancedScan dos quais ReadScreenShot() depende não são suportados dentro de um processo x86. Instalar IronOcr.Extensions.AdvancedScan é necessário, mas isso não altera a arquitetura do processo host, então a chamada ainda não pode ser executada em x86.
Solução
Opção 1: Direcionar para x64 diretamente
A correção mais limpa é mudar o alvo de plataforma do projeto para x64. No Visual Studio:
- Clique com o botão direito no projeto e selecione Propriedades.
- Abra a aba Compilação.
- Defina Alvo da plataforma para x64.
- Desmarque Preferir 32 bits.
- Recompile e execute.
Com o processo host rodando como x64, ReadScreenShot() executa em um ambiente suportado.
Opção 2: Mantenha o aplicativo x86 e chame um processo auxiliar x64
Quando o aplicativo principal deve permanecer x86, mova apenas a operação OCR para um pequeno processo auxiliar x64 e chame-o do aplicativo existente. A estrutura se parece com isto:
MainWinForms.x86
- .NET Framework Windows Forms app
- Platform target: x86
- Does not run ReadScreenShot() directly
- Calls the x64 helper process
OcrHelper.x64
- .NET Framework Console app
- Platform target: x64
- References IronOCR
- References IronOcr.Extensions.AdvancedScan
- Runs Ocr.ReadScreenShot()
- Returns the OCR result to the main app
O aplicativo x86 permanece inalterado enquanto o AdvancedScan roda onde é suportado.
Chamando o auxiliar do aplicativo x86
Inicie o auxiliar com ProcessStartInfo e leia sua saída:
using System;
using System.Diagnostics;
using System.IO;
public static class OcrHelperClient
{
public static string ReadScreenshotWithHelper(string imagePath)
{
string helperExePath = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"OcrHelper.x64",
"OcrHelper.x64.exe"
);
if (!File.Exists(helperExePath))
{
throw new FileNotFoundException("The OCR helper executable was not found.", helperExePath);
}
var startInfo = new ProcessStartInfo
{
FileName = helperExePath,
Arguments = "\"" + imagePath + "\"",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using (var process = new Process())
{
process.StartInfo = startInfo;
process.Start();
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();
if (process.ExitCode != 0)
{
throw new Exception("OCR helper failed: " + error);
}
return output;
}
}
}using System;
using System.Diagnostics;
using System.IO;
public static class OcrHelperClient
{
public static string ReadScreenshotWithHelper(string imagePath)
{
string helperExePath = Path.Combine(
AppDomain.CurrentDomain.BaseDirectory,
"OcrHelper.x64",
"OcrHelper.x64.exe"
);
if (!File.Exists(helperExePath))
{
throw new FileNotFoundException("The OCR helper executable was not found.", helperExePath);
}
var startInfo = new ProcessStartInfo
{
FileName = helperExePath,
Arguments = "\"" + imagePath + "\"",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using (var process = new Process())
{
process.StartInfo = startInfo;
process.Start();
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();
if (process.ExitCode != 0)
{
throw new Exception("OCR helper failed: " + error);
}
return output;
}
}
}Imports System
Imports System.Diagnostics
Imports System.IO
Public NotInheritable Class OcrHelperClient
Private Sub New()
End Sub
Public Shared Function ReadScreenshotWithHelper(imagePath As String) As String
Dim helperExePath As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "OcrHelper.x64", "OcrHelper.x64.exe")
If Not File.Exists(helperExePath) Then
Throw New FileNotFoundException("The OCR helper executable was not found.", helperExePath)
End If
Dim startInfo = New ProcessStartInfo With {
.FileName = helperExePath,
.Arguments = """" & imagePath & """",
.UseShellExecute = False,
.RedirectStandardOutput = True,
.RedirectStandardError = True,
.CreateNoWindow = True
}
Using process As New Process()
process.StartInfo = startInfo
process.Start()
Dim output As String = process.StandardOutput.ReadToEnd()
Dim [error] As String = process.StandardError.ReadToEnd()
process.WaitForExit()
If process.ExitCode <> 0 Then
Throw New Exception("OCR helper failed: " & [error])
End If
Return output
End Using
End Function
End ClassImports System
Imports System.Diagnostics
Imports System.IO
Public NotInheritable Class OcrHelperClient
Private Sub New()
End Sub
Public Shared Function ReadScreenshotWithHelper(imagePath As String) As String
Dim helperExePath As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "OcrHelper.x64", "OcrHelper.x64.exe")
If Not File.Exists(helperExePath) Then
Throw New FileNotFoundException("The OCR helper executable was not found.", helperExePath)
End If
Dim startInfo = New ProcessStartInfo With {
.FileName = helperExePath,
.Arguments = """" & imagePath & """",
.UseShellExecute = False,
.RedirectStandardOutput = True,
.RedirectStandardError = True,
.CreateNoWindow = True
}
Using process As New Process()
process.StartInfo = startInfo
process.Start()
Dim output As String = process.StandardOutput.ReadToEnd()
Dim [error] As String = process.StandardError.ReadToEnd()
process.WaitForExit()
If process.ExitCode <> 0 Then
Throw New Exception("OCR helper failed: " & [error])
End If
Return output
End Using
End Function
End ClassRedirecionar tanto StandardOutput quanto StandardError permite que o chamador capture o texto reconhecido e apresente qualquer falha a partir do código de saída do auxiliar.
string imagePath = @"C:\Images\Step_1-5.jpg";
string text = OcrHelperClient.ReadScreenshotWithHelper(imagePath);
Console.WriteLine(text);string imagePath = @"C:\Images\Step_1-5.jpg";
string text = OcrHelperClient.ReadScreenshotWithHelper(imagePath);
Console.WriteLine(text);Dim imagePath As String = "C:\Images\Step_1-5.jpg"
Dim text As String = OcrHelperClient.ReadScreenshotWithHelper(imagePath)
Console.WriteLine(text)Dim imagePath As String = "C:\Images\Step_1-5.jpg"
Dim text As String = OcrHelperClient.ReadScreenshotWithHelper(imagePath)
Console.WriteLine(text)Construindo o auxiliar x64
Construa o auxiliar como um aplicativo de console x64 que referencia IronOcr e IronOcr.Extensions.AdvancedScan. Lê o caminho da imagem do primeiro argumento, executa o OCR e grava o resultado em stdout:
using System;
using System.IO;
using IronOcr;
namespace OcrHelper.x64
{
internal static class Program
{
private static int Main(string[] args)
{
try
{
if (args.Length == 0)
{
Console.Error.WriteLine("Missing image path argument.");
return 1;
}
string imagePath = args[0];
if (!File.Exists(imagePath))
{
Console.Error.WriteLine("Image file was not found: " + imagePath);
return 2;
}
string licenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY");
if (!string.IsNullOrWhiteSpace(licenseKey))
{
License.LicenseKey = licenseKey;
}
var ocr = new IronTesseract();
using (var input = new OcrInput())
{
input.LoadImage(imagePath);
var result = ocr.ReadScreenShot(input);
Console.WriteLine(result.Text);
}
return 0;
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.ToString());
return 99;
}
}
}
}using System;
using System.IO;
using IronOcr;
namespace OcrHelper.x64
{
internal static class Program
{
private static int Main(string[] args)
{
try
{
if (args.Length == 0)
{
Console.Error.WriteLine("Missing image path argument.");
return 1;
}
string imagePath = args[0];
if (!File.Exists(imagePath))
{
Console.Error.WriteLine("Image file was not found: " + imagePath);
return 2;
}
string licenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY");
if (!string.IsNullOrWhiteSpace(licenseKey))
{
License.LicenseKey = licenseKey;
}
var ocr = new IronTesseract();
using (var input = new OcrInput())
{
input.LoadImage(imagePath);
var result = ocr.ReadScreenShot(input);
Console.WriteLine(result.Text);
}
return 0;
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.ToString());
return 99;
}
}
}
}Imports System
Imports System.IO
Imports IronOcr
Namespace OcrHelper.x64
Friend Module Program
Private Function Main(args As String()) As Integer
Try
If args.Length = 0 Then
Console.Error.WriteLine("Missing image path argument.")
Return 1
End If
Dim imagePath As String = args(0)
If Not File.Exists(imagePath) Then
Console.Error.WriteLine("Image file was not found: " & imagePath)
Return 2
End If
Dim licenseKey As String = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")
If Not String.IsNullOrWhiteSpace(licenseKey) Then
License.LicenseKey = licenseKey
End If
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImage(imagePath)
Dim result = ocr.ReadScreenShot(input)
Console.WriteLine(result.Text)
End Using
Return 0
Catch ex As Exception
Console.Error.WriteLine(ex.ToString())
Return 99
End Try
End Function
End Module
End NamespaceImports System
Imports System.IO
Imports IronOcr
Namespace OcrHelper.x64
Friend Module Program
Private Function Main(args As String()) As Integer
Try
If args.Length = 0 Then
Console.Error.WriteLine("Missing image path argument.")
Return 1
End If
Dim imagePath As String = args(0)
If Not File.Exists(imagePath) Then
Console.Error.WriteLine("Image file was not found: " & imagePath)
Return 2
End If
Dim licenseKey As String = Environment.GetEnvironmentVariable("IRONOCR_LICENSE_KEY")
If Not String.IsNullOrWhiteSpace(licenseKey) Then
License.LicenseKey = licenseKey
End If
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImage(imagePath)
Dim result = ocr.ReadScreenShot(input)
Console.WriteLine(result.Text)
End Using
Return 0
Catch ex As Exception
Console.Error.WriteLine(ex.ToString())
Return 99
End Try
End Function
End Module
End NamespaceCódigos de saída distintos (1, 2, 99) permitem que o aplicativo chamador diferencie entre um argumento ausente, um arquivo ausente ou uma exceção inesperada.
Notas para Uso em Produção
O exemplo usa stdout por simplicidade. Para produção, escolha o método de comunicação que se adequa à sua arquitetura. As opções incluem:
- Saída padrão e erro padrão.
- Arquivos JSON temporários.
- Pipes nomeados.
- Um endpoint HTTP local.
- Um serviço Windows hospedando a operação OCR x64.
Para chamadas pequenas ou ocasionais: lançar o auxiliar sob demanda geralmente está bem. Para cargas de trabalho de alto volume: um serviço auxiliar x64 de longa execução tende a ser mais eficiente do que iniciar um processo por solicitação.
Dicas de Depuração
Realize estas verificações quando a abordagem auxiliar se comportar mal:
- Confirme que o aplicativo principal realmente precisa permanecer x86, e que
Ocr.Read()não é suficiente para o cenário de captura de tela. - Verifique se
ReadScreenShot()é bem-sucedido quando executado diretamente de um processo x64. - Construa o projeto auxiliar com Plataforma alvo: x64, e certifique-se de que o aplicativo x86 nunca chame
ReadScreenShot()por si só. - Instale
IronOcr.Extensions.AdvancedScanno projeto auxiliar x64. - Verifique se o caminho da imagem passado para o auxiliar é acessível pelo processo auxiliar.
- Configure a chave de licença do IronOCR no código, configuração do aplicativo ou na variável de ambiente
IRONOCR_LICENSE_KEY.
Ao publicar o auxiliar, copie todo o resultado da construção, não apenas o .exe. A pasta de saída deve incluir todas as assemblies referenciadas e os arquivos de runtime nativo gerados pela construção, ou o auxiliar enfrentará o mesmo erro de implantação.
Curtis Chau é bacharel em Ciência da Computação (Universidade Carleton) e se especializa em desenvolvimento front-end, com experiência em Node.js, TypeScript, JavaScript e React. Apaixonado por criar interfaces de usuário intuitivas e esteticamente agradáveis, Curtis gosta de trabalhar com frameworks modernos e criar manuais bem estruturados e visualmente atraentes.