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

後で起動されたアプリケーションのコマンドライン引数を取得したい

環境/言語:[OS : Windows XP Home Edition / 言語 : Visual Basic .NET / .NET Framework : 2.0]
分類:[.NET]

【解決したい問題】

VB.NET2005を使用しています。

http://dobon.net/vb/dotnet/process/checkprevinstance.html
の「Visual Studio 2005以降のVB.NETで、Visual Basicアプリケーションモデルを使用する方法」
の「後で起動されたアプリケーションのコマンドライン引数を取得する」

を使用してアプリケーションを作成し、
そのアプリケーションに関連付けした拡張子のファイルを
2つ以上エクスプローラー上で選択した状態でEnterキーを押下すると
2つのファイルを読み込むような動作を期待していたのですが、
最初のひとつしかコマンドラインに読み込みません。

ファイルをドラッグアンドドロップや、ファイルひとつずつのマウスでのクリックでは読み込めます。

なにか回避策はあるでしょうか?
> 2つ以上エクスプローラー上で選択した状態でEnterキーを押下すると
> 2つのファイルを読み込むような動作を期待していたのですが、
> 最初のひとつしかコマンドラインに読み込みません。

エクスプローラの動作として、選択されたファイルそれぞれに対して既定のアクションしようとするからでしょう。
それからすると正しい挙動です。
期待している動作としては、コンテキストメニューの「送る」がそれにあたりますね。
というわけでエクスプローラの挙動を変えることが出来ない限り、おっしゃる操作では無理ということになります。
> 最初のひとつしかコマンドラインに読み込みません。

このコマンドラインとは、どのように取得したものでしょうか?StartupNextInstanceイベントハンドラで取得したものでしょうか?普通に考えると、StartupNextInstanceイベントは、(選択したファイル数-1)回発生し、それぞれ一つのコマンドラインしか取得できないと思われますが、このようになっていないということでしょうか?
■No20928に返信(管理人さんの記事)
>>最初のひとつしかコマンドラインに読み込みません。
>
> このコマンドラインとは、どのように取得したものでしょうか?StartupNextInstanceイベントハンドラで取得したものでしょうか?普通に考えると、StartupNextInstanceイベントは、(選択したファイル数-1)回発生し、それぞれ一つのコマンドラインしか取得できないと思われますが、このようになっていないということでしょうか?

そういうことです。

例えば、テキストボックスに単純に関連付けられた.TXTファイルの内容を追加するアプリを作った時、
アプリ起動中の時、
A.TXT
B.TXT
C.TXT
をエクスプローラー上でひとつずつ選択→Enterキー押下した場合は
それぞれ一個ずつStartupNextInstanceイベントで読み込めるのですが、

3つ選択した状態で→Enterキー押下した場合は
StartupNextInstanceイベントでは
For Each cmd As String In e.CommandLine
   My.Forms.Form1.fileOpen(cmd)
Next
のcmdにはA.TXTのみのイベントしか発生しません。

3つ選択した状態で→アプリ.exeにドラッグアンドドロップした場合は、
cmdはA,B,Cそれぞれが一度に(一度のイベントで)読み出せます。


StartupNextInstanceイベントが発生しない場合がある以上別の手を考えた方がいいかと思っていますがどんな方法が一般的なのでしょうか?
> 3つ選択した状態で→アプリ.exeにドラッグアンドドロップした場合は、
> cmdはA,B,Cそれぞれが一度に(一度のイベントで)読み出せます。

常識的に考えて、StartupNextInstanceイベントハンドラで、そのアプリ自身にドロップされたファイルのパスを取得できるのはおかしくないですか?例えば、Startupイベントと間違えているということはありませんか?それとも、すでに一つのインスタンスが作成されている状態でファイルをドロップしたということでしょうか?
■No20956に返信(管理人さんの記事)
>>3つ選択した状態で→アプリ.exeにドラッグアンドドロップした場合は、
>>cmdはA,B,Cそれぞれが一度に(一度のイベントで)読み出せます。
>
> 常識的に考えて、StartupNextInstanceイベントハンドラで、そのアプリ自身にドロップされたファイルのパスを取得できるのはおかしくないですか?例えば、Startupイベントと間違えているということはありませんか?それとも、すでに一つのインスタンスが作成されている状態でファイルをドロップしたということでしょうか?

>アプリ起動中の時
と書いてあります。

Startupイベントにも同じ処理が入っています。(コマンドラインを読む前に初期化処理が入っていますが)

問題は
関連付けられたファイルのマウスダブルクリックや
関連付けられたファイル選択がひとつの時のEnterキー押下、
関連付けられたファイル選択がひとつ又は複数の時のドラッグアンドドロップ
ではちゃんとStartupNextInstanceイベントが発生しコマンドラインが正しく読めますが、

関連付けられたファイル選択が複数の時のEnterキー押下の場合、
StartupNextInstanceイベントが一度しか発生せず、コマンドラインの数が選択されたファイルのうちのひとつしか読めないことなんです。
2007/11/14(Wed) 03:30:55 編集(投稿者)

試しにやってみましたが、問題なくできました。次のようなコードで確認しました。

Private Sub MyApplication_StartupNextInstance(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs) Handles Me.StartupNextInstance
For Each cmd As String In e.CommandLine
Form1.ListBox1.Items.Add(cmd)
Next
End Sub

複数のファイルをドロップしたときと、複数のファイルを選択してEnterキーを押した時の違いは、前者はStartupNextInstanceイベントが1回しか発生しないのに対して、後者は複数回発生するということでしょう。StartupNextInstanceイベントが複数回発生していないのは確かかをデバッグ等でもう一度お調べになってはいかがでしょうか。
■No20975に返信(管理人さんの記事)
> 2007/11/14(Wed) 03:30:55 編集(投稿者)
(中略)
>StartupNextInstanceイベントが複数回発生していないのは確かかをデバッグ等でもう一度お調べになってはいかがでしょうか。

ありがとうございます。
確かに複数回イベントが発生していました。
原因はStartupNextInstanceイベントではありませんでした。
申し訳ありません。

原因はStartupNextInstanceイベントが同時に発生してしまう為に
クリップボードのテキスト文を読む処理のところでエラーが発生していました。

同時に発生する原因は
System.Windows.Forms.SendKeys.SendWait
を実施すると次のStartupNextInstanceイベントが発生するようです。

System.Windows.Forms.SendKeys.SendWaitはMy.Application.DoEvents メソッドを呼び出してるのかな?

Monitor.EnterやSyncLockでロックかかるかやってみましたがかかりませんのでMy.Application.DoEventsメソッドが発生しない方法を考えて試してみます。

みなさんお手数をおかけしました。
ありがとうございます。
解決済み!

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