ASP.NET Web アプリケーションがサーバー上で自動化された Excel レポートを生成するとします。処理が終了したら、サーバー側の Excel.EXE を強制終了するにはどうすればよいですか。Excel ファイルが閉じられた後でも、ガベージ コレクターは Excel 実行可能ファイルをクリーンアップしないと思われるため、これを意図的に上げています。
何か参考になりますか?
ASP.NET Web アプリケーションがサーバー上で自動化された Excel レポートを生成するとします。処理が終了したら、サーバー側の Excel.EXE を強制終了するにはどうすればよいですか。Excel ファイルが閉じられた後でも、ガベージ コレクターは Excel 実行可能ファイルをクリーンアップしないと思われるため、これを意図的に上げています。
何か参考になりますか?
申し訳ありませんが、私は賢くしようとしているわけではありませんが、サーバーにオフィスを置かないでください!!!
それは私が正しく理解した場合です!:)
編集:私はこれについて非難されていますが、サーバー上で Office を実行することを推奨することは決してありません。
そうは言っても、同じことが私とCrystal Reportsにも当てはまります;-)
サーバー上で Office を実行しないことに同意します。この件に関して私に選択肢があるわけではありません:)
taskkill オプションで留意すべきことの 1 つは、それを具体的に計画しない限り (別名 - シングルトン)、実行中の Excel (またはその他の Office アプリ) の複数のコピーがあり、意図せずに間違ったインスタンスを閉じる可能性があることです。
また、 http://support.microsoft.com/kb/257757ごとに注意してください。
Office が不安定な動作を示したり、/または、この環境で Office を実行するとデッドロックが発生します。
別の方法として、サーバー環境で Excel シートをプログラムで操作できるように設計された製品を提供するAspose Cellsという製品があります。免責事項として、私はこの製品を個人的に使用したことはありませんが、過去に一緒に働いた何人かから聞いたことがあります.
この答えについて考える時間が増えたので、OpenXMLOfficeスプレッドシート形式でXMLアプローチを使用することをお勧めします。
ここに、コードを使用したオフィスドキュメントの作成を開始するためのいくつかの良いリンクがあります。 http://msdn.microsoft.com/en-us/magazine/cc163478.aspx http://msdn.microsoft.com/en-us/library/bb735940(office.12).aspx
SQLServerでSSISを使用するだけです。Excelにエクスポートする機能を提供します。サーバー上でオフィスを運営しないでください。代わりに、asposeまたはspreadsheetgearにお金を浪費します。
GCは、このパターンに従って適切に使用しないだけで機能します...
private void killExcel()
{
xlApp.Quit();
Marshal.ReleaseCOMObject(xlApp);
if(xlApp != null)
{
xlApp = null;
}
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
Excel操作クラスにIDisposableを実装させてから、disposeメソッドにkillExcel()を固定します。
更新:また、開発者がタスクマネージャーで実行されているExcel.exeを引き続き表示する場合があることにも注意してください。上記のコードが機能していないと想定する前に、コードを実行しているプロセスも閉じられていることを確認してください。VSTOまたはCOMアドインの場合は、起動プロセスに戻るGCルートがまだあるため、Word/パワーポイント/その他のExcelインスタンスも閉じられていることを確認してください。それが閉じられると、Excel.exeプロセスが閉じます。
同様の問題がありました。「taskkill excel.exe」またはすべての「Excel」プロセスを列挙して強制終了することはできますが、実行中のすべての Excel プロセスが強制終了されます。現在作業しているインスタンスのみを強制終了する方がよいでしょう。
これを達成するために使用したコードは次のとおりです。PInvoke (こちらを参照) を使用して、Excel.Application インスタンス (以下の例では Me.ExcelInstance) から ProcessID を取得します。
Dim ExcelPID As Integer
GetWindowThreadProcessId(New IntPtr(Me.ExcelInstance.Hwnd), ExcelPID)
If ExcelPID > 0 Then
Dim ExcelProc As Process = Process.GetProcessById(ExcelPID)
If ExcelProc IsNot Nothing Then ExcelProc.Kill()
End If
PInvoke が原因で、これはすべてのプラットフォームで機能しない可能性があることに注意してください... 現在のところ、これが信頼できる唯一の方法です。また、すべての Excel プロセスを列挙し、Process.MainModule.BaseAddress を Excel.Application.Hinstance と比較して、正しい PID を見つけようとしました。
'DO NOT USE THIS METHOD, for demonstration only
For Each p as Process in ExcelProcesses
Dim BaseAddr As Integer = p.MainModule.BaseAddress.ToInt32()
If BaseAddr = Me.ExcelInstance.Hinstance Then
p.Kill()
Exit For
End If
Next
これは正しいプロセスを見つけるための信頼できる方法ではありません。複数のプロセスで BaseAddress が同じように見えることがあるためです (その結果、間違った PID が強制終了されます)。
VSTOを使用していますか?excelobject.Quit();
作業が終了したら、Excel アプリを閉じることができます。
Excel 自体なしで Excel ファイルを作成するために、Excel の XML スキーマを調べることができます。まったく同じことを行うCarlosAg Excel Writerを確認してください。
:)。ここにExcelで小競り合いを書き留めました。また、いくつかの重い検索の後に見つけたリンクもいくつかあります。それが役に立てば幸い。
基本的にエクセルは自動化できるとはいえめんどくさい。
私はspreadsheetgearを使用してサーバー上でXLレポートを生成しましたが、これは非常にうまく機能します。EXCELプロセスについて心配する必要はありません。
また、mdb ファイルへのデータ アクセスを除いて、サーバー上で Office アプリを使用することもお勧めしません。
必要な場合があることは十分理解できます。そのような場合は、次のことをお勧めします。
絶対に同じサーバーで実行する必要がある場合は、少なくとも上記を独自のアプリ プールに実装してください。
仕事のキューを保持し、Excel (または他の Office アプリ) のインスタンスを 1 つだけ保持するように制限すると、TaskKill または .Kill() を使用して放棄して強制終了し、仕事を失うことはありません。
それを単一のスレッドに保持すれば、それを殺す必要はめったにないと思います。
私は実際に、これと似たような質問を少し前に受けました - Office オートメーションを使用しているときにハングした Office プロセスをチェックしてください- その質問への回答のいくつかはあなたにとって役立つかもしれません.
また、Office 製品をサーバーから切り離すことに関して、他の人が言っていることに同意する必要があります。ただし、Excel を使用しているので、 Excel XML ドキュメントを生成することは可能かもしれません。これは、Office オートメーションを実行しなくても実行でき、プロセスは非常に簡単です。単純なグリッド ベースのスプレッドシートの場合、Excel を使用して自動化するよりも少し簡単であることがわかりました。Office Open XMLは非常に強力であり、より複雑なレポートが可能であり、さらに労力を費やすことができます。
作業を終了したら、すべての COM 相互運用オブジェクトを安全に破棄する必要があります。「すべて」とは、コレクション、プロパティ値など、絶対にすべてを意味します。スタック オブジェクトを作成し、セットアップ中にオブジェクトをプッシュしました。
Stack<object> comObjectsToRelease = new Stack<object>();
...
Log("Creating VBProject object.");
VBProject vbProject = workbook.VBProject;
comObjectsToRelease.Push(vbProject);
...
finally
{
if(excel != null)
{
Log("Quiting Excel.");
excel.Quit();
excel = null;
}
while (comObjectsToRelease.Count > 0)
{
Log("Releasing {0} COM object.", comObjectsToRelease.GetType().Name);
Marshal.FinalReleaseComObject(comObjectsToRelease.Pop());
}
Log("Invoking garbage collection.");
GC.Collect();
}
Excel がまだ存在する場合は、手動で強制終了する必要があります。
同様の問題があり、次のコードを使用しました。
System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcesses();
for (int i = 0; i < procs.Length; i++)
{
if(procs[i].ProcessName == "EXCEL")
{
procs[i].Kill();
}
}
これはかなりうまくいきましたが、サーバー上で Office を使用することを本当に考えます。
最善の方法は、Aspose のライブラリなどの専用ライブラリを使用して、スプレッドシートを生成したり、テンプレートに入力したりすることです。次善の方法は、必要に応じてオフィス用の xml 形式を使用することです。場合によっては適切な軽量のアプローチは、1 つのテーブルを含む HTML ファイルを作成し、.xls 拡張子を付けて名前を付けることです。Excel は喜んでそれを読み取りますが、できることは非常に限られています。
これらは私が使用したオプションです(ただし、それほど多くはありません)。Microsoft Office Sharepoint Server というものもありますが、実際にどれくらいのことができるのかわかりません。
とは言うものの、通常の Excel ライブラリを呼び出すと、実際には .Net とは完全に独立して Excel をスピンアップし、実際にはプロキシ ライブラリと対話するだけで問題が発生しています。これは、WCF とサービスの場合とほとんど同じです。クライアント アプリケーションがサービスの使用を終了したからといって、サービスが終了するとは思わないでしょう。さらに悪いことに、Excel は管理されていないリソースであり、破棄/ファイナライズ/ガベージ コレクションがまったく行われません。.Net ランタイムは Excel については認識していません。それらのプロキシについて認識しているだけです。Application.quit は必要なものであり、作成された com オブジェクトを明示的に解放する必要がある場合もあります。