冰楓論壇

 找回密碼
 立即註冊
搜索
查看: 4119|回覆: 0
打印 上一主題 下一主題

[心得] [C#] 獲取硬碟資訊(非WMI方式)

[複製鏈接]

1114

主題

0

好友

1042

積分

高級贊助會員

Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20

UID
390967
帖子
2182
主題
1114
精華
0
積分
1042
楓幣
26494
威望
578
存款
10100
贊助金額
1800
推廣
0
GP
3799
閱讀權限
150
在線時間
272 小時
註冊時間
2023-5-18
最後登入
2025-12-27

2023年紀念勳章 太陽勳章 神手勳章 高級客戶 VIP會員 私服達人 懶人勳章 幼兒勳章 音樂勳章 屁孩勳章 貢獻王 性別(女) 性別(男) 積分勳章 發帖達人 2023端午節紀念勳章 富豪勳章 富可敵國 2023中秋節紀念勳章 解說達人 論壇粉絲 2023聖誕節紀念勳章 2024年紀念勳章 2024端午節紀念勳章 2024中秋節紀念勳章 2024聖誕節紀念勳章 2025年紀念勳章 2025端午節紀念勳章 2025中秋節紀念勳章 2025聖誕節紀念勳章

跳轉到指定樓層
1
發表於 2023-10-12 18:16:14 |只看該作者 |倒序瀏覽
本帖最後由 whitefox 於 2023-10-14 01:29 編輯

<20231014-修正一些多餘字串造成的錯誤>
需先創一個類別 HardDiskInfo 命名空間 Hardware(看各人喜好)
程式碼如下
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Text;

  4. namespace Hardware
  5. {
  6.     [Serializable]
  7.     public struct HardDiskInfo
  8.     {
  9.         /// <summary>
  10.         /// 型號
  11.         /// </summary>
  12.         public string ModuleNumber;
  13.         /// <summary>
  14.         /// 韌體版本
  15.         /// </summary>
  16.         public string Firmware;
  17.         /// <summary>
  18.         /// 序號
  19.         /// </summary>
  20.         public string SerialNumber;
  21.         /// <summary>
  22.         /// 容量,以M為單位
  23.         /// </summary>
  24.         public uint Capacity;
  25.     }

  26.     #region Internal Structs
  27.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  28.     internal struct GetVersionOutParams
  29.     {
  30.         public byte bVersion;
  31.         public byte bRevision;
  32.         public byte bReserved;
  33.         public byte bIDEDeviceMap;
  34.         public uint fCapabilities;
  35.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  36.         public uint[] dwReserved; // For future use.
  37.     }

  38.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  39.     internal struct IdeRegs
  40.     {
  41.         public byte bFeaturesReg;
  42.         public byte bSectorCountReg;
  43.         public byte bSectorNumberReg;
  44.         public byte bCylLowReg;
  45.         public byte bCylHighReg;
  46.         public byte bDriveHeadReg;
  47.         public byte bCommandReg;
  48.         public byte bReserved;
  49.     }

  50.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  51.     internal struct SendCmdInParams
  52.     {
  53.         public uint cBufferSize;
  54.         public IdeRegs irDriveRegs;
  55.         public byte bDriveNumber;
  56.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  57.         public byte[] bReserved;
  58.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  59.         public uint[] dwReserved;
  60.         public byte bBuffer;
  61.     }

  62.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  63.     internal struct DriverStatus
  64.     {
  65.         public byte bDriverError;
  66.         public byte bIDEStatus;
  67.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  68.         public byte[] bReserved;
  69.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
  70.         public uint[] dwReserved;
  71.     }

  72.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  73.     internal struct SendCmdOutParams
  74.     {
  75.         public uint cBufferSize;
  76.         public DriverStatus DriverStatus;
  77.         public IdSector bBuffer;
  78.     }

  79.     [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 512)]
  80.     internal struct IdSector
  81.     {
  82.         public ushort wGenConfig;
  83.         public ushort wNumCyls;
  84.         public ushort wReserved;
  85.         public ushort wNumHeads;
  86.         public ushort wBytesPerTrack;
  87.         public ushort wBytesPerSector;
  88.         public ushort wSectorsPerTrack;
  89.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  90.         public ushort[] wVendorUnique;
  91.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
  92.         public byte[] sSerialNumber;
  93.         public ushort wBufferType;
  94.         public ushort wBufferSize;
  95.         public ushort wECCSize;
  96.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
  97.         public byte[] sFirmwareRev;
  98.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
  99.         public byte[] sModelNumber;
  100.         public ushort wMoreVendorUnique;
  101.         public ushort wDoubleWordIO;
  102.         public ushort wCapabilities;
  103.         public ushort wReserved1;
  104.         public ushort wPIOTiming;
  105.         public ushort wDMATiming;
  106.         public ushort wBS;
  107.         public ushort wNumCurrentCyls;
  108.         public ushort wNumCurrentHeads;
  109.         public ushort wNumCurrentSectorsPerTrack;
  110.         public uint ulCurrentSectorCapacity;
  111.         public ushort wMultSectorStuff;
  112.         public uint ulTotalAddressableSectors;
  113.         public ushort wSingleWordDMA;
  114.         public ushort wMultiWordDMA;
  115.         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
  116.         public byte[] bReserved;
  117.     }
  118.     #endregion

  119.     /// <summary>
  120.     /// ATAPI磁碟機相關
  121.     /// </summary>
  122.     public class AtapiDevice
  123.     {
  124.         #region DllImport
  125.         [DllImport("kernel32.dll", SetLastError = true)]
  126.         static extern int CloseHandle(IntPtr hObject);

  127.         [DllImport("kernel32.dll", SetLastError = true)]
  128.         static extern IntPtr CreateFile(string lpFileName,
  129.                                         uint dwDesiredAccess,
  130.                                         uint dwShareMode,
  131.                                         IntPtr lpSecurityAttributes,
  132.                                         uint dwCreationDisposition,
  133.                                         uint dwFlagsAndAttributes,
  134.                                         IntPtr hTemplateFile);

  135.         [DllImport("kernel32.dll")]
  136.         static extern int DeviceIoControl(IntPtr hDevice,
  137.                                           uint dwIoControlCode,
  138.                                           IntPtr lpInBuffer,
  139.                                           uint nInBufferSize,
  140.                                           ref GetVersionOutParams lpOutBuffer,
  141.                                           uint nOutBufferSize,
  142.                                           ref uint lpBytesReturned,
  143.                                           [Out] IntPtr lpOverlapped);

  144.         [DllImport("kernel32.dll")]
  145.         static extern int DeviceIoControl(
  146.             IntPtr hDevice,
  147.             uint dwIoControlCode,
  148.             ref SendCmdInParams lpInBuffer,
  149.             uint nInBufferSize,
  150.             ref SendCmdOutParams lpOutBuffer,
  151.             uint nOutBufferSize,
  152.             ref uint lpBytesReturned,
  153.             [Out] IntPtr lpOverlapped);

  154.         const uint DFP_GET_VERSION = 0x00074080;
  155.         const uint DFP_SEND_DRIVE_COMMAND = 0x0007c084;
  156.         const uint DFP_RECEIVE_DRIVE_DATA = 0x0007c088;
  157.         const uint GENERIC_READ = 0x80000000;
  158.         const uint GENERIC_WRITE = 0x40000000;
  159.         const uint FILE_SHARE_READ = 0x00000001;
  160.         const uint FILE_SHARE_WRITE = 0x00000002;
  161.         const uint CREATE_NEW = 1;
  162.         const uint OPEN_EXISTING = 3;
  163.         #endregion

  164.         #region GetHddInfo
  165.         /// <summary>
  166.         /// 獲得硬碟資訊
  167.         /// </summary>
  168.         /// <param name="driveIndex">硬碟序號</param>
  169.         /// <returns>硬碟資訊</returns>
  170.         /// <remarks>
  171.         /// 在windows 98/ME中,S.M.A.R.T並不預設安裝,請將SMARTVSD.VXD拷貝到%SYSTEM%\iOSUBSYS目錄下。
  172.         /// 在Windows 2000/2003下,需要Administrators組的許可權。
  173.         /// </remarks>
  174.         /// <example>
  175.         /// AtapiDevice.GetHddInfo()
  176.         /// </example>
  177.         public static HardDiskInfo GetHddInfo(byte driveIndex)
  178.         {
  179.             switch (Environment.OSVersion.Platform)
  180.             {
  181.                 case PlatformID.Win32Windows:
  182.                     return GetHddInfo9x(driveIndex);
  183.                 case PlatformID.Win32NT:
  184.                     return GetHddInfoNT(driveIndex);
  185.                 case PlatformID.Win32S:
  186.                     throw new NotSupportedException("Win32s is not supported.");
  187.                 case PlatformID.WinCE:
  188.                     throw new NotSupportedException("WinCE is not supported.");
  189.                 default:
  190.                     throw new NotSupportedException("Unknown Platform.");
  191.             }
  192.         }

  193.         #region GetHddInfo9x
  194.         private static HardDiskInfo GetHddInfo9x(byte driveIndex)
  195.         {
  196.             GetVersionOutParams vers = new GetVersionOutParams();
  197.             SendCmdInParams inParam = new SendCmdInParams();
  198.             SendCmdOutParams outParam = new SendCmdOutParams();
  199.             uint bytesReturned = 0;
  200.             IntPtr hDevice = CreateFile(@"\\.\Smartvsd",
  201.                                         0,
  202.                                         0,
  203.                                         IntPtr.Zero,
  204.                                         CREATE_NEW,
  205.                                         0,
  206.                                         IntPtr.Zero);
  207.             if (hDevice == IntPtr.Zero)
  208.             {
  209.                 throw new Exception("Open smartvsd.vxd failed.");
  210.             }
  211.             if (0 == DeviceIoControl(hDevice,
  212.                                      DFP_GET_VERSION,
  213.                                      IntPtr.Zero,
  214.                                      0,
  215.                                      ref vers,
  216.                                      (uint)Marshal.SizeOf(vers),
  217.                                      ref bytesReturned,
  218.                                      IntPtr.Zero))
  219.             {
  220.                 CloseHandle(hDevice);
  221.                 throw new Exception("DeviceIoControl failed:DFP_GET_VERSION");
  222.             }
  223.             // If IDE identify command not supported, fails
  224.             if (0 == (vers.fCapabilities & 1))
  225.             {
  226.                 CloseHandle(hDevice);
  227.                 throw new Exception("Error: IDE identify command not supported.");
  228.             }
  229.             if (0 != (driveIndex & 1))
  230.             {
  231.                 inParam.irDriveRegs.bDriveHeadReg = 0xb0;
  232.             }
  233.             else
  234.             {
  235.                 inParam.irDriveRegs.bDriveHeadReg = 0xa0;
  236.             }
  237.             if (0 != (vers.fCapabilities & (16 >> driveIndex)))
  238.             {
  239.                 // We don't detect a ATAPI device.
  240.                 CloseHandle(hDevice);
  241.                 throw new Exception(string.Format("Drive {0} is a ATAPI device, we don't detect it", driveIndex + 1));
  242.             }
  243.             else
  244.             {
  245.                 inParam.irDriveRegs.bCommandReg = 0xec;
  246.             }

  247.             inParam.bDriveNumber = driveIndex;
  248.             inParam.irDriveRegs.bSectorCountReg = 1;
  249.             inParam.irDriveRegs.bSectorNumberReg = 1;
  250.             inParam.cBufferSize = 512;

  251.             if (0 == DeviceIoControl(hDevice,
  252.                                      DFP_RECEIVE_DRIVE_DATA,
  253.                                      ref inParam,
  254.                                      (uint)Marshal.SizeOf(inParam),
  255.                                      ref outParam,
  256.                                      (uint)Marshal.SizeOf(outParam),
  257.                                      ref bytesReturned,
  258.                                      IntPtr.Zero))
  259.             {
  260.                 CloseHandle(hDevice);
  261.                 throw new Exception("DeviceIoControl failed: DFP_RECEIVE_DRIVE_DATA");
  262.             }

  263.             CloseHandle(hDevice);

  264.             return GetHardDiskInfo(outParam.bBuffer);
  265.         }
  266.         #endregion

  267.         #region GetHddInfoNT
  268.         private static HardDiskInfo GetHddInfoNT(byte driveIndex)
  269.         {
  270.             GetVersionOutParams vers = new GetVersionOutParams();
  271.             SendCmdInParams inParam = new SendCmdInParams();
  272.             SendCmdOutParams outParam = new SendCmdOutParams();
  273.             uint bytesReturned = 0;
  274.             // We start in NT/Win2000
  275.             IntPtr hDevice = CreateFile(string.Format(@"\\.\PhysicalDrive{0}", driveIndex),
  276.                                         GENERIC_READ | GENERIC_WRITE,
  277.                                         FILE_SHARE_READ | FILE_SHARE_WRITE,
  278.                                         IntPtr.Zero,
  279.                                         OPEN_EXISTING,
  280.                                         0,
  281.                                         IntPtr.Zero);
  282.             if (hDevice == IntPtr.Zero)
  283.             {
  284.                 throw new Exception("CreateFile faild.");
  285.             }
  286.             if (0 == DeviceIoControl(hDevice,
  287.                                      DFP_GET_VERSION,
  288.                                      IntPtr.Zero,
  289.                                      0,
  290.                                      ref vers,
  291.                                      (uint)Marshal.SizeOf(vers),
  292.                                      ref bytesReturned,
  293.                                      IntPtr.Zero))
  294.             {
  295.                 CloseHandle(hDevice);
  296.                 throw new Exception(string.Format("Drive {0} may not exists.", driveIndex + 1));
  297.             }
  298.             // If IDE identify command not supported, fails
  299.             if (0 == (vers.fCapabilities & 1))
  300.             {
  301.                 CloseHandle(hDevice);
  302.                 throw new Exception("Error: IDE identify command not supported.");
  303.             }
  304.             // Identify the IDE drives
  305.             if (0 != (driveIndex & 1))
  306.             {
  307.                 inParam.irDriveRegs.bDriveHeadReg = 0xb0;
  308.             }
  309.             else
  310.             {
  311.                 inParam.irDriveRegs.bDriveHeadReg = 0xa0;
  312.             }
  313.             if (0 != (vers.fCapabilities & (16 >> driveIndex)))
  314.             {
  315.                 // We don't detect a ATAPI device.
  316.                 CloseHandle(hDevice);
  317.                 throw new Exception(string.Format("Drive {0} is a ATAPI device, we don't detect it.", driveIndex + 1));
  318.             }
  319.             else
  320.             {
  321.                 inParam.irDriveRegs.bCommandReg = 0xec;
  322.             }

  323.             inParam.bDriveNumber = driveIndex;
  324.             inParam.irDriveRegs.bSectorCountReg = 1;
  325.             inParam.irDriveRegs.bSectorNumberReg = 1;
  326.             inParam.cBufferSize = 512;

  327.             if (0 == DeviceIoControl(hDevice,
  328.                                      DFP_RECEIVE_DRIVE_DATA,
  329.                                      ref inParam,
  330.                                      (uint)Marshal.SizeOf(inParam),
  331.                                      ref outParam,
  332.                                      (uint)Marshal.SizeOf(outParam),
  333.                                      ref bytesReturned,
  334.                                      IntPtr.Zero))
  335.             {
  336.                 CloseHandle(hDevice);
  337.                 throw new Exception("DeviceIoControl failed: DFP_RECEIVE_DRIVE_DATA");
  338.             }

  339.             CloseHandle(hDevice);

  340.             return GetHardDiskInfo(outParam.bBuffer);
  341.         }
  342.         #endregion

  343.         private static HardDiskInfo GetHardDiskInfo(IdSector phdinfo)
  344.         {
  345.             HardDiskInfo hddInfo = new HardDiskInfo();
  346.             ChangeByteOrder(phdinfo.sModelNumber);
  347.             hddInfo.ModuleNumber = Encoding.ASCII.GetString(phdinfo.sModelNumber).Trim();
  348.             ChangeByteOrder(phdinfo.sFirmwareRev);
  349.             hddInfo.Firmware = Encoding.ASCII.GetString(phdinfo.sFirmwareRev).Trim();
  350.             ChangeByteOrder(phdinfo.sSerialNumber);
  351.             hddInfo.SerialNumber = Encoding.ASCII.GetString(phdinfo.sSerialNumber).Trim();
  352.             hddInfo.Capacity = phdinfo.ulTotalAddressableSectors / 2 / 1024;
  353.             return hddInfo;
  354.         }

  355.         private static void ChangeByteOrder(byte[] charArray)
  356.         {
  357.             byte temp;

  358.             for (int i = 0; i < charArray.Length; i += 2)
  359.             {
  360.                 temp = charArray[i];
  361.                 charArray[i] = charArray[i + 1];
  362.                 charArray[i + 1] = temp;
  363.             }
  364.         }
  365.         #endregion
  366.     }
  367. }
複製代碼
調用方式:
  1. HardDiskInfo hdd = AtapiDevice.GetHddInfo(0); // 第一個硬碟
  2. Console.WriteLine("Module Number: {0}", hdd.ModuleNumber);
  3. Console.WriteLine("Serial Number: {0}", hdd.SerialNumber);
  4. Console.WriteLine("Firmware: {0}", hdd.Firmware);
  5. Console.WriteLine("Capacity: {0} M", hdd.Capacity);
複製代碼
收藏收藏0 推0 噓0

分享這篇文章



把本文推薦給朋友或其他網站上,每次被點擊增加您在本站積分: 1鑰匙
複製連結並發給好友,以賺取推廣點數
簡單兩步驟,註冊、分享網址,即可獲得獎勵! 一起推廣文章換商品、賺$$
高級模式
B Color Image Link Quote Code Smilies |上傳

廣告刊登意見回饋關於我們管群招募本站規範DMCA隱私權政策詐騙防範及資料調閱

Copyright © 2011-2026 冰楓論壇, All rights reserved

免責聲明:本網站是以即時上載留言的方式運作,本站對所有留言的真實性、完整性及立場等,不負任何法律責任。

而一切留言之言論只代表留言者個人意見,並非本網站之立場,用戶不應信賴內容,並應自行判斷內容之真實性。

小黑屋|手機版|冰楓論壇

GMT+8, 2026-1-17 18:28

回頂部