残念ながら、ハッキングや奇妙なトリックを使わずにこの情報を取得するには、P/Invoke 手法を使用する必要があります。2 つのオプションがあります。
- ユーザーまたはシステムによって設定された実際のラベルを取得します。これは、「新しいボリューム」、「インストール (\Server)」、「Contoso Pro インストール ディスク 4」などです。
- エクスプローラー (マイ コンピューター / この PC ウィンドウ) に表示されているラベルを正確に取得します。これは (1) と同じですが、「ドライブ文字を非表示にする」などの [フォルダ オプション] ダイアログで設定されたユーザー設定に従います。例: 「新しいボリューム (Q:)」
オプション (1) で説明した情報を取得するには、次のコードを使用する必要があります。
public const string SHELL = "shell32.dll";
[DllImport(SHELL, CharSet = CharSet.Unicode)]
public static extern uint SHParseDisplayName(string pszName, IntPtr zero, [Out] out IntPtr ppidl, uint sfgaoIn, [Out] out uint psfgaoOut);
[DllImport(SHELL, CharSet = CharSet.Unicode)]
public static extern uint SHGetNameFromIDList(IntPtr pidl, SIGDN sigdnName, [Out] out String ppszName);
public enum SIGDN : uint
{
NORMALDISPLAY = 0x00000000,
PARENTRELATIVEPARSING = 0x80018001,
DESKTOPABSOLUTEPARSING = 0x80028000,
PARENTRELATIVEEDITING = 0x80031001,
DESKTOPABSOLUTEEDITING = 0x8004c000,
FILESYSPATH = 0x80058000,
URL = 0x80068000,
PARENTRELATIVEFORADDRESSBAR = 0x8007c001,
PARENTRELATIVE = 0x80080001
}
//var x = GetDriveLabel(@"C:\")
public string GetDriveLabel(string driveNameAsLetterColonBackslash)
{
IntPtr pidl;
uint dummy;
string name;
if (SHParseDisplayName(driveNameAsLetterColonBackslash, IntPtr.Zero, out pidl, 0, out dummy) == 0
&& SHGetNameFromIDList(pidl, SIGDN.PARENTRELATIVEEDITING, out name) == 0
&& name != null)
{
return name;
}
return null;
}
SIGDN.PARENTRELATIVEEDITING
オプション (2) については、SIGDN.PARENTRELATIVE
またはに置き換えSIGDN.NORMALDISPLAY
ます。
注: オプション 2 には、 を使用した 1-call メソッドもありますShGetFileInfo()
が、とにかくこれらのメソッドを呼び出し、柔軟性が低いため、ここには投稿しません。
注 2 : この例では、 の署名SHGetNameFromIDList()
が最適化されていることに注意してください。ドライブ ラベルが一時的にのみ使用される場合 (特に時々再読み取りされる場合)、この例では小さなメモリ リークが発生します。それを避けるには、最後のパラメータを として宣言しout IntPtr
、次のようなものを使用します
var tmp = Marshal.PtrToStringUni(ppszName);
Marshal.FreeCoTaskMem(ppszName);
注 3 : これは Windows シェルで機能するため、このラベルのソース (ボリューム ラベル、ユーザー編集、Autorun.inf ファイルなど) に関係なく、ユーザーが期待するものを返します。