DOBON.NET DOBON.NETプログラミング掲示板過去ログ

最初のインスタンスのみにファイルを受け渡す

環境/言語:[Windows 7, VB.NET]
分類:[.NET]

こんにちは。以前はMac OS Xのアプリケーションをつくっていましたが、最近はWindows用のアプリケーションをつくっています。

最近作った簡単なアプリケーションはTabControlを使って複数のテキスト・ファイル(.rtf、.txt)を閲覧できるようにしています。またテキストファイルをダブルクリックした時にアプリケーションが起動してファイルを受け渡すようにしています。
'
Dim f As String = Command$()
If Not f = "" Then
OpenDoc(Replace(f, Chr(34), ""))
End If
'
Mac OS Xだと単一インスタンスでの起動しかできないので、ファイルを受け渡してそれで終わりです。Windowsの場合は単純にやるとアプリケーションが複数のインスタンスで起動してしまいますので、複数のインスタンスが起動しないようにしてあると、一度しかファイルを受け渡すことができません。どうやったら二重起動を禁止しながらファイルを最初のインスタンスのみに受け渡すことができるでしょうか?ちょっと自分のような初心者には難題です。二重起動は簡単に以下のコードで防いでいます。
'
If Process.GetProcessesByName(Process.GetCurrentProcess.ProcessName).Length > 1 Then
Application.Exit()
End If
'
よろしくお願いします。
こちらのページは確認済みでしょうか?
まだなのであれば、質問の前に Tips を探してみるなどすると、手間が減ると思います。

後で起動されたアプリケーションのコマンドライン引数を取得する
http://dobon.net/vb/dotnet/process/checkprevinstance.html#section5
■No30400に返信(Azuleanさんの記事)
> こちらのページは確認済みでしょうか?
> まだなのであれば、質問の前に Tips を探してみるなどすると、手間が減ると思います。
>
> 後で起動されたアプリケーションのコマンドライン引数を取得する
> http://dobon.net/vb/dotnet/process/checkprevinstance.html#section5

返答ありがとうございます。確認済みです。
■No30401に返信(缶吉さんの記事)
> 返答ありがとうございます。確認済みです。

確認してどうだったんでしょうか?
確認した、しないという事実だけでは正直何も進みません。

「後で起動されたアプリケーションのコマンドライン引数を取得する」という部分を使えない理由があるのですか?それともその部分をお読みになれていないのですか?
私の確認に対する答えとして、そういったことを書いてほしかったと思います。

なお、アプリケーションフレームワークを使えないとなると、プロセス間通信で面倒くさいことをやらないといけません。
WM_COPY やら、WCF やら、名前付きパイプやら、一時ファイルを使ってやるなど。
■No30399に返信(缶吉さんの記事)

Azuleanさんの提示されたリンク先をみると

> If Process.GetProcessesByName(Process.GetCurrentProcess.ProcessName).Length > 1 Then
>     Application.Exit()
> End If
こうではなくて

1.メニューの「プロジェクト」-「プロパティ」により、プロジェクトのプロパティを表示します。 
2.「アプリケーション」タブを選択します(デフォルトで選択されています)。 
3.「アプリケーションフレームワークを有効にする」にチェックを入れ、有効にします。 
4.「Windowsアプリケーションフレームワークプロパティ」の「単一インスタンスのアプリケーションを作成する」にチェックを入れます。 
5.以上です。 

で2重起動を防止して

Namespace My

    Partial Friend Class MyApplication

        Private Sub MyApplication_StartupNextInstance( _
                ByVal sender As Object, _
                ByVal e As Microsoft.VisualBasic.ApplicationServices. _
                StartupNextInstanceEventArgs) _
                Handles Me.StartupNextInstance
            Console.WriteLine("二重起動されました")

            '後で起動されたアプリケーションのコマンドライン引数を表示
            For Each cmd As String In e.CommandLine
                Console.WriteLine(cmd)
            Next

            '先に起動しているアプリケーションをアクティブにしない
            e.BringToForeground = False
        End Sub
    End Class


End Namespace

で後から起動されたプロセスにわたされたコマンドライン引数を取得しています。
後から起動されたプロセスというのは現在、Application.Exit()されているプロセスのことです。このプロセスにファイル名の情報が渡されているのではないでしょうか?
■No30403に返信(shuさんの記事)
> ■No30399に返信(缶吉さんの記事)
>
> Azuleanさんの提示されたリンク先をみると
>
>>If Process.GetProcessesByName(Process.GetCurrentProcess.ProcessName).Length > 1 Then
>> Application.Exit()
>>End If
> こうではなくて
>
> 1.メニューの「プロジェクト」-「プロパティ」により、プロジェクトのプロパティを表示します。
> 2.「アプリケーション」タブを選択します(デフォルトで選択されています)。
> 3.「アプリケーションフレームワークを有効にする」にチェックを入れ、有効にします。
> 4.「Windowsアプリケーションフレームワークプロパティ」の「単一インスタンスのアプリケーションを作成する」にチェックを入れます。
> 5.以上です。
>
> で2重起動を防止して
>
>
詳しい説明をありがとうございます。

「単一インスタンスのアプリケーションを作成する」は使っていません。これを使うと、他の自分のつくったアプリケーションの起動も妨害されてしまうようなので。
2012/05/07(Mon) 07:13:41 編集(投稿者)

■No30405に返信(缶吉さんの記事)
> 「単一インスタンスのアプリケーションを作成する」は使っていません。これを使うと、他の自分のつくったアプリケーションの起動も妨害されてしまうようなので。

それは、プロジェクトファイル一式をコピーして使っていると言うことではないですか? (テンプレートとして保存して GUID の部分のケアをしていない場合も同様)
プロジェクトファイルや AssemblyInfo.cs には GUID と呼ばれるユニークな ID が割り当てられています。本来はユニークなものをコピーしてしまっているが故に、弊害が出ていると言うことはありませんか?

作った後からであれば、プロジェクトファイル(*.vbproj)と AssemblyInfo.cs の GUID の部分を GUID 作成ツールで生成し直したものに置き換えてください。念のため、両方別々の ID にすることをお忘れなく。
(GUID 作成ツールがないのであれば、新規にプロジェクトを作ってそこからもらってくるのも手です)
■No30406に返信(Azuleanさんの記事)
> 2012/05/07(Mon) 07:13:41 編集(投稿者)
>
> ■No30405に返信(缶吉さんの記事)
>>「単一インスタンスのアプリケーションを作成する」は使っていません。これを使うと、他の自分のつくったアプリケーションの起動も妨害されてしまうようなので。
>
> それは、プロジェクトファイル一式をコピーして使っていると言うことではないですか? (テンプレートとして保存して GUID の部分のケアをしていない場合も同様)
> プロジェクトファイルや AssemblyInfo.cs には GUID と呼ばれるユニークな ID が割り当てられています。本来はユニークなものをコピーしてしまっているが故に、弊害が出ていると言うことはありませんか?

おっしゃる通りです。まだVBの使用は経験が浅いので、その原因がアプリケーションのCodeSignをしていないためか、また他の要因か知りませんでした。これからは新規プロジェクトからGUIDをもらうことにします。
■No30399に返信(缶吉さんの記事)
本題と関係ないですが

> Dim f As String = Command$()
・・・
> OpenDoc(Replace(f, Chr(34), ""))

Environment.GetCommandLineArgsを使えば
文字列配列としてコマンドライン引数を扱え、『"』も除去されるので提示されているReplaceはいらなくなります。
■No30408に返信(shuさんの記事)
> ■No30399に返信(缶吉さんの記事)
> 本題と関係ないですが
>
>>Dim f As String = Command$()
> ・・・
>>OpenDoc(Replace(f, Chr(34), ""))
>
> Environment.GetCommandLineArgsを使えば
> 文字列配列としてコマンドライン引数を扱え、『"』も除去されるので提示されているReplaceはいらなくなります。
>

いいえ。そういう小さい指示も初心者にとっては役に立ちます。ありがとうございます。No30399とhttp://dobon.net/vb/dotnet/process/checkprevinstance.html#section5に従ってこれから再度コードを立て直してみます。

また報告します。
知らなかったことですが、NamespaceMyのコードは「アプリケーションイベントの表示」を開いて使うのですね。

この変更により、ファイルをクリックすると最初のインスタンスにそれが引き渡されるようになりました。

shuさん、Azuleanさん、ありがとうございました。
解決しました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板