2010-05-16 43 views
13

Khi tôi sử dụng System.IO.DriveInfo.GetDrives() và xem tài sản .VolumeLabel của một trong các ổ đĩa, tôi thấy "PATRIOT XT", thực sự là nhãn ổ đĩa của ổ đĩa.Nhận nhãn lái xe trong C#

Nếu tôi mở "My Computer", thay vào đó tôi thấy "TrueCrypt Traveler Disk", và tôi dường như không tìm được cách nào để lấy giá trị đó theo chương trình vì không có thuộc tính DriveInfo nào giữ giá trị đó. Tôi cũng đã thử truy vấn thông tin qua số Win32_LogicalDisk của WMI, nhưng không có thuộc tính nào chứa giá trị đó.

Vì vậy, bất kỳ ý tưởng nào mà nhãn Máy tính của tôi sử dụng được gọi và quan trọng hơn là làm cách nào để truy xuất chương trình đó?

EDIT: Để được rõ ràng, đây là đoạn code tôi đang sử dụng, sau đó là những gì nó kết quả đầu ra, tiếp theo là những gì tôi nhìn thấy trong My Computer (đó là những gì tôi muốn lặp lại):

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 
    ); 
 
Removable (A:) 
Fixed (C:) 
CDRom (D:) 
PATRIOT XT (E:) 
Backup (Y:) 
Data (Z:) 

chi tiết My Computer xem màn hình:

 
Floppy Disk Drive (A:) 
Local Disk (C:) 
DVD RW Drive (D:) 
TrueCrypt Traveler Disk (E:) 
Backup (Y:) 
Data (Z:) 

Trả lời

0

tôi đã không cố gắng this bản thân mình, nhưng trong registry, tìm kiếm

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

sau đó đọc phím

DefaultLabel 

. Đồng thời CẢNH BÁO! ghi các khóa/giá trị không hợp lệ vào sổ đăng ký có thể làm hỏng nghiêm trọng hệ thống của bạn! Hãy chắc chắn rằng bạn chắc chắn về những gì bạn đang làm trước khi tiếp tục. Here is a resource to help you with accessing the registry programmatically.

+0

Bạn có hệ điều hành nào? Không có khóa có tên là "DriveIcons" trong Win XP Home !! – Nayan

+0

@Nayan - Tôi đang sử dụng Windows 7. –

+0

Khóa không tồn tại trong Vista. – Pindatjuh

0

This có vẻ như đây có thể là giải pháp.

+0

Cảm ơn, nhưng Win32_DiskDrive và Win32_PhysicalMedia dường như không giữ giá trị tôi đang tìm kiếm. Tôi đã thử một số lớp Win32 bây giờ, và không ai trong số họ dường như! – Rick

1

Có vẻ như Máy tính của tôi nhìn vào autorun.inf và sử dụng giá trị nhãn = từ phần [autorun].

Vẫn không hoàn toàn chắc chắn nơi nhãn "DVD RW Drive" và "Ổ đĩa mềm" đến từ đâu, nhưng tôi đoán chúng có thể được mã hóa cứng dựa trên loại ổ đĩa.

1

Tôi hy vọng sau đây sẽ giúp bạn:

[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; 
    } 
+0

Mã này nói chung không tốt và không hiển thị những gì OP muốn xem. Thông tin này được thu thập dễ dàng hơn từ 'System.IO.DriveInfo.GetDrives()'. – GSerg

0

Nó nằm trong thư mục autorun.inf. Khối lượng Label của tôi cho ổ đĩa flash của tôi chỉ đơn giản là 16G, nhưng bằng cách đặt một file autorun.inf với nội dung sau [autorun] label = My 16 GB Flash Drive

và sau đó sử dụng attrib để + s + h + r tập tin, nó không hiển thị trừ khi tôi có hiển thị các tệp ẩn và hiển thị tệp hệ thống trong tùy chọn thư mục/chế độ xem được bật.

Để lập trình xác định vị trí này qua C#, tôi đã không cố gắng mở autorun.inf, nhưng phải thẳng về phía trước, kiểm tra xem File.Exists (Drive: \ autorun.inf) bỏ qua thực tế là đó là + s + h + r (chỉ trong trường hợp ai đó đã đặt nó), sau đó mở nó chỉ đọc và phân tích cú pháp nhãn = dòng. Nếu trên thực tế, tệp có mặt, hãy sử dụng nhãn tự động thay vì Nhãn âm lượng.

Tôi vẫn có thể thay đổi sử dụng tính năng tự động chạy.inf label = tag ngay cả trong Windows 7 để sửa đổi nhãn.

3

Cảm ơn bạn đã tip về autorun.inf. Đây là đoạn C# mà tôi tạo ra để lấy nhãn.

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 
    } 
2

Thật không may, để có được thông tin này mà không cần hack và thủ thuật lạ, bạn cần sử dụng kỹ thuật P/Invoke. Có 2 tùy chọn:

  1. Nhận nhãn thực do người dùng hoặc hệ thống đặt. Đây có thể là "Ổ đĩa mới", "Cài đặt (\ Server)", "Đĩa cài đặt chuyên biệt Contoso Pro 4" và cứ tiếp tục như vậy.
  2. Lấy nhãn chính xác như được hiển thị trong Explorer (Máy tính của tôi/Cửa sổ PC này). Điều này giống với (1) nhưng nó tuân theo tùy chọn người dùng được đặt trong hộp thoại Tùy chọn thư mục, ví dụ: "Ẩn ký tự ổ đĩa". Ví dụ: "khối lượng mới (Q :)"

Để có được thông tin như được giải thích trong tùy chọn (1), bạn sẽ phải sử dụng đoạn mã sau:

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; 
    } 

Đối với tùy chọn (2), thay thế SIGDN.PARENTRELATIVEEDITING bằng SIGDN.PARENTRELATIVEEDITING hoặc SIGDN.NORMALDISPLAY.

Lưu ý: đối với tùy chọn 2, cũng có phương pháp 1 cuộc gọi sử dụng ShGetFileInfo(), nhưng nó vẫn gọi là các phương thức này và ít linh hoạt hơn, vì vậy tôi không đăng nó ở đây.

Lưu ý 2: lưu ý rằng chữ ký của SHGetNameFromIDList() được tối ưu hóa trong ví dụ này. Trong trường hợp nhãn ổ đĩa chỉ được sử dụng tạm thời (đặc biệt nếu nhãn được đọc lại theo thời gian), ví dụ này giới thiệu rò rỉ bộ nhớ nhỏ. Để tránh điều đó, tuyên bố tham số cuối cùng như out IntPtr, và sau đó sử dụng một cái gì đó giống như

 var tmp = Marshal.PtrToStringUni(ppszName); 
    Marshal.FreeCoTaskMem(ppszName); 

Note 3: Công việc này trên Windows vỏ, vì vậy nó sẽ trở lại những gì người dùng mong đợi, không phụ thuộc vào nguồn gốc của nhãn này - khối lượng nhãn, chỉnh sửa người dùng, tệp Autorun.inf hoặc bất kỳ thứ gì khác.

Các vấn đề liên quan