- PR -

起動中アプリケーションに対しての処理について

投稿者投稿内容
ダッチ
大ベテラン
会議室デビュー日: 2005/10/31
投稿数: 113
投稿日時: 2005-12-04 14:15
ダッチです。

ウィンドウを複数表示する常駐型アプリケーションを作成しようと思考中です。
タスクアイコンの「コンテキストメニュー」-「新規作成」から
ウィンドウを新規作成します。

常駐型アプリケーションなので多重起動される場合が考えられます。
その時に新たなウィンドウを新規作成したいのです。
しかし、どのようにすれば既に起動されているアプリケーションに対して
新規作成処理をしてくださいと教えることが出来るのかが不明です。

ご教示お願いいたします。

下記に多重起動部分のコードを記載いたします。

コード:
<STAThread()> _
    Public Shared Sub Main()

        ' Mutex の新しいインスタンスを生成
        Dim userMutex As System.Threading.Mutex = New System.Threading.Mutex(False, Application.ProductName)

        ' Mutex のシグナルを受信できるかどうか判断
        If userMutex.WaitOne(0, False) = True Then

            ' アプリケーション実行
            Application.Run(New MainWindow)

            ' 解放
            userMutex.ReleaseMutex()

        Else
            ' 既にアプリケーションが起動中

            ' ここに新規作成処理を教える処理を記載したい

        End If

        ' 破棄
        userMutex.Close()

    End Sub

じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-12-04 14:27
引用:

ダッチさんの書き込み (2005-12-04 14:15) より:

しかし、どのようにすれば既に起動されているアプリケーションに対して
新規作成処理をしてくださいと教えることが出来るのかが不明です。


「新規作成処理」を実装しているであろう、

引用:

ウィンドウを複数表示する常駐型アプリケーションを作成しようと思考中です。
タスクアイコンの「コンテキストメニュー」-「新規作成」から
ウィンドウを新規作成します。


この部分のメソッドを呼び出すだけなのではないでしょうか?

引用:

下記に多重起動部分のコードを記載いたします。

コード:

    <STAThread()> _
    Public Shared Sub Main()
        ' Mutex の新しいインスタンスを生成
        Dim userMutex As System.Threading.Mutex = New System.Threading.Mutex(False, Application.ProductName)

        ' Mutex のシグナルを受信できるかどうか判断
        If userMutex.WaitOne(0, False) = True Then

            ' アプリケーション実行
            Application.Run(New MainWindow)

            ' 解放
            userMutex.ReleaseMutex()
        Else
            ' 既にアプリケーションが起動中
            ' ここに新規作成処理を教える処理を記載したい
        End If

        ' 破棄
        userMutex.Close()
    End Sub



これって、Mutex を保持するオブジェクトが、GC の対象になる可能性がありませんか?
プライベート メンバな変数にするか、GC の対象から外してあげてください。

  二重起動を確実に禁止する

また、Try 〜 Finally で Close を保証してあげてください。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ダッチ
大ベテラン
会議室デビュー日: 2005/10/31
投稿数: 113
投稿日時: 2005-12-04 14:54
回答ありがとうございます。

引用:

じゃんぬねっとさんの書き込み(2005-12-04 14:27) より:

これって、Mutex を保持するオブジェクトが、GC の対象になる可能性がありませんか?
プライベート メンバな変数にするか、GC の対象から外してあげてください。

  二重起動を確実に禁止する

また、Try 〜 Finally で Close を保証してあげてください。



Mutexの扱いを修正いたしました。

コード:
<STAThread()> _
    Public Shared Sub Main()

        Dim userMutex As System.Threading.Mutex

        Try

            ' Mutex の新しいインスタンスを生成
            userMutex = New System.Threading.Mutex(False, Application.ProductName)

            ' Mutex のシグナルを受信できるかどうか判断
            If userMutex.WaitOne(0, False) = True Then

                ' Mutex をガベージコレクションから外す
                GC.KeepAlive(userMutex)

                ' アプリケーション実行
                Application.Run(New MainWindow)

                ' 解放
                userMutex.ReleaseMutex()

            Else

                ' 既にアプリケーションが起動中
                Dim mainWindow As MainWindow = New MainWindow
                ' 新規作成処理
                mainWindow.AddWindow()

            End If

        Finally

            ' 破棄
            If Not userMutex Is Nothing Then
                userMutex.Close()
            End If

        End Try

    End Sub



引用:

この部分のメソッドを呼び出すだけなのではないでしょうか?



' 新規作成処理
mainWindow.AddWindow()
を実行しても一瞬でウィンドウが閉じてしまいます。
おそらくApplication.Run(New MainWindow)
で生成した MainWindow のインスタンスに対して
処理を行っていないからではないかと思います。
そのためメッセージループされていないのではないでしょうか。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-12-04 15:24
GC.KeepAliveは、
引用:

このメソッドは、 obj オブジェクトを参照し、ルーチンの開始時からこのメソッドが呼び出される時点までの間、そのオブジェクトをガベージ コレクションの対象から外します。このメソッドのコードは、 obj を使用可能にする必要がある命令の範囲の最初ではなく最後に作成します。


の通り、事前ではなく事後に呼び出すメソッドです。非常に奇妙な印象を受けますが。


さて、Mutexで多重起動を制限したとしても、実際に実行ファイルをダブルクリックしたときに起動するのは元々存在しているプロセスとは(当然のことながら)別のプロセスです。
既存プロセスに処理をお願いしなければなりません。
手段はいくつか考えられます。代表的なものは、
  • .NETのプロセス間通信である.NET Remoting
  • DDE
  • Windowsメッセージ
  • 名前つきイベント(Mutexでもできるっけ)
下のものほど、新規プロセスから既存プロセスに送信できる情報が限られるようになります。また例に挙げたものでは.NET Remoting以外はWin32APIに頼る必要性が出てきます。
プロセス間通信で調べれば情報は様々に出てくるでしょう。
一番実装が簡単なのは、適当なメッセージをSendMessage関数(Win32APIです)を使って送信することでしょうか。
既存プロセスは対応する手段で起動を感知し、それに対応した処理を行います。

<チラシの裏>
そういえばDDEMLのクラス化放置しっぱなしだな……。
</チラシの裏>
ダッチ
大ベテラン
会議室デビュー日: 2005/10/31
投稿数: 113
投稿日時: 2005-12-04 15:44
回答ありがとうございます。

引用:

Hongliangさんの書き込み(2005-12-04 15:24) より:

GC.KeepAliveは、

このメソッドは、 obj オブジェクトを参照し、ルーチンの開始時からこのメソッドが呼び出される時点までの間、そのオブジェクトをガベージ コレクションの対象から外します。このメソッドのコードは、 obj を使用可能にする必要がある命令の範囲の最初ではなく最後に作成します。

の通り、事前ではなく事後に呼び出すメソッドです。非常に奇妙な印象を受けますが。




確かに奇妙な印象を受けますがご指摘ありがとうございます。
修正いたします。

引用:


  • .NETのプロセス間通信である.NET Remoting
  • DDE
  • Windowsメッセージ
  • 名前つきイベント(Mutexでもできるっけ)




貴重な情報ありがとうございます。
なるべく Win32API は使用したくありませんので、
ますは.NET Remoting から調べたいと思います。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2005-12-04 16:05
ちょっと疑問なんですが…
今回出てるような処理の流れで、GC.KeepAlive()って必要ですか?
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-12-04 16:16
引用:

ちょっと疑問なんですが…
今回出てるような処理の流れで、GC.KeepAlive()って必要ですか?


Mutexがローカル変数である場合は必要です。
http://dobon.net/vb/dotnet/process/checkprevinstance.html
うまい理屈付けは私にはできてないんですけど。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2005-12-04 16:23
引用:

Hongliangさんの書き込み (2005-12-04 16:16) より:
Mutexがローカル変数である場合は必要です。
http://dobon.net/vb/dotnet/process/checkprevinstance.html
うまい理屈付けは私にはできてないんですけど。


mutexのcloseが後ろにあっても駄目なんですかね?
※念のため、私は「後ろにCloseがあるから不要なのでは?」と思ったわけです。

スキルアップ/キャリアアップ(JOB@IT)