

お世話になります。

一般的には、フォームを立ち上げていても、ログオフやシャットダウンをすれば  
一緒に閉じるものなのですが、単体起動するフォームのアプリをdllにし、  
別のアプリから参照してdll化したフォームを立ち上げると、ログオフ、及び  
シャットダウンしたときには親フォームはきちんと閉じるのに、dll化した  
アプリの方が閉じずに、『このアプリが再起動を妨げています。』のような  
メッセージが出て、シャットダウンが止まってしまいます。

そのため、ネットで調べ、下記のイベントを実装して、シャットダウン、ログオフを  
しようとしたときに、併せてフォームが閉じるようにしようとしたのですが、これでも駄目。

[code]

    //ログオフ、シャットダウンしようとしているとき
    private void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
    {
            Application.Exit();
    }
    
[/code]

ちなみに、dll化したフォームはデジタル時計を作ったアプリで、Timerで  
一秒ごとフォームを再描画する仕様のものですが、それが何かの原因なのでしょうか？  
このフォームは、単体のexeのままなら、きちんとシャットダウン時に閉じてくれます。

原因と対策をご指導いただけますでしょうか。

よろしくお願いいたします。

追記・すみません。原因の探り方が甘かったみたいです。  
試してみたところ、原因はdll化した方ではなく、呼び出している親アプリの方でした。  
一度、ゼロからフォームを立ち上げて、そこに時計のdllフォームを呼び出せば、無事  
シャットダウンに併せてクローズ、しかし、空のフォームをdll化して既存の親のアプリで  
呼び出すと、時計の時と同じように再起動を妨げました。  
dllは一切問題はないようです。確認の方法が不足しており、申し訳ありませんでした。

さて、そこで親元のアプリの方ですが、クローズボタンを押しても終了させず、  
最小化させて、タスクトレイに常駐、アプリの終了はCotentMenuStripのメニューから  
『終了』を選ぶことで、Application.Exit()を呼び出して終了させる流れを作っています。

これが原因になっているのでしょうか。

更に追記・どうも原因がいろいろと重なっているらしく、親アプリの方でFormClisingで  
クローズをキャンセルするとシャットダウンの時にも終了されることがないようです。  
しかし、シャットダウン時の例の警告画面には親アプリの名前は出てきません。どういうわけか、  
親、子とも閉じられていないのに警告は子供のみ表示されるようです。

また、クローズをキャンセルすることで、上記SystemEvents_SessionEndingも  
実行されないようです。

更に問題は、例のシャットダウンの警告画面がSystemEvents_SessionEndingメソッドが  
走るより前に表示されてしまうため、たとえこのメソッドでクローズさせようとしても  
もう遅いということです(Windows10にて)。

初めの表題の内容とは意味合いが異なってしまいましたが、システムのシャットダウン時に、  
親アプリがきちんと終了させられれば解決できそうですが、  
そういった方法はありますでしょうか。

何度も申し訳ありませんが、よろしくお願いいたします。


CC BY-SA 3.0
2015-09-03T00:36:53.393
15163
2015-09-04T07:21:51.923
2015-09-04T04:40:40.810
9374
9374
question
c#
C# dllで表示したフォームをシャットダウン時に閉じたい


`FormClosing` イベントにて `FormClosingEventArgs` の `Cancel` プロパティを `false`
にするといいと思います。


CC BY-SA 3.0
2015-09-03T07:51:26.343
15185
2015-09-03T07:51:26.343
8870
15163
answer


Timer はメインスレッドではないスレッドで Elapsed をコールします。  
そのため、もし Elapsed
イベントハンドラ内で単純にその外部フォームを表示しているようでしたら、そのフォームはメッセージループのないフォームになってしまい、終了その他のイベントに応答できなくなりそうです。（ここらへんの結果的挙動は調べないと自信がありませんが。）

現状、フォーム表示のために Elapsed
イベント内で特になにもしていないようであれば、[マーシャリングの質問](https://stackoverflow.com/questions/709187/accessing-
ui-in-a-thread)などを参考に、UIスレッド上でフォームを作成するようにするとよいと思います。


CC BY-SA 3.0
2015-09-03T17:13:26.073
15210
2015-09-03T17:13:26.073
2017-05-23T12:38:56.467
-1
623
15163
answer


SystemEvent.SessionEndingイベントがUIスレッドで発生しない可能性がある場合は、次のように対処できます。

[code]

    private void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e){
        if( Application.OpenForms.Count > 0 ){
            var mainForm = Application.OpenForms[0];
            if( mainForm.InvokeRequired )
                mainForm.Invoke( new Action( Application.Exit ) );
            else
                Application.Exit();
        }
    }
    
[/code]


CC BY-SA 3.0
2015-09-04T04:30:54.883
16222
2015-09-04T04:30:54.883
2207
15163
answer


FormClosing の FormClosingEventArgs e.CloseReason の値で判定できませんか？  
CloseReason.WindowsShutDown, CloseReason.TaskManagerClosing
以外の時は最小化・タスクトレイ常駐・Cancel=Trueする  
(質問に記載の要件だけであれば CloseReason.WindowsShutDown以外の時だけでもいいかもしれません )


CC BY-SA 3.0
2015-09-04T06:50:23.193
16234
2015-09-04T07:21:51.923
2015-09-04T07:21:51.923
7343
7343
15163
answer