tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re^3: Exeファイルの挙動が途中で止まる
投稿日: 2020/03/15(Sun) 16:54
投稿者魔界の仮面弁士
現状は原因が分からないので、虱潰しに探すしかないのですよね。
元ソースの一部をコメントアウトするなどして、挙動を止める原因となる行が特定できれば
話が早いのですけれども。

-------

> 早速Visible = Trueとさせて頂きましたが、
> 表にExcelが立ち上がってきてしまいます。
> 表示状態にすると必ずこうなってしまうのでしょうか。

邪魔に思えるかもしれませんが、仮に、ダイアログの表示によって停止していた場合には、
表示状態にしておいた方が問題を発見しやすいため、可能であれば
デバッグ終了までは True 設定にすることをお奨めしています。

-------

> 『Selection や Active 何某』とはなんのことなのでしょうか。
> 今回の事象とは関係なさそうとのことですが少し気になり…。

Excel VBA でマクロの記録を行うと、Activate メソッドや Selection プロパティを
多用したコードが散見されます。同様の呼び出しを VB から行っていないか…という事です。

VB において、
 Me.TextBox1.Text = "NewText"
と記述するところで、
 Me.TextBox1.Select()
 Me.ActiveControl.Text = "NewText"
と記述したりはしないですよね。それと同じことです。

1 回目に呼び出した Selection と 2 回目に呼び出した Selection では、
処理タイミングによっては別のオブジェクトを指し示す可能性がありますので、
「現在アクティブなオブジェクト」に対する操作は不安定になりがちです。
.NET からの呼び出しであれば猶のこと。

-------


> ちなみに例ではCellsが何を参照にしているかを明示していないため、
> 解放漏れが起きているという理解であっていますでしょうか。

その通りです。先の例では、『 Excel.[Global].Cells 』へのアクセスと見なされるでしょう。

これが「VBA」であれば、「自分自身」に対するアクセスなのでさほど問題になりませんが、
VB からの呼び出しの場合、どのオブジェクトの Cells なのか曖昧になるため、障害となります。

下記のように、VB6 においても障害となりえます。
http://hanatyan.sakura.ne.jp/vb6/excel01.htm#no3


-------

「COM オブジェクトを引数に渡すタイプのメンバー」(メソッドやプロパティ)の
呼び出しは極力控えてください。

特に、引数を Object 型で受け渡した場合、COM の参照カウントが予期せず増加してしまい、
正しく解放されなかったり、以前に破棄したオブジェクト情報を内部的に保持し続けてしまうことで
2 回目以降の呼び出しが誤動作するなどの障害を引き起こす可能性があります。


-------

Excel のオブジェクト階層としては、たとえばセルへのアクセスなら

Application オブジェクト → Workbooks プロパティ
→ Workbooks コレクション → Open メソッド/Add メソッド
 → Workbook オブジェクト → Sheets プロパティ/Worksheets プロパティ
  → Sheets コレクション → インデクサ、あるいは For/For Each での列挙
   → Worksheet オブジェクト(グラフシートの場合は Chart)
    → Range オブジェクト → Cells プロパティ/Range プロパティなど

という階層構造を取るはずです。

Application.ActiveCell などのように、途中の階層を飛ばしてアクセスするメンバーなども
ありますが、可能な限り段階を踏み、それぞれの COM オブジェクトを確実に変数に受け取って
Marshal.ReleaseComObject に引き渡してください。
(もちろん、使用中のオブジェクトを破棄するのは NG ですが)

-------

コレクションの列挙処理も要注意です。特に For Each の場合、IEnumVARIANT という
COM インターフェイスを中継することになるので、使用する COM 相互運用機能アセンブリによっては、
解放しにくくなることがあるようです。(しかも列挙子が .NET 側でラッピングされているがゆえに、
IsComObject が False となってしまい、内部の COM オブジェクトにアクセスしにくい)

なので For Each を使っている箇所がある場合、可能であれば
For ループや Do ループへの置き換えを検討してみてください。
https://divakk.co.jp/aoyagi/csharp_tips_vssenum.html
http://hanatyan.sakura.ne.jp/vbnetbbs/wforum.cgi?mode=allread&no=9291

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。