14

ドライブの 1 つのプロパティを使用System.IO.DriveInfo.GetDrives()して見ると、.VolumeLabel実際にドライブのボリューム ラベルである「PATRIOT XT」が表示されます。

DriveInfo「マイ コンピュータ」を開くと、代わりに「TrueCrypt Traveler ディスク」が表示されます。その値を保持するプロパティがないため、プログラムでその値を取得する方法が見つからないようです。また、WMI を介して情報を照会しようとしましWin32_LogicalDiskたが、その値を含むプロパティもありませんでした。

My Computer が使用するラベルが何と呼ばれているか、さらに重要なことに、プログラムでそれを取得する方法について何か考えはありますか?

編集:明確にするために、ここに私が使用しているコード、次に出力するもの、次にマイコンピューターに表示されるものを示します(これは複製したいものです):

foreach (DriveInfo DI in DriveInfo.GetDrives())
    richTextBox1.AppendText(
        (
            DI.IsReady ?
            (DI.VolumeLabel.Length == 0 ? DI.DriveType.ToString() : DI.VolumeLabel) :
            DI.DriveType.ToString()
        )
        +
        " (" + DI.Name.Replace("\\", "") + ")"
        + Environment.NewLine
    );
リムーバブル (A:)
固定 (C:)
CDロム (D:)
パトリオット XT (E:)
バックアップ (Y:)
データ (Z:)

マイ コンピュータの詳細ビューが表示されます。

フロッピー ディスク ドライブ (A:)
ローカル ディスク (C:)
DVD RW ドライブ (D:)
TrueCrypt トラベラー ディスク (E:)
バックアップ (Y:)
データ (Z:)
4

8 に答える 8

6

残念ながら、ハッキングや奇妙なトリックを使わずにこの情報を取得するには、P/Invoke 手法を使用する必要があります。2 つのオプションがあります。

  1. ユーザーまたはシステムによって設定された実際のラベルを取得します。これは、「新しいボリューム」、「インストール (\Server)」、「Contoso Pro インストール ディスク 4」などです。
  2. エクスプローラー (マイ コンピューター / この 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 ファイルなど) に関係なく、ユーザーが期待するものを返します。

于 2015-03-22T18:41:40.053 に答える
3

autorun.inf についてのヒントをありがとう。ラベルを取得するために作成した C# フラグメントを次に示します。

private string GetDriveLabelFromAutorunInf(string drivename)
    {
        try
        {
            string filepathAutorunInf = Path.Combine(drivename, "autorun.Inf");
            string stringInputLine = "";
            if (File.Exists(filepathAutorunInf))
            {
                StreamReader streamReader = new StreamReader(filepathAutorunInf);
                while ((stringInputLine = streamReader.ReadLine()) != null) 
                  {
                      if (stringInputLine.StartsWith("label="))
                          return stringInputLine.Substring(startIndex:6);
                  }
                return "";
            }
            else return "";
        }
        #region generic catch exception, display message box, and terminate
        catch (Exception exception)
        {
            System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(exception, true);
            MessageBox.Show(string.Format("{0} Exception:\n{1}\n{2}\n\n{3}\n\nMethod={4}   Line={5}   Column={6}",
                    trace.GetFrame(0).GetMethod().Module,
                    exception.Message,
                    exception.StackTrace,
                    exception.ToString(),
                    trace.GetFrame(0).GetMethod().Name,
                    trace.GetFrame(0).GetFileLineNumber(),
                    trace.GetFrame(0).GetFileColumnNumber()),
                "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            Environment.Exit(1);
            return "";      // to keep compiler happy
        }
        #endregion
    }
于 2011-10-15T15:17:57.427 に答える
1

以下がお役に立てば幸いです。

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    static extern bool GetVolumeInformation(string Volume,
        StringBuilder VolumeName, uint VolumeNameSize,
        out uint SerialNumber, out uint SerialNumberLength, out uint flags,
        StringBuilder fs, uint fs_size);

    private void Form1_Load(object sender, EventArgs e)
    {
        uint serialNum, serialNumLength, flags;
        StringBuilder volumename = new StringBuilder(256);
        StringBuilder fstype = new StringBuilder(256);
        bool ok = false;
        Cursor.Current = Cursors.WaitCursor;
        foreach (string drives in Environment.GetLogicalDrives())
        {
            ok = GetVolumeInformation(drives, volumename, (uint)volumename.Capacity - 1, out serialNum,
                                   out serialNumLength, out flags, fstype, (uint)fstype.Capacity - 1);
            if (ok)
            {
                lblVolume.Text = lblVolume.Text + "\n Volume Information of " + drives + "\n";
                lblVolume.Text = lblVolume.Text + "\nSerialNumber of is..... " + serialNum.ToString() + " \n";
                if (volumename != null)
                {
                    lblVolume.Text = lblVolume.Text + "VolumeName is..... " + volumename.ToString() + " \n";
                }
                if (fstype != null)
                {
                    lblVolume.Text = lblVolume.Text + "FileType is..... " + fstype.ToString() + " \n";
                }
            }
            ok = false;
        }
        Cursor.Current = Cursors.Default;
    }
于 2010-05-17T07:11:49.877 に答える
1

マイコンピュータがautorun.infを調べ、[autorun]セクションのlabel=値を使用しているようです。

「DVDRWドライブ」と「フロッピーディスクドライブ」のラベルがどこから来ているのかはまだよくわかりませんが、ドライブの種類に基づいてハードコーディングされている可能性があります。

于 2010-05-16T20:23:20.167 に答える
0

これで解決できそうです。

于 2010-05-16T15:42:21.597 に答える
0

これは autorun.inf フォルダーにあります。フラッシュ ドライブのボリューム ラベルは単純に 16G ですが、autorun.inf ファイルに次のテキスト [autorun] label=My 16 GB Flash Drive を追加します。

+s +h +r ファイルに attrib を使用すると、隠しファイルを表示し、フォルダーオプション/ビューの下でシステムファイルを表示しない限り、表示されません。

C# を介してプログラムでこれを見つけるために、私は正直に autorun.inf を開こうとはしていませんが、それは +s+h+ であるという事実を無視して File.Exists(Drive:\autorun.inf) を確認してください。 r (誰かが設定した場合に備えて)、読み取り専用で開き、 label= 行を解析します。実際にファイルが存在する場合は、ボリューム ラベルの代わりに自動実行ラベルを使用してください。

Windows 7 でも autorun.inf label= タグを使用してラベルを変更できます。

于 2010-07-08T04:00:28.450 に答える
0

私はこれを自分で試したことはありませんが、レジストリで探します

HKLM/Software/Microsoft/Windows/CurrentVersion/Explorer/DriveIcons/[Drive-Letter]/

次に、

DefaultLabel

鍵。また、警告!無効なキー/値をレジストリに書き込むと、システムに重大な損傷を与える可能性があります! 先に進む前に、何をしているのかを確認してください。プログラムでレジストリにアクセスするのに役立つリソースを次に示します。

于 2010-05-16T13:45:25.893 に答える