OcrInternalsのx86アプリケーションでの展開エラー
IronTesseract.ReadScreenShot() は、IronOCRのAdvancedScanパイプラインを通ります。これはWindows x64プロセスでのみサポートされています。 x86アプリケーションから呼び出すと、OcrInternals 展開エラーで失敗します。たとえIronOcr.Extensions.AdvancedScan パッケージがインストールされていても。
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]
失敗は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 UsingReadScreenShot() が依存しているAdvancedScanのネイティブコンポーネントは、x86プロセス内ではサポートされていません。 IronOcr.Extensions.AdvancedScan のインストールが必要ですが、ホストプロセスのビット数を変更しないため、呼び出しは依然としてx86で実行できません。
解決策
オプション1: 直接x64をターゲット
最も簡潔な修正は、プロジェクトのプラットフォームターゲットをx64に切り替えることです。Visual Studioで:
- プロジェクトを右クリックし、プロパティを選択します。
- ビルドタブを開きます。
- プラットフォームターゲットをx64に設定します。
- 32ビット優先をオフにします。
- 再ビルドして実行します。
ホストプロセスがx64として実行されていると、ReadScreenShot() はサポートされている環境で実行されます。
オプション2: アプリをx86のままにしてx64のヘルパープロセスを呼び出す
メインアプリケーションをx86のままにする必要がある場合、OCR操作を小さなx64のヘルパープロセスに移動し、既存のアプリから呼び出します。この構造は次のようになります:
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
x86アプリケーションは変更されず、AdvancedScanはサポートされている場所で実行されます。
x86アプリケーションからヘルパーを呼び出す
ProcessStartInfo でヘルパーを起動し、その出力を読みます。
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 ClassStandardOutput とStandardError の両方をリダイレクトすると、呼び出し側は認識されたテキストをキャプチャし、ヘルパーの終了コードから失敗を表面化できます。
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)x64ヘルパーの構築
ヘルパーをx64コンソールアプリとしてビルドし、IronOcr とIronOcr.Extensions.AdvancedScan を参照させます。 それは最初の引数から画像パスを読み取り、OCRを実行し、結果を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 Namespace異なる終了コード(1, 2, 99)によって、呼び出しアプリケーションは、引数が欠けているのかファイルが欠けているのか、または予期しない例外かを判別できます。
本番利用の注意事項
サンプルは簡単にするためにstdout を使用します。 本番環境には、アーキテクチャに合った通信方法を選んでください。 オプションには以下があります:
- 標準出力と標準エラー。
- 一時的なJSONファイル。
- 名前付きパイプ。
- ローカルHTTPエンドポイント。
- x64 OCR操作をホストするWindowsサービス。
小規模または頻繁でない呼び出しの場合:通常、必要に応じてヘルパーを起動するだけで大丈夫です。大容量のワークロードの場合:リクエストごとにプロセスを生成するよりも、長時間稼働するx64ヘルパーサービスがより効率的です。
デバッグのヒント
ヘルパーアプローチが誤動作する場合は、これらのチェックを実行します:
- メインアプリケーションが本当にx86のままである必要があることを確認し、
Ocr.Read()がスクリーンショットのシナリオに十分でないことを確認します。 ReadScreenShot()がx64プロセスから直接実行したときに成功することを確認します。- プラットフォームターゲット: x64でヘルパープロジェクトをビルドし、x86アプリが
ReadScreenShot()を自分で呼び出さないようにします。 - x64ヘルパープロジェクトに
IronOcr.Extensions.AdvancedScanをインストールします。 - ヘルパーに渡される画像パスがヘルパープロセスからアクセス可能であることを確認してください。
コード、アプリ設定、または
IRONOCR_LICENSE_KEY環境変数でIronOCRのライセンスキーを設定します。
ヘルパーを公開するときは、.exe のみでなく、ビルド出力全体をコピーします。 出力フォルダには、参照されるすべてのアセンブリとビルドによって生成されたネイティブランタイムファイルを含める必要があります。さもなくば、ヘルパーは同じ展開エラーに直面します。
Curtis Chauは、カールトン大学でコンピュータサイエンスの学士号を取得し、Node.js、TypeScript、JavaScript、およびReactに精通したフロントエンド開発を専門としています。直感的で美しいユーザーインターフェースを作成することに情熱を持ち、Curtisは現代のフレームワークを用いた開発や、構造の良い視覚的に魅力的なマニュアルの作成を楽しんでいます。