このメッセージ、ExcelやWordなんかのCOMオブジェクトを使っていて、書き方を間違えると発生するものですが、以下の様な書き方をしなければ、なかなかお目にかかれません.
いや、お目にかかりたくは無いんですけどねw
#region " USING "
using System;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
#endregion
namespace Com
{
/// <summary>
/// CExcel の概要の説明です。
/// </summary>
public class CExcel
{
/// <summary>
/// 引数無しコンストラクタ
/// </summary>
public CExcel()
{
}
/// <summary>
/// デストラクタ
/// </summary>
~CExcel()
{
}
/// <summary>
/// エラーを発生させてみるテスト.
/// </summary>
public void test()
{
// Local variable.
ApplicationClass objExcel = new ApplicationClass();
Worksheet objWorksheet = new Worksheet();
// Workbook 追加.
objExcel.Workbooks.Add(Type.Missing);
// 1ページ目の Worksheet を取得(非常識な取得の仕方ですが)
objWorksheet = (Worksheet)objExcel.Workbooks.get_Item(1)
.Worksheets.get_Item(1);
// Worksheet の名前を表示してみる.
MessageBox.Show(objWorksheet.Name); // Sheet1
/**
* 本来必要は無いが、Worksheet を COM オブジェクトとしてを解放し
* てみる.
* 更に解放した Worksheet の Delete メソッドを呼び出してみる.
* この時点では何故かエラーが出ない.
* そして、Worksheet の名前を参照しようとすると
*
* 基になる RCW から分割された COM オブジェクトを使うことはできません
*
* と言う、非常に分かりにくいエラーメッセージが発生 orz
* しかも、COM オブジェクト解放のみを実行した場合は、
*
* オブジェクト参照がオブジェクト インスタンスに設定されていません。
*
* と言う見慣れた「ああ、インスタンス化してねーじゃん」と言うメッ
* セージになり、Delete メソッドだけ実行した場合は、
*
* HRESULT からの例外です : 0x800401A8。
*
* と言うエラーが参照段階で発生します.
*/
this.releaseComObject(objWorksheet);
objWorksheet.Delete();
MessageBox.Show(objWorksheet.Name); // ここで例のエラーが発生.
// Excel 終了.
objExcel.Quit();
/**
* ここの COM オブジェクトリリースは必要.
* 解放しない場合、プログラムが終了するまで Excel プロセスが継続.
*/
this.releaseComObject(objExcel);
}
/// <summary>
/// すべてのCOMオブジェクトが解放されるまで、繰り返し ReleaseComObject を
/// 実行します。
/// </summary>
/// <param name="objInput">COMオブジェクト</param>
public void releaseComObject(Object objInput)
{
while (System.Runtime.InteropServices.Marshal.
ReleaseComObject(objInput) > 0);
objInput = null;
}
} // CExcel
} // namespace
※見た通り、全く意味の無い適当な書き方です.using System;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
#endregion
namespace Com
{
/// <summary>
/// CExcel の概要の説明です。
/// </summary>
public class CExcel
{
/// <summary>
/// 引数無しコンストラクタ
/// </summary>
public CExcel()
{
}
/// <summary>
/// デストラクタ
/// </summary>
~CExcel()
{
}
/// <summary>
/// エラーを発生させてみるテスト.
/// </summary>
public void test()
{
// Local variable.
ApplicationClass objExcel = new ApplicationClass();
Worksheet objWorksheet = new Worksheet();
// Workbook 追加.
objExcel.Workbooks.Add(Type.Missing);
// 1ページ目の Worksheet を取得(非常識な取得の仕方ですが)
objWorksheet = (Worksheet)objExcel.Workbooks.get_Item(1)
.Worksheets.get_Item(1);
// Worksheet の名前を表示してみる.
MessageBox.Show(objWorksheet.Name); // Sheet1
/**
* 本来必要は無いが、Worksheet を COM オブジェクトとしてを解放し
* てみる.
* 更に解放した Worksheet の Delete メソッドを呼び出してみる.
* この時点では何故かエラーが出ない.
* そして、Worksheet の名前を参照しようとすると
*
* 基になる RCW から分割された COM オブジェクトを使うことはできません
*
* と言う、非常に分かりにくいエラーメッセージが発生 orz
* しかも、COM オブジェクト解放のみを実行した場合は、
*
* オブジェクト参照がオブジェクト インスタンスに設定されていません。
*
* と言う見慣れた「ああ、インスタンス化してねーじゃん」と言うメッ
* セージになり、Delete メソッドだけ実行した場合は、
*
* HRESULT からの例外です : 0x800401A8。
*
* と言うエラーが参照段階で発生します.
*/
this.releaseComObject(objWorksheet);
objWorksheet.Delete();
MessageBox.Show(objWorksheet.Name); // ここで例のエラーが発生.
// Excel 終了.
objExcel.Quit();
/**
* ここの COM オブジェクトリリースは必要.
* 解放しない場合、プログラムが終了するまで Excel プロセスが継続.
*/
this.releaseComObject(objExcel);
}
/// <summary>
/// すべてのCOMオブジェクトが解放されるまで、繰り返し ReleaseComObject を
/// 実行します。
/// </summary>
/// <param name="objInput">COMオブジェクト</param>
public void releaseComObject(Object objInput)
{
while (System.Runtime.InteropServices.Marshal.
ReleaseComObject(objInput) > 0);
objInput = null;
}
} // CExcel
} // namespace
※参照追加でExcelのObjectLibraryを追加しないと動きません(念のため).
参考に「相互運用機能アセンブリを使った複雑な COM オブジェクトの処理 - Office のメニュー ボタンが機能停止した場合の対策」と言うページも見たのですが、未だにピンと来ません.
…私のレベルでは理解不能な話の様です orz
嗚呼低次元低次元...
0 件のコメント:
コメントを投稿