OcrInternals Deployment Error in x86 Applications
IronTesseract.ReadScreenShot() runs through IronOCR's AdvancedScan pipeline, which is supported only in a Windows x64 process. Calling it from an x86 application fails with an OcrInternals deployment error, even when the IronOcr.Extensions.AdvancedScan package is installed.
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]
The failure surfaces on the ReadScreenShot() call itself:
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);
}
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);
}
Imports IronOcr
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImage("Step_1-5.jpg")
Dim result = ocr.ReadScreenShot(input)
Console.WriteLine(result.Text)
End Using
The AdvancedScan native components that ReadScreenShot() depends on are not supported inside an x86 process. Installing IronOcr.Extensions.AdvancedScan is required, but it does not change the bitness of the host process, so the call still cannot run under x86.
Solution
Option 1: Target x64 directly
The cleanest fix is to switch the project's platform target to x64. In Visual Studio:
- Right-click the project and select Properties.
- Open the Build tab.
- Set Platform target to x64.
- Uncheck Prefer 32-bit.
- Rebuild and run.
With the host process running as x64, ReadScreenShot() executes in a supported environment.
Option 2: Keep the app x86 and call an x64 helper process
When the main application must stay x86, move only the OCR operation into a small x64 helper process and call it from the existing app. The structure looks like this:
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
The x86 application stays untouched while AdvancedScan runs where it is supported.
Calling the helper from the x86 application
Launch the helper with ProcessStartInfo and read its 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;
}
}
}
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 Module OcrHelperClient
Public 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 As 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 Module
Redirecting both StandardOutput and StandardError lets the caller capture the recognized text and surface any failure from the helper's exit code.
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);
Imports System
Dim imagePath As String = "C:\Images\Step_1-5.jpg"
Dim text As String = OcrHelperClient.ReadScreenshotWithHelper(imagePath)
Console.WriteLine(text)
Building the x64 helper
Build the helper as an x64 console app that references IronOcr and IronOcr.Extensions.AdvancedScan. It reads the image path from the first argument, runs the OCR, and writes the result to 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 Namespace
Distinct exit codes (1, 2, 99) let the calling app tell a missing argument from a missing file or an unexpected exception.
Notes for Production Use
The sample uses stdout for simplicity. For production, pick the communication method that fits your architecture. Options include:
- Standard output and standard error.
- Temporary JSON files.
- Named pipes.
- A local HTTP endpoint.
- A Windows Service hosting the x64 OCR operation.
For small or occasional calls: launching the helper on demand is usually fine. For high-volume workloads: a long-running x64 helper service tends to be more efficient than spawning a process per request.
Debug Tips
Work through these checks when the helper approach misbehaves:
- Confirm the main application genuinely needs to stay x86, and that
Ocr.Read()is not sufficient for the screenshot scenario. - Verify
ReadScreenShot()succeeds when run directly from an x64 process. - Build the helper project with Platform target: x64, and make sure the x86 app never calls
ReadScreenShot()itself. - Install
IronOcr.Extensions.AdvancedScanin the x64 helper project. - Check that the image path passed to the helper is reachable by the helper process.
- Configure the IronOCR license key in code, app config, or the
IRONOCR_LICENSE_KEYenvironment variable.
When publishing the helper, copy the entire build output, not just the .exe. The output folder must include all referenced assemblies and the native runtime files generated by the build, or the helper will hit the same deployment error.

