Błąd wdrożenia OcrInternals w aplikacjach x86

This article was translated from English: Does it need improvement?
Translated
View the article in English

IronTesseract.ReadScreenShot() działa przez zaawansowaną ścieżkę skanowania IronOCR, która jest obsługiwana tylko w procesie Windows x64. Wywołanie jej z aplikacji x86 kończy się błędem wdrożenia OcrInternals, nawet gdy pakiet IronOcr.Extensions.AdvancedScan jest zainstalowany.

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]

Niepowodzenie pojawia się na samym wywołaniu 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);
}
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
$vbLabelText   $csharpLabel

Zaawansowane komponenty natywne, na których polega ReadScreenShot(), nie są obsługiwane w procesie x86. Instalacja IronOcr.Extensions.AdvancedScan jest wymagana, ale nie zmienia bitności procesu hosta, więc to wywołanie wciąż nie może działać w x86.

UwagaInstalacja AdvancedScan nie sprawia, że ReadScreenShot() działa w procesie x86. Proces, który ją wywołuje, musi działać jako x64.

Rozwiązanie

Opcja 1: Bezpośredni cel x64

Najczystsze rozwiązanie to zmiana celu platformy projektu na x64. W Visual Studio:

  1. Kliknij prawym przyciskiem myszy projekt i wybierz Właściwości.
  2. Otwórz kartę Kompilacja.
  3. Ustaw Cel platformy na x64.
  4. Odznacz Preferowane 32-bitowe.
  5. Przebuduj i uruchom.

Z procesem hosta działającym jako x64, ReadScreenShot() działa w obsługiwanym środowisku.

Opcja 2: Utrzymaj app x86 i wywołuj proces pomocniczy x64

Kiedy główna aplikacja musi pozostać x86, przenieś tylko operację OCR do małego procesu pomocniczego x64 i wywołuj go z istniejącej aplikacji. Struktura wygląda na:

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

Aplikacja x86 pozostaje niezmieniona, podczas gdy AdvancedScan działa tam, gdzie jest obsługiwane.

Wywoływanie pomocnika z aplikacji x86

Uruchom pomocnika z ProcessStartInfo i odczytaj jego wyjście:

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
$vbLabelText   $csharpLabel

Przekierowanie zarówno StandardOutput, jak i StandardError pozwala wywołującemu uchwycić rozpoznany tekst i wyświetlić wszelkie niepowodzenie z kodu wyjścia pomocnika.

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)
$vbLabelText   $csharpLabel

Budowanie pomocnika x64

Zbuduj pomocnika jako aplikację konsolową x64, która odnosi się do IronOcr i IronOcr.Extensions.AdvancedScan. Odczytuje ścieżkę obrazu z pierwszego argumentu, uruchamia OCR i zapisuje wynik do 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
$vbLabelText   $csharpLabel

Odrębne kody wyjścia (1 2, 99) pozwalają wywołującej aplikacji rozróżniać brakujący argument od brakującego pliku lub nieoczekiwanego wyjątku.

Notatki do użytkowania produkcyjnego

Przykład wykorzystuje stdout dla uproszczenia. Dla produkcji wybierz metodę komunikacji, która pasuje do twojej architektury. Opcje obejmują:

  • Standardowe wyjście i standardowy błąd.
  • Tymczasowe pliki JSON.
  • Nazwane potoki.
  • Lokalny punkt końcowy HTTP.
  • Usługa Windows hostująca operację OCR w x64.

Dla małych lub okazjonalnych wywołań: uruchamianie pomocnika na żądanie zazwyczaj jest w porządku. Dla dużych obciążeń roboczych: długotrwała usługa pomocnika x64 jest zazwyczaj bardziej efektywna niż tworzenie nowego procesu na każde żądanie.

Wskazówki dotyczące debugowania

Przeanalizuj te sprawdzenia, gdy podejście pomocnika działa źle:

  • Potwierdź, że główna aplikacja faktycznie musi pozostać x86, i że Ocr.Read() nie wystarcza dla scenariusza zrzutu ekranu.
  • Zweryfikuj ReadScreenShot(), gdy uruchamiane bezpośrednio z procesu x64.
  • Zbuduj projekt pomocnika z Platforma docelowa: x64 i upewnij się, że aplikacja x86 nigdy nie wywołuje ReadScreenShot() siebie.
  • Zainstaluj IronOcr.Extensions.AdvancedScan w projekcie pomocnika x64.
  • Sprawdź, czy ścieżka obrazu przekazana do pomocnika jest osiągalna przez proces pomocnika.
  • Skonfiguruj klucz licencyjny IronOCR w kodzie, konfiguracji aplikacji lub zmiennej środowiskowej IRONOCR_LICENSE_KEY.

Podczas publikowania pomocnika skopiuj całą zawartość folderu build, nie tylko .exe. Folder wyjściowy musi zawierać wszystkie odwoływane zbiory i natywne pliki uruchomieniowe generowane podczas budowania, w przeciwnym razie pomocnik napotka ten sam błąd wdrożenia.

Curtis Chau
Autor tekstów technicznych

Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podrę...

Czytaj więcej
Gotowy, aby rozpocząć?
Nuget Pliki do pobrania 6,136,090 | Wersja: 2026.7 właśnie wydany
Still Scrolling Icon

Wciąż przewijasz?

Czy chcesz szybko dowodu? PM > Install-Package IronOcr
uruchom próbkę obserwuj, jak twój obraz staje się tekstem z możliwością wyszukiwania.