ファイルに関連付けられているexeを知るには?

[戻る]
Arutu 2006/06/24(土) 22:00:15
FindExecutable
という関数を見つけ、ファイルをダブルクリックして開くexeのパスを知ることは出来きました。

しかし、複数のexeが関連付けしてある場合がありますよね?
エクスプローラでファイルを右クリックすると、「プログラムから開く」というメニューがあり、そ
れを選択すると、関連付けられているアプリケーション一覧が表示されると思います。

例えば *.avi ファイルの場合私のパソコンでは
Windows Media Player
Winamp
GOM Player
が表示されます。

その、関連付けられているすべてのアプリケーションのexeのパスなどを取得したいのですが、どうす
ればよいでしょう?

瀬戸っぷ [E-Mail] 2006/06/25(日) 01:08:40
> その、関連付けられているすべてのアプリケーションのexeのパスなどを取得したいの
ですが、
> どうすればよいでしょう?

試していませんが……
SHGetFileInfo()でSHFILEINFO構造体を取得し、
構造体メンバのszTypeNameをキーにして、
レジストリのHKEY_CLASSES_ROOT以下を探す。
さらにその下にshellというキーがあればその下を調べる。
というのでどうでしょう?
レジストリエディタで見てみると判るかと…

# ただし、シェル拡張で追加されているメニューは出てこないでしょうけど。

Arutu 2006/06/25(日) 17:30:06
返信ありがとうございます。

SHGetFileInfoを試したところ、
szTypeNameには*.txtの場合「テキスト ドキュメント」*.aviの場合「Winamp Media File」の文
字列が入っていました。
これってキーじゃないですよね?
レジストリエディタを見たところHKEY_CLASSES_ROOTの下層に、「.txt」やら「.avi」やらのフォ
ルダ(キー?)を見つけたので、szTypeNameには拡張子文字列が入っているのが正解なのでしょう
か?

といってもこの拡張子名のキーから各実行ファイルパス取得までの経路がイマイチなのですが・・・
一応「.avi」のデータから Winamp.File や GomPlayer.avi 等のキーを検索し、 shell -> 
open -> Command と辿って幾つかの実行ファイルパスを見つける手順は見つけられたのですが、
Windos Media Palyer 等、「.avi」から普通に辿っても見つけられない実行ファイルもあります
(例外?)

やはり、レジストリに関して勉強しないと難しいのでしょうか・・・・
FindExecutableのように関数一つで解決できる方法があればいいんですけどねぇ……

Blue 2006/06/25(日) 18:54:37
本題ではないですが、
> FindExecutableのように関数一つで解決できる
は問題があるそうです。
http://dobon.net/vb/dotnet/system/findassociatedexe.html

なので、上記のサイトにもありますが、レジストリの値から実行ファイルを取得するこ
とになります。
(上記サイトはC#,VB.NETの例ですので、キーの値はどれかのみ着目してください)
ただ、レジストリの値は「"○○○.exe" "%1"」のような値がありうるので、
Path〜の関数(shlwapi.h)を駆使して、実行ファイルパスを取得します。

    // 「"○○○.exe" "%1"」のような値の場合
    if ( !PathFileExists( レジストリの値 ) )
    {
        // 引数を削除
        PathRemoveArgs( レジストリの値 );
        // 前後の " を削除
        PathUnquoteSpaces( レジストリの値 );
    }

瀬戸っぷ [E-Mail] 2006/06/26(月) 00:10:25
> SHGetFileInfoを試したところ、
> szTypeNameには*.txtの場合「テキスト ドキュメント」*.aviの場合「Winamp Media
File」の
> 文字列が入っていました。
> これってキーじゃないですよね?

ありゃ、そういうのが取れましたか。
手元にお気楽に試せるコードが無かったので推測でしたが、そとらが返ってくるとは…

> といってもこの拡張子名のキーから各実行ファイルパス取得までの経路がイマイチなの
ですが・・・
> 一応「.avi」のデータから Winamp.File や GomPlayer.avi 等のキーを検索し、 shell -> 
open -> Command と辿って幾つかの実行ファイルパスを見つける手順は見つけられたので
すが、
> Windos Media Palyer 等、「.avi」から普通に辿っても見つけられない実行ファイルも
あります
> (例外?)

たどり方はソレでOKかと思います。
Windos Media Palyer(再生リストに追加/同期リストに追加/書き込みリストに追加)等は、
shellex -> ContextMenuHandlersの下のキーからCLSIDを取得して、
HKEY_CLASSES_ROOT\CLSID以下の該当のキーのInprocServer32辺りでしょうか。
*.aviの場合、HKEY_CLASSES_ROOT\.avi\ShellExの下にも何かあるようですが…

# DLLだったりするけど、どうやって渡すのか不明…
# シェル拡張とかで調べれば出てくるだろうか??

Arutu 2006/06/26(月) 00:51:09
Blue様情報ありがとうございます。
後々役に立ちそうです。

瀬戸っぷ様
> shellex -> ContextMenuHandlersの下のキーからCLSIDを取得して、
shellexとは何処のことでしょうか?

HKEY_CLASSES_ROOT\CLSID を調べたところ
{c5a40261-cd64-4ccf-84cb-c394da41d590}
等の謎の数列を見つけたのですが、
.avi -> ShellEx 内のフォルダ名またはデータ文字列も似たような謎の数列になっており、何らか
の関連をがあると感じました。

という経緯から
> shellex -> ContextMenuHandlers
は私の環境では
.avi -> ShellEx
のことではないかと察したのですが、違うでしょうか?

というかいろいろ複雑な予感がしますね。
これ以外にもいろいろ例外がありそうですし・・・

そろそろ調べるのあきらめようかな・・・・と思ったりもしますが、折角調べ始めたのでもうすこし
がんばってみます。
情報があればよろしくお願いしますm(__)m

Arutu 2006/06/26(月) 01:05:00
AVIFile というキーを見つけ、中にWindows Media Playerの情報がありました。

.avi キー内のデータにはそんなファイルタイプが見当たらないので、
「.avi」→「AVIFile」
っていう法則で拡張子を変換したキーはデフォルトで検索したほうがよさそうですね。

「.」を削って大文字にして「File」を後ろに追加すれば完成かな。

レジストリ強敵すぎる。

Arutu 2006/06/26(月) 11:14:36
レジストリに関していろいろ調べたところ、信頼性はともかくexeへの辿り方っぽい方法がわかってき
たので報告します。

例えば .avi の場合
HKEY_CURRENT_USER→Software→Microsoft→Windows→CurrentVersion→Explorer→
FileExts→.avi→OpenWithList

内のデータに各アプリケーション名が保存されていて、さらに一番下のデータ(MRUList)にその表示
順番が保存されています。

http://www5f.biglobe.ne.jp/~ayum/sample/fromp.html

そこで取得したアプリケーション名をキーとして

HKEY_CURRENT_USER→Software→Classes→Applications
と
HKEY_CLASSES_ROOT→Applications
下層のキーを検索し(前者の方が優先っぽい?)、

そこから
shell→xxxx(open等)→command

と辿ればexeのパスが取得できる気がします。
後は実際に使ってみて・・・って感じですかね・・・・

瀬戸っぷさんのCLSIDに関してはまだ調べてませんが、これも必要なのかな?(特殊な実行のしかた
の場合に必要?)

Arutu 2006/06/26(月) 19:36:12
[[解決]]
エクスプローラの「プログラムから開く」で表示される一覧は、上記以外にもさまざまなルートを
辿ってexeパスを特定しているようですね……

さらにいうと、commannd内のデータ(引数付きのパス)を取得してからが大変そうです……
Blueさんに紹介していただいた、PathRemoveArgsなども使ってみたのですが、例外で幾つか失敗す
るようです。

「プログラムから開く」にはほど遠いですが、まあ似たようなことが出来そうですし、これをもって
解決とさせていただきます。

いろいろありがとうございました。

古いスレッドには追加発言できません。