関連付けアプリケーションの起動でプロセスを取得

タグの編集
投稿者 日研迷琉  (社会人) 投稿日時 2023/10/31 17:07:27
何時も困ったら検索させて頂いております。

当方の環境は、Win10/VS2022/Fw4.8 で VB 開発中です。

問合せの内容は、題名の通りで コードは、下記内容です。

Dim Run_Process As System.Diagnostics.Process
Dim Filename as String = "C:\ABC.Jpg"
Run_Process = System.Diagnostics.Process.Start(Filename)

画像「ABC.Jpg」は、存在し、画面上にはビューアにて表示されているのですが
「Run_Process」には、「Nothing」が返ってきます。
対象ファイルが画像で無く「PDF」でも取得できていません。
他の方法で、『関連付けアプリケーションの取得』を参考に実行アプリケーションの
取得を試みましたがこちらも取得できませんでした。
プログラム的には、実行中に表示した画像をあるタイミングで閉じたいと思っております。
どなたかご教授よろしくお願いします。
投稿者 (削除されました)  () 投稿日時 2023/10/31 19:36:23
(削除されました)
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/10/31 20:13:01
> 実行中に表示した画像をあるタイミングで閉じたいと思っております。
残念ながら、汎用的な方法は無いと思います。
関連付け起動によってアプリを開くことができたとしても、
それをどうやって閉じるか、その手段は統一的ではありません。

たとえば、異なる複数の画像を同時に開こうとした場合、
「起動されるごとに新しいウィンドウで開かれる」アプリもあれば、
「すでにアプリが開かれていれば、同じウィンドウ内で別の画像を開きなおす」アプリもあるし、
「複数の画像を開いた場合も、すべて同一ウィンドウ内の別々のタブで開く」アプリもあります。

こうなると、メインウィンドウを閉じればよい…という単純な話にはならず、
CloseMainWindow メソッドが使える保証がありません。
そもそも今回のように、Process インスタンスを取得できないケースも珍しくないですし。

起動されるアプリケーションが固定的であるならば、現在開かれているウィンドウを列挙し、
その中で該当ウィンドウを探し当てて、目的の画像のみ閉じるようなコードを書くことは
できるかもしれませんが、アプリケーションごとに固有の操作になってしまうので、
汎用的な仕組みにするのは難しいでしょう。
相手がストア アプリ URI ランチャー アプリケーションの場合は特に。


> 「Nothing」が返ってきます。
「別のプロセスを起動して、直ちに終了してしまうプロセス」が呼び出された場合などは、
対象インスタンスが既に存在しないため、Process クラスで捉えられません。

'標準アプリ(フォト)で画像が開かれる 
Run_Process = System.Diagnostics.Process.Start(Filename)

'Nothing 
MsgBox(Run_Process?.HasExited)


'Windows Photo Viewer で画像が開かれる 
Run_Process = System.Diagnostics.Process.Start("rundll32.exe", $"""{Environment.GetEnvironmentVariable("ProgramFiles")}\Windows Photo Viewer\PhotoViewer.dll"",ImageView_Fullscreen {Filename}")
'False 
MsgBox(Run_Process?.HasExited)


'フォトで画像が開かれる 
Run_Process = New System.Diagnostics.Process()
'Run_Process.StartInfo.FileName = "shell:AppsFolder\Microsoft.Windows.Photos_8wekyb3d8bbwe!App" 
Run_Process.StartInfo.FileName = "ms-photos:"
Run_Process.StartInfo.Arguments = Filename
Run_Process.StartInfo.UseShellExecute = True
Run_Process.Start()

'InvalidOperationException:このオブジェクトに関連付けられているプロセスはありません。 
MsgBox(Run_Process.HasExited)


関連付け起動で(ストアアプリの)「フォト」が呼ばれた場合、
画像を表示しているのは PhotosApp.exe ですが、
同時に PhotoService.exe も起動されているようですね。

環境によっては、"ms-photos:viewer?fileName=C:\ABC.jpg&fullScreen=1" のように
呼び出せたという情報もあるのですが、現行バージョンではこのパラメーターが無視される模様。
https://learn.microsoft.com/ja-jp/windows/uwp/launch-resume/launch-default-app#photos-app-uri-scheme
https://github.com/MicrosoftDocs/windows-dev-docs/issues/2500
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/10/31 20:38:49
関連付け起動にこだわらないのなら、mspaint.exe で固定的に開く…という逃げ方。

Run_Process = System.Diagnostics.Process.Start("PBrush", Filename)

If Run_Process.WaitForInputIdle() AndAlso
    Not Run_Process?.HasExited AndAlso
    MsgBox("閉じる?", MsgBoxStyle.Question Or MsgBoxStyle.YesNo Or MsgBoxStyle.SystemModal) _
    = MsgBoxResult.Yes Then

    Run_Process.CloseMainWindow()

End If
Run_Process.Close()


あるいは画像ビューワー機能を自アプリ内に内包するとか。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/11/1 09:41:55
訂正。
コメントを修正し忘れていました。

下記コメントは「フォトで画像が開かれる」ではなく「フォトを起動する」が正しいです。
(指定したファイルを開くことはできないはず…)

> 'フォトで画像が開かれる 
> Run_Process = New System.Diagnostics.Process()
> 'Run_Process.StartInfo.FileName = "shell:AppsFolder\Microsoft.Windows.Photos_8wekyb3d8bbwe!App" 
> Run_Process.StartInfo.FileName = "ms-photos:"
投稿者 日研迷琉  (社会人) 投稿日時 2023/11/2 09:25:33
魔界の仮面弁士様、色々なコメントをたくさん頂きましてありがとうございました。

やはり難しそうですね。

実は今回、開く(起動する)ファイルは、固定ではなくDataGrid上に一覧されている
明細の詳細情報が別ファイル(画像やPDF、Excel,Word等)に保存されていて
明細のボタンをクリックすると表示する様なアプリケーションを作成しておりました。
ですので別画面が複数立ち上がるのを嫌ったためにこの様な仕様を考えたのですが
まっ、運用(手動)で閉じてもらえば良いだけなので仕組み的に出来ないと言う事で
勉強になりました。

色々とご教授ありがとうございました。
とりあえず解決と言う事でクローズさせて頂きます。