.Net (C# または VB: don't care) では、実際に存在するファイルのファイル パス文字列、FileInfo 構造体、または FileSystemInfo 構造体が与えられた場合、シェル (エクスプローラー) が使用するアイコンをどのように判断できますか?ファイル?
現在、これを何にも使用する予定はありませんが、この質問を見たときにその方法に興味があり、SO でここにアーカイブしておくと便利だと思いました。
.Net (C# または VB: don't care) では、実際に存在するファイルのファイル パス文字列、FileInfo 構造体、または FileSystemInfo 構造体が与えられた場合、シェル (エクスプローラー) が使用するアイコンをどのように判断できますか?ファイル?
現在、これを何にも使用する予定はありませんが、この質問を見たときにその方法に興味があり、SO でここにアーカイブしておくと便利だと思いました。
Imports System.Drawing
Module Module1
Sub Main()
Dim filePath As String = "C:\myfile.exe"
Dim TheIcon As Icon = IconFromFilePath(filePath)
If TheIcon IsNot Nothing Then
''#Save it to disk, or do whatever you want with it.
Using stream As New System.IO.FileStream("c:\myfile.ico", IO.FileMode.CreateNew)
TheIcon.Save(stream)
End Using
End If
End Sub
Public Function IconFromFilePath(filePath As String) As Icon
Dim result As Icon = Nothing
Try
result = Icon.ExtractAssociatedIcon(filePath)
Catch ''# swallow and return nothing. You could supply a default Icon here as well
End Try
Return result
End Function
End Module
レジストリを使用するように言っている人は無視してください。レジストリは API ではありません。必要な API は、SHGFI_ICON を使用した SHGetFileInfo です。ここで P/Invoke 署名を取得できます。
ステファンの答えのC#バージョンにすぎません。
using System.Drawing;
class Class1
{
public static void Main()
{
var filePath = @"C:\myfile.exe";
var theIcon = IconFromFilePath(filePath);
if (theIcon != null)
{
// Save it to disk, or do whatever you want with it.
using (var stream = new System.IO.FileStream(@"c:\myfile.ico", System.IO.FileMode.CreateNew))
{
theIcon.Save(stream);
}
}
}
public static Icon IconFromFilePath(string filePath)
{
var result = (Icon)null;
try
{
result = Icon.ExtractAssociatedIcon(filePath);
}
catch (System.Exception)
{
// swallow and return nothing. You could supply a default Icon here as well
}
return result;
}
}
特定の拡張機能のアイコンのみに関心があり、一時ファイルを作成してもかまわない場合は、ここに表示されている例に従うことができます
C# コード:
public Icon LoadIconFromExtension(string extension)
{
string path = string.Format("dummy{0}", extension);
using (File.Create(path)) { }
Icon icon = Icon.ExtractAssociatedIcon(path);
File.Delete(path);
return icon;
}
レジストリ アプローチの問題は、アイコン インデックス ID を明示的に取得していないことです。場合によっては (常にではないにしても)、アプリケーション開発者がアイコンのスロットに名前を付けるために使用したエイリアスであるアイコン ResourceID を取得します。
したがって、レジストリ メソッドは、すべての開発者が暗黙的なアイコン インデックス ID (ゼロ ベース、絶対、決定論的) と同じ ResourceID を使用することを意味します。
レジストリの場所をスキャンすると、多くの負の数が表示され、場合によってはテキスト参照も表示されます。つまり、アイコン インデックス ID ではありません。OSに作業を任せるので、暗黙的な方法の方が良いようです。
現在、この新しい方法をテストしているだけですが、理にかなっていて、うまくいけばこの問題を解決します。
このリンクにはいくつかの情報があるようです。これには多くのレジストリのトラバースが含まれますが、実行可能のようです。例は C++ です
"HKCR\.{extension}"
、デフォルト値を読み取ります (それを と呼びましょうfiletype
)"HKCR\{filetype}\DefaultIcon"
、デフォルト値を読み取ります。これは、アイコン ファイル (または、アイコン リソースが埋め込まれた .exe などのアイコン コンテナー ファイル) へのパスです。コメントから編集/上に移動:
アイコンがコンテナ ファイル内にある場合 (これは非常に一般的です)、次のようにパスの後にカウンターが表示されます"foo.exe,3"
。これは、使用可能なアイコンのアイコン番号 4 (インデックスはゼロベース) であることを意味します。",0" の値は暗黙的 (およびオプション) です。カウンターが 0 または欠落している場合、最初に使用可能なアイコンがシェルによって使用されます。