フッターコンテンツにスキップ
IRONXLの使用

ExcelオブジェクトをC#で解放 | IronXLでExcelプロセスの滞留を停止

Excel オブジェクトを C# で解放: IronXLで Excel プロセスの残留を停止: 画像 1 - Excel オブジェクトを C# で解放: 2 つの方法の比較

C# アプリケーションで Microsoft Excel ファイルを操作すると、Excel プロセスが閉じないというイライラする問題が発生することがよくあります。 コードの実行が終了してから長時間メモリを消費し、タスク マネージャーに複数の EXCEL.EXE インスタンスが蓄積されている場合があります。 このガイドでは、従来の Excel Interop でなぜこのようなことが起こるのかを説明し、 IronXL がこれらの COM オブジェクトの悩みを完全に解消して、複雑なクリーンアップ コードや運用メモリ リークを回避する方法を説明します。

根本的な原因は、.NET Framework がCOM 参照を通じて Microsoft Office と対話する方法にあります。 Microsoft.Office.Interop.Excel を使用してコードを記述すると、Excel アプリケーションのすべてのオブジェクト、ワークブック、ワークシートで、明示的なクリーンアップを必要とする COM オブジェクトが作成されます。リリース呼び出しを 1 つでも省略すると、または app.Workbooks.Open() のような二重ドットを含むパターンを使用すると、孤立した参照が残り、Excel プロセスが終了しなくなります。

今IronXLを始めましょう。
green arrow pointer

Excel プロセスが閉じた後もタスク マネージャーに残るのはなぜですか?

COM オブジェクトの参照カウントが適切に減分されないため、Excel アプリケーションは終了しません。 コードが Excel アプリケーション、ブック、またはワークシートにアクセスするたびに、ランタイムは、基になる COM オブジェクトへの参照カウントを保持するランタイム呼び出し可能ラッパー (RCW) を作成します。 .NETガベージ コレクターは、Marshal.ReleaseComObject を使用してすべての参照が明示的に解放されるまで、これらの相互運用オブジェクトを解放できません。

プロセスが長引く原因となる一般的な間違いは次のとおりです。

  • プロパティ チェーンで 2 つのドットを使用する (例: app.Workbooks.Open() (非表示の一時オブジェクトを作成する))
  • COM コレクションに対して foreach ループを反復処理します (これにより、解放されていない列挙子が生成されます)
  • Excel アプリケーション オブジェクトで Quit() を呼び出すのを忘れる
  • finally ブロック内でクリーンアップせずに例外をキャッチする

以前のバージョンの Microsoft Office (2000 ~ 2003) では、Office API オブジェクトの解放に失敗すると、Excel のメイン ウィンドウが無期限にハングしていました。 新しいバージョンではより寛容になっていますが、Excel プロセスは依然としてタスク マネージャーに蓄積され、Excel スプレッドシート ファイルでメモリ リークやファイル ロックの問題が発生する可能性があります。

この問題は、サーバー側またはスケジュールされたアプリケーションで特に深刻になります。これらのアプリケーションでは、時間の経過とともにプロセスが蓄積され、サーバーのメモリが不足します。 なぜこのようなことが起こるのかを理解することが、仕事に適したツールを選択するための第一歩です。

COM 層では何が起こるのでしょうか?

Excel COM オブジェクトのすべてのプロパティ アクセスで新しい RCW を作成できます。 worksheet.Range["A1"].Value と記述すると、2 つの別個の COM オブジェクトが作成されます。1 つは Range 用で、もう 1 つは二重ドット アクセスによって暗黙的に作成されます。 ガベージ コレクターは最終的にこれらをクリーンアップする可能性がありますが、タイミングについては保証されません。 高スループットのアプリケーションでは、コレクションが発生するよりも速くバックログが増加する可能性があります。

Windows は COM 参照を内部的にカウントします。 カウントがゼロになるまで、基盤となるプロセス(EXCEL.EXE)は動作し続けます。GC.Collect()GC.WaitForPendingFinalizers() を呼び出すとコレクションサイクルが強制的に実行されますが、この方法はパフォーマンスコストが高く、実稼働コードでは長期的な解決策にはなりません。

ダブルドットパターンが問題を引き起こすのはなぜですか?

二重ドット パターン (app.Workbooks.Open(path)) は C# では慣用的ですが、COM 相互運用コンテキストでは参照されていない中間オブジェクトが作成されます。 Workbooks コレクション オブジェクトが作成され、Open を呼び出すために使用されますが、コードに参照がないため、すぐに孤立します。 ガベージ コレクターにはこれらのオブジェクトを終了するための予測可能なスケジュールがないため、EXCEL.EXE は開いたままになります。

Interop を使用した唯一の安全なアプローチは、すべての中間オブジェクトを名前付き変数に格納し、作成と逆の順序で各オブジェクトを明示的に解放することです。

Excel 相互運用オブジェクトを正しくリリースするにはどうすればよいですか?

従来のアプローチでは、作成されたすべての COM オブジェクトを綿密に追跡する必要があります。 二重ドットを避け、すべての中間オブジェクトをローカル変数に格納し、逆の順序で解放する必要があります。 次のコードは、Stack Overflow の回答や Microsoft のドキュメントによく見られる詳細なクリーンアップ パターンを示しています。

using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;

// Verbose Interop cleanup pattern
Excel.Application excelApp = new Excel.Application();
Excel.Workbooks workbooks = excelApp.Workbooks;
Excel.Workbook workbook = workbooks.Open("report.xlsx");
Excel.Sheets sheets = workbook.Sheets;
Excel.Worksheet worksheet = (Excel.Worksheet)sheets[1];

// Work with data
worksheet.Cells[1, 1] = "Updated Value";

// Cleanup -- release EVERY COM object in reverse order
workbook.Close(false);
excelApp.Quit();

Marshal.ReleaseComObject(worksheet);
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApp);

GC.Collect();
GC.WaitForPendingFinalizers();
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;

// Verbose Interop cleanup pattern
Excel.Application excelApp = new Excel.Application();
Excel.Workbooks workbooks = excelApp.Workbooks;
Excel.Workbook workbook = workbooks.Open("report.xlsx");
Excel.Sheets sheets = workbook.Sheets;
Excel.Worksheet worksheet = (Excel.Worksheet)sheets[1];

// Work with data
worksheet.Cells[1, 1] = "Updated Value";

// Cleanup -- release EVERY COM object in reverse order
workbook.Close(false);
excelApp.Quit();

Marshal.ReleaseComObject(worksheet);
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(workbook);
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApp);

GC.Collect();
GC.WaitForPendingFinalizers();
$vbLabelText   $csharpLabel

このコードは、適切なクリーンアップを確実に行うために、各Excelオブジェクトを個別に保存します。最後にあるGC.WaitForPendingFinalizers()の呼び出しにより、ガベージコレクションが強制的に実行されます。 例外が発生した場合でもクリーンアップを保証するために、すべてを try/finally ブロックでラップする開発者もいます。

標準的なクリーンアップが失敗する極端なケースでは、一部のチームは Windows ジョブ オブジェクトを使用してプロセスを強制終了するアプローチに頼ります。 これには、SetInformationJobObject、および AssignProcessToJobObject の P/Invoke 宣言が含まれます。 これは最後の手段として機能しますが、根本的な設計上の問題を修正するのではなく、症状を治療することになります。

C# で COM フリーの Excel ライブラリをインストールするにはどうすればよいでしょうか?

IronXL は、Excel ファイル操作に対して根本的に異なるアプローチを採用しています。 IronXL は、Microsoft Office COM オブジェクトをラップするのではなく、独自のパーサーとレンダラーを使用して Excel ファイル形式を直接読み書きします。 つまり、COM 参照、Office 相互運用性の依存関係、残留プロセスはありません。 マシンに Microsoft Excel がインストールされている必要もありません。

Visual Studio のNuGetパッケージ マネージャー コンソールからIronXL をインストールします。

Install-Package IronXl.Excel
Install-Package IronXl.Excel
SHELL

または.NET CLIを使用します:

dotnet add package IronXl.Excel
dotnet add package IronXl.Excel
SHELL

インストール後、ファイルにusing IronXL;ディレクティブを追加してください。これで、プロジェクトはOfficeに依存せずにExcelファイル操作に直接ネイティブアクセスできるようになります。 IronXL は.NET 8、 .NET 9、 .NET 10、 .NET Framework 4.6.2+ を対象としており、Windows、Linux、macOS、Docker、Azure で実行されます。

必要なNuGetパッケージは何ですか?

必要なNuGetパッケージは 1 つだけです: IronXl.Excel。 Microsoft Office、Office Interop アセンブリ、または COM 登録に依存しません。 これにより、展開が大幅に簡素化されます。アプリケーションを自己完結型実行可能ファイルとして公開すると、Office がインストールされていない任意のサーバー上で実行できるようになります。

PDF 生成も必要なプロジェクトの場合、 IronPDF はIronXLと統合して、Excel 自動化を経由せずに Excel データを直接 PDF にエクスポートします。

COM オブジェクトなしで Excel ファイルを読み取るにはどうすればよいでしょうか?

次のコードは、 IronXLを使用して Excel ファイルを読み取る方法を示しています。 クリーンアップ コードが必要ないことに注意してください。

using IronXL;

// Load and read Excel files without COM objects
WorkBook workBook = WorkBook.Load("report.xlsx");
WorkSheet workSheet = workBook.DefaultWorkSheet;

// Access cell values directly
string cellValue = workSheet["A1"].StringValue;
decimal columnSum = workSheet["B2:B10"].Sum();

// なし cleanup required -- workBook is a standard .NET object
Console.WriteLine($"Cell A1: {cellValue}");
Console.WriteLine($"Sum B2:B10: {columnSum}");
using IronXL;

// Load and read Excel files without COM objects
WorkBook workBook = WorkBook.Load("report.xlsx");
WorkSheet workSheet = workBook.DefaultWorkSheet;

// Access cell values directly
string cellValue = workSheet["A1"].StringValue;
decimal columnSum = workSheet["B2:B10"].Sum();

// なし cleanup required -- workBook is a standard .NET object
Console.WriteLine($"Cell A1: {cellValue}");
Console.WriteLine($"Sum B2:B10: {columnSum}");
$vbLabelText   $csharpLabel

コンソール出力

Excel オブジェクトをリリース C#: IronXLを使用して Excel プロセスの残留を停止する: 画像 3 - 入力 Excel ファイルを読み取る出力IronXL

IronXLはExcelオブジェクトをネイティブ.NET型として処理します。Marshal.ReleaseComObjectを呼び出したり、ガベージコレクションサイクルを強制したりする必要はありません。

また、プロセス リークを防止するために必須ではありませんが、確定的な破棄のためにIronXLワークブックで using ブロックを使用することもできます。これは単に、 .NETリソース管理の適切な実践の問題です。

複数のワークシートにアクセスするにはどうすればよいでしょうか?

IronXLで複数のワークシートにアクセスするのは、任意 for .NETコレクションを操作するのと同じくらい簡単です。

using IronXL;

WorkBook workBook = WorkBook.Load("multi-sheet-report.xlsx");

// Iterate all worksheets
foreach (WorkSheet sheet in workBook.WorkSheets)
{
    string sheetName = sheet.Name;
    int rowCount = sheet.RowCount;
    Console.WriteLine($"Sheet '{sheetName}' has {rowCount} rows");
}

// Access a specific sheet by name
WorkSheet salesSheet = workBook["Sales"];
decimal totalRevenue = salesSheet["C2:C100"].Sum();
Console.WriteLine($"Total Revenue: {totalRevenue:C}");
using IronXL;

WorkBook workBook = WorkBook.Load("multi-sheet-report.xlsx");

// Iterate all worksheets
foreach (WorkSheet sheet in workBook.WorkSheets)
{
    string sheetName = sheet.Name;
    int rowCount = sheet.RowCount;
    Console.WriteLine($"Sheet '{sheetName}' has {rowCount} rows");
}

// Access a specific sheet by name
WorkSheet salesSheet = workBook["Sales"];
decimal totalRevenue = salesSheet["C2:C100"].Sum();
Console.WriteLine($"Total Revenue: {totalRevenue:C}");
$vbLabelText   $csharpLabel

COM 反復列挙子、非表示の一時オブジェクト、クリーンアップは必要ありません。 IronXL の API は全体的に標準 for .NETコレクション パターンに従います。

Interop なしで新しい Excel ファイルを作成するにはどうすればよいですか?

Excel ファイルの作成は、同じ簡単な方法パターンで機能します。 次のコードは、新しいワークブックを作成し、構造化データを追加し、基本的な書式を適用して保存する方法を示しています。

using IronXL;

// Create a new Excel spreadsheet in XLSX format
WorkBook workBook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet workSheet = workBook.CreateWorkSheet("Sales Data");

// Write headers
workSheet["A1"].Value = "Product";
workSheet["B1"].Value = "Units Sold";
workSheet["C1"].Value = "Revenue";

// Write data rows
workSheet["A2"].Value = "Widget Alpha";
workSheet["B2"].Value = 450;
workSheet["C2"].Value = 22500;

workSheet["A3"].Value = "Widget Beta";
workSheet["B3"].Value = 310;
workSheet["C3"].Value = 15500;

// Add a formula
workSheet["C4"].Formula = "=SUM(C2:C3)";

// Save the Excel file
workBook.SaveAs("sales_report.xlsx");
Console.WriteLine("Spreadsheet saved successfully.");
using IronXL;

// Create a new Excel spreadsheet in XLSX format
WorkBook workBook = WorkBook.Create(ExcelFileFormat.XLSX);
WorkSheet workSheet = workBook.CreateWorkSheet("Sales Data");

// Write headers
workSheet["A1"].Value = "Product";
workSheet["B1"].Value = "Units Sold";
workSheet["C1"].Value = "Revenue";

// Write data rows
workSheet["A2"].Value = "Widget Alpha";
workSheet["B2"].Value = 450;
workSheet["C2"].Value = 22500;

workSheet["A3"].Value = "Widget Beta";
workSheet["B3"].Value = 310;
workSheet["C3"].Value = 15500;

// Add a formula
workSheet["C4"].Formula = "=SUM(C2:C3)";

// Save the Excel file
workBook.SaveAs("sales_report.xlsx");
Console.WriteLine("Spreadsheet saved successfully.");
$vbLabelText   $csharpLabel

出力

Excel オブジェクトを解放する C#: IronXLを使用して Excel プロセスの残留を停止する: 画像 4 - Interop なしで作成された Excel ファイル

このアプローチにより、Excel アプリケーション オブジェクトの管理、未保存の変更プロンプトの処理、メイン スレッドが STA アパートメント モデルを使用していることの確認などの複雑さが解消されます。 IronXL は、Office アドインの依存関係や Interop アセンブリの登録の負担なしに、スプレッドシート機能へのアクセスを簡素化します。

より複雑な操作が必要なシナリオの場合、 IronXL は数式の評価セルのスタイル設定、および複数シートのワークブックのメソッドを提供します。 COM オブジェクトのライフサイクル管理を気にすることなく、Excel ワークシート データを操作し、書式を適用し、複数のファイル形式にエクスポートするコードを記述できます。

Excel Interop と直接ライブラリの主な違いは何ですか?

次の表は、2 つのアプローチの最も重要な違いをまとめたものです。

Excel Interop と C# アプリケーションにおけるIronXLの比較
能力 Excel Interop IronXL
Microsoft Officeが必要です はい なし
COMオブジェクトのクリーンアップ マニュアル(すべてのオブジェクト) 自動(.NET GC)
EXCEL.EXEが残るリスク 高い 該当なし
サーバー環境で動作します 限定(STAスレッドが必要) はい(すべての環境)
Docker / Linux サポート なし はい
サポートされているファイル形式 XLS、XLSX(Office経由) XLS、XLSX、CSV、TSV、JSON
スレッドの安全性 STAのみ マルチスレッド
コードの複雑さ(基本的な読み取り) 高(リリースコールが多い) 低(3~5行)

Excel オブジェクトを C# から解放: IronXLで Excel プロセスの残留を停止: 画像 2 - Interop とIronXLの比較表

IronXL は、 CSV ファイルの読み取りCSV へのデータのエクスポートExcel グラフの操作条件付き書式の適用もサポートしています。 これらの機能はすべて Office に依存せずに利用できるため、 IronXL はデスクトップ アプリケーションとサーバー側アプリケーションの両方に適しています。

高度なシナリオの詳細については、 IronXL のドキュメントIronXL API リファレンスを参照してください。 また、 IronXLサンプル ギャラリーを参照して、数十の一般的な Excel 自動化タスクを網羅した、すぐに使用できるコード サンプルを探すこともできます。

Excel の数式とデータの検証についてはどうですか?

IronXL は、Excel の数式の読み取りと書き込みをネイティブにサポートします。 セルの Formula プロパティを設定すると、 IronXL は数式をファイルに保存し、評価します。 データ検証ルールについては、 IronXL はドロップダウン リスト、数値範囲の制約、日付の検証をサポートしており、これらはすべて Excel で計算を実行する必要なしに実行できます。

このライブラリは、Excel のパスワード保護結合セルExcel の固定ペインの構成も処理します。 各機能の詳細な手順については、 IronXLチュートリアルを参照してください。

Excel Interop からネイティブ.NETライブラリに移行するにはどうすればよいですか?

既存の Interop ベースのコードベースをIronXLに移行するには、通常、次の 4 つの手順が必要です。

  1. Microsoft.Office.Interop.Excel NuGet参照とCOM登録を削除します。
  2. NuGet経由でIronXl.Excelをインストールする
  3. Interop オブジェクトの作成をIronXL の同等の機能に置き換えます (WorkBook.Create)
  4. すべてのGC.Collectパターンを削除します。

ほとんどのプロパティ名は直感的にマップされます。つまり、worksheet.Cells[row, col]workSheet[$"{col}{row}"].Value になり、workbook.SaveAs(path) はほぼ同じままです。 IronXL移行ガイドでは、一般的な変換パターンについて説明します。

注意すべき領域の 1 つはスレッドです。 相互運用性には STA スレッドが必要であり、 ASP.NETで特定のスレッド プール構成が強制されます。 IronXLに切り替えた後、[STAThread] 属性とスレッド アパートメント設定を削除できます。IronXLはデフォルトでスレッドセーフです。

多数のファイルにわたる大規模な移行の場合、 IronXLバッチ処理の例では、並列ループと非同期パターンを使用して数百の Excel ファイルを効率的に処理する方法を示します。

次のステップは何ですか?

Excel Interop における COM オブジェクトのクリーンアップ問題は、長年にわたり.NET開発者を悩ませてきました。 すべての中間オブジェクトを追跡し、それらを正しい順序で解放し、参照を漏らさずに例外を処理すると、単純なスプレッドシート操作に大幅な複雑さが加わります。

IronXL は、より明確な前進の道を提供します。 Microsoft Office に依存せずに Excel ファイル形式を直接操作することで、COM オブジェクトの問題を根本から排除します。 既存のファイルを読み取る場合でも、新しいファイルを作成する場合でも、大規模なバッチを処理する場合でも、 IronXL は最新 for .NET開発で要求されるシンプルさで Excel スプレッドシート操作を処理します。

開始するには:

.NETエコシステム内の他の Excel ライブラリとの比較については、 Excel InteropEPPlus ライブラリGitHubリポジトリ、およびClosedXML プロジェクトに関する Microsoft ドキュメントを参照して、オプション間のトレードオフを理解してください。 IronXL の利点は、豊富な API、Office を必要としない展開、および単一の商用ライセンスによる完全なクロスプラットフォーム サポートの組み合わせです。

よくある質問

IronXLとは何ですか?

IronXL は、C# アプリケーション内で Excel ファイルの操作を簡素化し、Microsoft Office Interop の必要性を排除する.NETライブラリです。

Excel オブジェクトを C# でリリースする必要があるのはなぜですか?

C# で Excel オブジェクトを解放することは、パフォーマンスの問題やメモリ リークにつながる可能性がある Excel プロセスの残留を防ぐために重要です。

IronXL はExcel オブジェクトのクリーンアップにどのように役立ちますか?

IronXL はExcel オブジェクトのクリーンアップを自動化し、C# での手動による相互運用オブジェクト管理に関連する複雑さとエラーを削減します。

C# で Excel Interop を使用する際の課題は何ですか?

C# での Excel Interop では、COM オブジェクトを手動で管理する必要があるため、プロセスの残留やメモリ リークなどの問題が発生することがよくあります。

Microsoft Office をインストールせずに Excel ファイルを操作できますか?

はい、 IronXL を使用すると、システムに Microsoft Office をインストールしなくても Excel ファイルを操作できます。

IronXL はすべての Excel ファイル形式をサポートしていますか?

IronXL は、XLSX、XLS、CSV など、幅広い Excel ファイル形式をサポートしており、多様なファイル操作を可能にします。

IronXL は大規模な Excel ファイル操作に適していますか?

IronXLは、大規模な Excel ファイル操作を効率的に処理するように設計されており、エンタープライズ レベルのアプリケーションに適しています。

Excel InteropよりもIronXLを使用する利点は何ですか?

IronXL は、Excel Interop と比較して、コードの簡素化、パフォーマンスの向上、COM 関連の問題の排除などの利点を提供します。

IronXL をC# プロジェクトに統合するにはどうすればよいですか?

NuGetパッケージ マネージャー経由で IronXL をインストールし、アプリケーション コードで参照することで、 IronXL をC# プロジェクトに統合できます。

IronXL はExcel の数式をサポートしていますか?

はい、 IronXL はExcel の数式をサポートしており、C# アプリケーション内でそれらの読み取り、書き込み、評価が可能です。

カーティス・チャウ
テクニカルライター

Curtis Chauは、カールトン大学でコンピュータサイエンスの学士号を取得し、Node.js、TypeScript、JavaScript、およびReactに精通したフロントエンド開発を専門としています。直感的で美しいユーザーインターフェースを作成することに情熱を持ち、Curtisは現代のフレームワークを用いた開発や、構造の良い視覚的に魅力的なマニュアルの作成を楽しんでいます。

開発以外にも、CurtisはIoT(Internet of Things)への強い関心を持ち、ハードウェアとソフトウェアの統合方法を模索しています。余暇には、ゲームをしたりDiscordボットを作成したりして、技術に対する愛情と創造性を組み合わせています。

Iron Support Team

We're online 24 hours, 5 days a week.
Chat
Email
Call Me