C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

フォームを閉じるとエラー

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■93087 / inTopicNo.1)  フォームを閉じるとエラー
  
□投稿者/ じょこびっち (30回)-(2019/11/19(Tue) 14:31:22)

分類:[C#] 

閉じるボタンでフォームを閉じようとしたら
「System.NullReferenceException: 'オブジェクト参照がオブジェクト インスタンスに設定されていません。'」
となります。なにがいけないのでしょうか?
private void Close_Click(object sender, EventArgs e)
{
this.Close();
}

よろしくお願いします。
引用返信 編集キー/
■93089 / inTopicNo.2)  Re[1]: フォームを閉じるとエラー
□投稿者/ とっちゃん (645回)-(2019/11/19(Tue) 15:25:35)
No93087 (じょこびっち さん) に返信
> 閉じるボタンでフォームを閉じようとしたら
> 「System.NullReferenceException: 'オブジェクト参照がオブジェクト インスタンスに設定されていません。'」
> となります。なにがいけないのでしょうか?

クリックイベントが届いてから、Close を実行し、クリックイベントが終了するタイミングの
「どこかで」
オブジェクトが Null になってしまうところがあり、それを
「参照してしまうため」
その結果として、「System.NullReferenceException」例外が発生しています。

まずは
「デバッガ」
を利用して、デバッグ実行し、どこで例外が発生しているかを突き止めましょう。

場所がわかったら次は、なぜNullになってしまうかの原因を探し

最終的に Nullを参照してしまうことがないように修正します。

差し当たり、今ある情報で言えるのはこれだけなので、
後は実際にデバッグしてみないと原因は探れません。

実際に、最小限の環境として、
VS2019 で .NET Framework 版の Forms アプリを作成し
ボタンを一つ配置してその中で、this.Close() を呼び出した限り
この現象は発生しませんでした。

なので、記載されていない別の何かが原因でエラーになっています。
それは、過去ログを継ぎ接ぎした程度ではわからないので
まずは原因を突き止める必要があります。

引用返信 編集キー/
■93093 / inTopicNo.3)  Re[1]: フォームを閉じるとエラー
□投稿者/ KOZ (44回)-(2019/11/19(Tue) 16:22:00)
No93087 (じょこびっち さん) に返信
> 閉じるボタンでフォームを閉じようとしたら
> 「System.NullReferenceException: 'オブジェクト参照がオブジェクト インスタンスに設定されていません。'」

X ボタンで閉じられるのであれば

private void Close_Click(object sender, EventArgs e)
{
BeginInvoke((Action)Close, null);
}

で回避できる可能性があります。
引用返信 編集キー/
■93100 / inTopicNo.4)  Re[2]: フォームを閉じるとエラー
□投稿者/ じょこびっち (31回)-(2019/11/20(Wed) 09:31:34)
No93089 (とっちゃん さん) に返信
> まずは
> 「デバッガ」
> を利用して、デバッグ実行し、どこで例外が発生しているかを突き止めましょう。
>
> 場所がわかったら次は、なぜNullになってしまうかの原因を探し
>
> 最終的に Nullを参照してしまうことがないように修正します。

xボタン処理の中にオブジェクトを解放する一文を記述しており、
ここにブレークポイントを置いてみたところworkBookがnullになっていました。

現在作っている物はフォームからエクセルを立ち上げる事ができるようになっています。
フォームからエクセルを立ち上げてフォームを閉じると問題はないのですが
フォームからエクセルを立ち上げずに閉じるとworkbookがnullになっていたようです。
これを回避するにはどうすればいいでしょうか?

private void Form1_Load(object sender, EventArgs e)
{
// Excel
excelApp = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
}

private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (excelApp != null)
{
if (workBook != null)
{
workBook.Saved = true;
}
//excelApp.Quit();
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
}


No93093 (KOZ さん) に返信

> X ボタンで閉じられるのであれば
>
> private void Close_Click(object sender, EventArgs e)
> {
> BeginInvoke((Action)Close, null);
> }
>
> で回避できる可能性があります。

Xボタンでも同じなので回避できませんでした。
引用返信 編集キー/
■93103 / inTopicNo.5)  Re[3]: フォームを閉じるとエラー
□投稿者/ とっちゃん (646回)-(2019/11/20(Wed) 10:14:58)
No93100 (じょこびっち さん) に返信

コードを張りつけるときは図表モードにすると崩れなくていいですよ。

> 現在作っている物はフォームからエクセルを立ち上げる事ができるようになっています。
> フォームからエクセルを立ち上げてフォームを閉じると問題はないのですが
> フォームからエクセルを立ち上げずに閉じるとworkbookがnullになっていたようです。
> これを回避するにはどうすればいいでしょうか?
> 
> private void Form1_FormClosed(object sender, FormClosedEventArgs e)
> {
>   if (excelApp != null)
>   {
>     if (workBook != null)
>     {
>       workBook.Saved = true;
>     }
>     //excelApp.Quit();
>   }
>   System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
> }

見にくかったので、整形した形で引用させてもらいました。

上を見るとわかりますが、excelApp が null ではない場合はとみていますが、
肝心の ReleaseComObject を呼び出すところは null でも呼び出していますよね?

こんな感じにしてみるといいのでは?と思います。

private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
  if (excelApp != null)
  {
    if (workBook != null)
    {
      workBook.Saved = true;
    }
    //excelApp.Quit();
    System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
    excelApp = null;
  }
}


引用返信 編集キー/
■93104 / inTopicNo.6)  Re[4]: フォームを閉じるとエラー
□投稿者/ とっちゃん (647回)-(2019/11/20(Wed) 10:22:38)
追記。

ReleaseComObject をしているのが一つだけなので、他は書いてませんが
workBook も COM オブジェクトだと思うので、それらの解放も必須です。
それを怠ると、裏でエクセルが終了せずに生き残ってしまいますので、注意してください。

引用返信 編集キー/
■93107 / inTopicNo.7)  Re[5]: フォームを閉じるとエラー
□投稿者/ じょこびっち (32回)-(2019/11/20(Wed) 11:35:31)
No93103 (とっちゃん さん) に返信
> 
> コードを張りつけるときは図表モードにすると崩れなくていいですよ。

ご指摘ありがとうございます。次回から使ってみようと思います。

> こんな感じにしてみるといいのでは?と思います。
> 
> private void Form1_FormClosed(object sender, FormClosedEventArgs e)
> {
>   if (excelApp != null)
>   {
>     if (workBook != null)
>     {
>       workBook.Saved = true;
>     }
>     //excelApp.Quit();
>     System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
>     excelApp = null;
>   }
> }

出来ました!確かにexcelApp != nullの外でCOMの解放をしてました。

> ReleaseComObject をしているのが一つだけなので、他は書いてませんが
> workBook も COM オブジェクトだと思うので、それらの解放も必須です。
> それを怠ると、裏でエクセルが終了せずに生き残ってしまいますので、注意してください。

なるほど、勉強になります。これからコードを見直そうと思います。

とっちゃんさん、KOZさんありがとうございました。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ