冰楓論壇

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

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

[複製鏈接]

821

主題

0

好友

854

積分

高級贊助會員

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

UID
390967
帖子
1592
主題
821
精華
0
積分
854
楓幣
10961
威望
395
存款
10100
贊助金額
1800
推廣
0
GP
2677
閱讀權限
150
在線時間
189 小時
註冊時間
2023-5-18
最後登入
2024-11-21

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

跳轉到指定樓層
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-2024 冰楓論壇, All rights reserved

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

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

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

GMT+8, 2024-11-21 17:48

回頂部