主页 > 卜八资讯 > 用C#获取硬盘序列号,CPU序列号,网卡MAC地址

用C#获取硬盘序列号,CPU序列号,网卡MAC地址

这个问题首先得考虑的就是你的硬盘是不是SCSI硬盘  
  如果是,那么根本不存在"物理序列号",只可能取得卷标的序列号  
   
  如果是卷标序列号,要注意的是每次格式化硬盘的时候这个序列号都会变  
  代码可以参考:  
  ?Id=25196  
   
  如果是物理序列号:  
  String   HDid;  
  ManagementClass   cimobject   =   new   ManagementClass("Win32_DiskDrive");  
  ManagementObjectCollection   moc   =   cimobject.GetInstances();  
  foreach(ManagementObject   mo   in   moc)  
  {  
  HDid   =   (string)mo.Properties["Model"].Value;  
  MessageBox.Show(HDid   );    
  }

如果是取得逻辑序列号(Format产生的那个),用WMI就可以,在引用中,添加system.mangement以后。    
  using   System.Management;  
  .....  
  ManagementObject     m_objDisk     =     new     ManagementObject(     "win32_logicaldisk.deviceid=\"c\"");          
  string     strSN     =     (string)m_objDisk.GetPropertyValue(     "VolumeSerialNumber     ");          
   
  如果要取得物理分区号,看这个帖子:  
  关于硬盘序列号,高手请留步啊.   (之一)  
  ?id=1143107  

683E0480(第一种方案取得)

ST3160815AS (第二个方案取得的)

5239355835565745202020202020202020202020(第三种方案取得)

private string[] GetMoc()
        
{
            
string[] str = new string[3];
            ManagementClass mcCpu 
= new ManagementClass("win32_Processor");
            ManagementObjectCollection mocCpu 
= mcCpu.GetInstances();
            
foreach(ManagementObject m in mocCpu)
            
{
                str[
0= m["ProcessorId"].ToString();
            }


            ManagementClass mcHD = new ManagementClass("win32_logicaldisk");
            ManagementObjectCollection mocHD 
= mcHD.GetInstances();
            
foreach(ManagementObject m in mocHD)
            
{
                
if(m["DeviceID"].ToString() == "C:")
                
{
                    str[
1= m["VolumeSerialNumber"].ToString();
                    
break;
                }

            }


            ManagementClass mcMAC = new ManagementClass("Win32_NetworkAdapterConfiguration");
            ManagementObjectCollection mocMAC 
= mcMAC.GetInstances();
            
foreach(ManagementObject m in mocMAC)
            
{
                
if((bool)m["IPEnabled"])
                
{
                    str[
2= m["MacAddress"].ToString();
                    
break;
                }

            }


            return str;
        }

以上为取硬盘逻辑分区序列号,重新格式化会改变

以下为硬盘物理序列号,需管理员权限,wmi

 Code

using System;
using System.Management;

namespace HTSoft.Common.Register
{
    
/// <summary> 
    
/// 计算机信息类
    
/// </summary> 
    internal class Computer
    {
        
public string CpuID;
        
public string MacAddress;
        
public string DiskID;
        
public string IpAddress;
        
public string LoginUserName;
        
public string ComputerName;
        
public string SystemType;
        
public string TotalPhysicalMemory; //单位:M 
        private static Computer _instance;

        
internal static Computer Instance()
        {
            
if (_instance == null)
                _instance 
= new Computer();
            
return _instance;
        }

        
internal Computer()
        {
            CpuID 
= GetCpuID();
            MacAddress 
= GetMacAddress();
            DiskID 
= GetDiskID();
            IpAddress 
= GetIPAddress();
            LoginUserName 
= GetUserName();
            SystemType 
= GetSystemType();
            TotalPhysicalMemory 
= GetTotalPhysicalMemory();
            ComputerName 
= GetComputerName();
        }
        
string GetCpuID()
        {
            
try
            {
                
//获取CPU序列号代码 
                string cpuInfo = "";//cpu序列号 
                ManagementClass mc = new ManagementClass("Win32_Processor");
                ManagementObjectCollection moc 
= mc.GetInstances();
                
foreach (ManagementObject mo in moc)
                {
                    cpuInfo 
= mo.Properties["ProcessorId"].Value.ToString();
                }
                moc 
= null;
                mc 
= null;
                
return cpuInfo;
            }
            
catch
            {
                
return "unknow";
            }
            
finally
            {
            }

        }
        
string GetMacAddress()
        {
            
try
            {
                
//获取网卡硬件地址 
                string mac = "";
                ManagementClass mc 
= new ManagementClass("Win32_NetworkAdapterConfiguration");
                ManagementObjectCollection moc 
= mc.GetInstances();
                
foreach (ManagementObject mo in moc)
                {
                    
if ((bool)mo["IPEnabled"== true)
                    {
                        mac 
= mo["MacAddress"].ToString();
                        
break;
                    }
                }
                moc 
= null;
                mc 
= null;
                
return mac;
            }
            
catch
            {
                
return "unknow";
            }
            
finally
            {
            }

        }
        
string GetIPAddress()
        {
            
try
            {
                
//获取IP地址 
                string st = "";
                ManagementClass mc 
= new ManagementClass("Win32_NetworkAdapterConfiguration");
                ManagementObjectCollection moc 
= mc.GetInstances();
                
foreach (ManagementObject mo in moc)
                {
                    
if ((bool)mo["IPEnabled"== true)
                    {
                        
//st=mo["IpAddress"].ToString(); 
                        System.Array ar;
                        ar 
= (System.Array)(mo.Properties["IpAddress"].Value);
                        st 
= ar.GetValue(0).ToString();
                        
break;
                    }
                }
                moc 
= null;
                mc 
= null;
                
return st;
            }
            
catch
            {
                
return "unknow";
            }
            
finally
            {
            }

        }

        
string GetDiskID()
        {
            
try
            {
                
//获取硬盘ID 
                String HDid = "";
                ManagementClass mc 
= new ManagementClass("Win32_DiskDrive");
                ManagementObjectCollection moc 
= mc.GetInstances();
                
foreach (ManagementObject mo in moc)
                {
                    HDid 
= (string)mo.Properties["Model"].Value;
                }
                moc 
= null;
                mc 
= null;
                
return HDid;
            }
            
catch
            {
                
return "unknow";
            }
            
finally
            {
            }

        }

        
/// <summary> 
        
/// 操作系统的登录用户名 
        
/// </summary> 
        
/// <returns></returns> 
        string GetUserName()
        {
            
try
            {
                
string st = "";
                ManagementClass mc 
= new ManagementClass("Win32_ComputerSystem");
                ManagementObjectCollection moc 
= mc.GetInstances();
                
foreach (ManagementObject mo in moc)
                {

                    st 
= mo["UserName"].ToString();

                }
                moc 
= null;
                mc 
= null;
                
return st;
            }
            
catch
            {
                
return "unknow";
            }
            
finally
            {
            }

        }


        
/// <summary> 
        
/// PC类型 
        
/// </summary> 
        
/// <returns></returns> 
        string GetSystemType()
        {
            
try
            {
                
string st = "";
                ManagementClass mc 
= new ManagementClass("Win32_ComputerSystem");
                ManagementObjectCollection moc 
= mc.GetInstances();
                
foreach (ManagementObject mo in moc)
                {

                    st 
= mo["SystemType"].ToString();

                }
                moc 
= null;
                mc 
= null;
                
return st;
            }
            
catch
            {
                
return "unknow";
            }
            
finally
            {
            }

        }

        
/// <summary> 
        
/// 物理内存 
        
/// </summary> 
        
/// <returns></returns> 
        string GetTotalPhysicalMemory()
        {
            
try
            {

                
string st = "";
                ManagementClass mc 
= new ManagementClass("Win32_ComputerSystem");
                ManagementObjectCollection moc 
= mc.GetInstances();
                
foreach (ManagementObject mo in moc)
                {

                    st 
= mo["TotalPhysicalMemory"].ToString();

                }
                moc 
= null;
                mc 
= null;
                
return st;
            }
            
catch
            {
                
return "unknow";
            }
            
finally
            {
            }
        }
        
/// <summary> 
        
///  获取计算机名称
        
/// </summary> 
        
/// <returns></returns> 
        string GetComputerName()
        {
            
try
            {
                
return System.Environment.GetEnvironmentVariable("ComputerName");
            }
            
catch
            {
                
return "unknow";
            }
            
finally
            {
            }
        }
    }
}

第三种方案:

Code
using System;
using System.Runtime.InteropServices;
using  System.Management;
namespace Hardware
{
 
/// <summary>
 /// Hardware_Mac 的摘要说明。
 
/// </summary>
 public class HardwareInfo
 {
  
//取机器名 
  public string GetHostName()
  {
   
return System.Net.Dns.GetHostName(); 
  }



  
//取CPU编号
  public String GetCpuID() 
  {
   
try
   {
    ManagementClass mc 
= new ManagementClass(Win32_Processor);
    ManagementObjectCollection moc 
= mc.GetInstances();
      
    String strCpuID 
= null ;
    
foreach( ManagementObject mo in moc ) 
    {
     strCpuID 
= mo.Properties[ProcessorId].Value.ToString();
     
break
    }
    
return strCpuID;
   }
   
catch
   {
    
return ;
   }



  }
//end method
 
  
//取第一块硬盘编号
  public String GetHardDiskID() 
  {
   
try
   {
    ManagementObjectSearcher searcher 
= new ManagementObjectSearcher(SELECT * FROM Win32_PhysicalMedia);
    String strHardDiskID 
= null ;
    
foreach(ManagementObject mo in searcher.Get()) 
    {    
     strHardDiskID 
= mo[SerialNumber].ToString().Trim();
     
break;          
    }
    
return strHardDiskID ;
   }
   
catch
   {
    
return ;
   }
  }
//end 



  public enum NCBCONST 
  { 
   NCBNAMSZ   
=16,      /* absolute length of a net name         */ 
   MAX_LANA   
=254,      /* lana's in range 0 to MAX_LANA inclusive   */ 
   NCBENUM      
=0x37,      /* NCB ENUMERATE LANA NUMBERS            */ 
   NRC_GOODRET   
=0x00,      /* good return                              */ 
   NCBRESET    
=0x32,      /* NCB RESET                        */ 
   NCBASTAT    
=0x33,      /* NCB ADAPTER STATUS                  */ 
   NUM_NAMEBUF 
=30,      /* Number of NAME's BUFFER               */ 
  } 



  [StructLayout(LayoutKind.Sequential)] 
   
public struct ADAPTER_STATUS 
  { 
   [MarshalAs(UnmanagedType.ByValArray, SizeConst
=6)] 
   
public byte[] adapter_address; 
   
public byte   rev_major;  
   
public byte   reserved0;  
   
public byte   adapter_type;  
   
public byte   rev_minor;  
   
public ushort    duration;  
   
public ushort    frmr_recv;  
   
public ushort    frmr_xmit;  
   
public ushort    iframe_recv_err;  
   
public ushort    xmit_aborts;  
   
public uint   xmit_success;  
   
public uint   recv_success;  
   
public ushort    iframe_xmit_err;  
   
public ushort    recv_buff_unavail;  
   
public ushort    t1_timeouts;  
   
public ushort    ti_timeouts;  
   
public uint   reserved1;  
   
public ushort    free_ncbs;  
   
public ushort    max_cfg_ncbs;  
   
public ushort    max_ncbs;  
   
public ushort    xmit_buf_unavail;  
   
public ushort    max_dgram_size;  
   
public ushort    pending_sess;  
   
public ushort    max_cfg_sess;  
   
public ushort    max_sess;  
   
public ushort    max_sess_pkt_size;  
   
public ushort    name_count; 
  } 



  [StructLayout(LayoutKind.Sequential)] 
   
public struct NAME_BUFFER 
  {  
   [MarshalAs(UnmanagedType.ByValArray, SizeConst
=(int)NCBCONST.NCBNAMSZ)] 
   
public byte[] name; 
   
public byte name_num;  
   
public byte name_flags;  
  } 



  [StructLayout(LayoutKind.Sequential)] 
   
public struct NCB 
  {  
   
public byte  ncb_command;  
   
public byte  ncb_retcode;  
   
public byte  ncb_lsn;  
   
public byte  ncb_num;  
   
public IntPtr ncb_buffer;  
   
public ushort ncb_length;  
   [MarshalAs(UnmanagedType.ByValArray, SizeConst
=(int)NCBCONST.NCBNAMSZ)] 
   
public byte[]  ncb_callname;  
   [MarshalAs(UnmanagedType.ByValArray, SizeConst
=(int)NCBCONST.NCBNAMSZ)] 
   
public byte[]  ncb_name;  
   
public byte  ncb_rto;  
   
public byte  ncb_sto;  
   
public IntPtr ncb_post;  
   
public byte  ncb_lana_num;  
   
public byte  ncb_cmd_cplt;  
   [MarshalAs(UnmanagedType.ByValArray, SizeConst
=10)] 
   
public byte[] ncb_reserve; 
   
public IntPtr ncb_event; 
  } 



  [StructLayout(LayoutKind.Sequential)] 
   
public struct LANA_ENUM 
  {  
   
public byte length;  
   [MarshalAs(UnmanagedType.ByValArray, SizeConst
=(int)NCBCONST.MAX_LANA)] 
   
public byte[] lana; 
  } 



  [StructLayout(LayoutKind.Auto)] 
   
public struct ASTAT 
  {  
   
public ADAPTER_STATUS adapt; 
   [MarshalAs(UnmanagedType.ByValArray, SizeConst
=(int)NCBCONST.NUM_NAMEBUF)] 
   
public NAME_BUFFER[] NameBuff; 
  } 
  
public class Win32API 
  { 
   [DllImport(NETAPI32.DLL)] 
   
public static extern char Netbios(ref NCB ncb); 
  } 
  
  
public string GetMacAddress() 
  { 
   
string addr=
   
try
   {
    
int cb; 
    ASTAT adapter; 
    NCB Ncb
=new NCB(); 
    
char uRetCode; 
    LANA_ENUM lenum; 



    Ncb.ncb_command 
= (byte)NCBCONST.NCBENUM; 
    cb 
= Marshal.SizeOf(typeof(LANA_ENUM)); 
    Ncb.ncb_buffer 
= Marshal.AllocHGlobal(cb); 
    Ncb.ncb_length 
= (ushort)cb; 
    uRetCode 
= Win32API.Netbios(ref Ncb); 
    lenum 
= (LANA_ENUM)Marshal.PtrToStructure(Ncb.ncb_buffer, typeof(LANA_ENUM)); 
    Marshal.FreeHGlobal(Ncb.ncb_buffer); 
    
if(uRetCode != (short)NCBCONST.NRC_GOODRET) 
     
return ; 



    
for(int i=0; i < lenum.length ;i++
    { 
     Ncb.ncb_command 
= (byte)NCBCONST.NCBRESET; 
     Ncb.ncb_lana_num 
= lenum.lana[i]; 
     uRetCode 
= Win32API.Netbios(ref Ncb); 
     
if(uRetCode != (short)NCBCONST.NRC_GOODRET) 
      
return ; 



     Ncb.ncb_command 
= (byte)NCBCONST.NCBASTAT; 
     Ncb.ncb_lana_num 
= lenum.lana[i]; 
     Ncb.ncb_callname[
0]=(byte)'*'
     cb 
= Marshal.SizeOf(typeof(ADAPTER_STATUS)) + Marshal.SizeOf(typeof(NAME_BUFFER))*(int)NCBCONST.NUM_NAMEBUF; 
     Ncb.ncb_buffer 
= Marshal.AllocHGlobal(cb); 
     Ncb.ncb_length 
= (ushort)cb; 
     uRetCode 
= Win32API.Netbios(ref Ncb); 
     adapter.adapt 
= (ADAPTER_STATUS)Marshal.PtrToStructure(Ncb.ncb_buffer, typeof(ADAPTER_STATUS)); 
     Marshal.FreeHGlobal(Ncb.ncb_buffer); 



     
if (uRetCode == (short)NCBCONST.NRC_GOODRET) 
     { 
      
if(i>0
       addr 
+= :; 
      addr 
= string.Format({0,2:X}{1,2:X}{2,2:X}{3,2:X}{4,2:X}{5,2:X}, 
       adapter.adapt.adapter_address[
0], 
       adapter.adapt.adapter_address[
1], 
       adapter.adapt.adapter_address[
2], 
       adapter.adapt.adapter_address[
3], 
       adapter.adapt.adapter_address[
4], 
       adapter.adapt.adapter_address[
5]); 
     } 
    } 
   }
   
catch
   {}
   
return addr.Replace(' ''0'); 
  } 



 }
}

一般软件的注册机制可以通过获取硬件序列号,然后用非对称加密算法生成相应的公钥私钥。但是用Managed Code写获取硬盘序列号的代码不能解决所有的问题,比如不能在非管理员的权限下使用,前几天Sunmast在他的Blog上发布了《如何得到硬盘序列号?.NET版本[C#]》,就是没有解决这个问题,用WMI也有很多问题。

要想顺利获取硬盘的序列号,目前只能依靠非托管代码了。DiskId32是一个源码公开的C++程序,可以解决上述问题。由于代码比较底层,我对VC和DDK不熟悉,没有能力将其封装为DLL,希望各位帮忙!

还有,就算封装好了这个Native DLL并可以使用了,但还有问题没有解决。如果封装到了Native DLL,该DLL很容易被人替换成另外一个,毕竟在Managed Code里面可以看到调用Native DLL的函数声明,别人只要模仿这些函数界面重新写一个新的就很容易达到破解目的了。不过具体我没有测试过,不知道行不行。

于是我又想到了另外一个方法,就是把获取硬盘序列号的Native DLL作为资源文件封装到Managed Code中,然后在每次要调要该DLL时,先把该DLL写入磁盘,再动态绑定。由于Managed Code可以通过混淆器来保护,以致不能对其进行修改,这个我在《如何保护我们的 .NET 程序集?》中已经给出了答案。动态绑定Native DLL又是另外一个技术难题,我已经找到了一些资料,与大家分享。
Late binding on native DLLs with C#
Late-Binding DLLs in C#
Using legacy plug-ins with .NET - Part 1
Using legacy plug-ins with .NET - Part 2
C-Function pointer for .NET
Dynamic PInvoke method calls

不过最牛的就是下面这一招了!直接把Native Code用字节数组保存在Managed Code中,然后调用,真是牛B,不过我还没有完全弄懂,希望大家来实践实践。
Execute Native Code From .NET

另外还有一篇文章是关于加密字符串的,值得研究!
Poly-Engine Crypt String

希望各位多多交流.NET程序的保护问题,找出最好的解决方案 

    
  
public   class   IDE     
  {     
      [StructLayout(LayoutKind.Sequential,   CharSet
=CharSet.Ansi)]       
      
internal   struct   IDSECTOR     
      {     
          
public   ushort     wGenConfig;     
          
public   ushort     wNumCyls;     
          
public   ushort     wReserved;     
          
public   ushort     wNumHeads;     
          
public   ushort     wBytesPerTrack;     
          
public   ushort     wBytesPerSector;     
          
public   ushort     wSectorsPerTrack;     
          [   MarshalAs(   UnmanagedType.ByValArray,   SizeConst
=3)]       
          
public   ushort   []   wVendorUnique;     
          [   MarshalAs(   UnmanagedType.ByValTStr,   SizeConst
=20)]       
          
public   string     sSerialNumber;     
          
public   ushort     wBufferType;     
          
public   ushort     wBufferSize;     
          
public   ushort     wECCSize;     
          [   MarshalAs(   UnmanagedType.ByValTStr,   SizeConst
=8)]       
          
public   string     sFirmwareRev;     
          [   MarshalAs(   UnmanagedType.ByValTStr,   SizeConst
=40)]       
          
public   string     sModelNumber;     
          
public   ushort     wMoreVendorUnique;     
          
public   ushort     wDoubleWordIO;     
          
public   ushort     wCapabilities;     
          
public   ushort     wReserved1;     
          
public   ushort     wPIOTiming;     
          
public   ushort     wDMATiming;     
          
public   ushort     wBS;     
          
public   ushort     wNumCurrentCyls;     
          
public   ushort     wNumCurrentHeads;     
          
public   ushort     wNumCurrentSectorsPerTrack;     
          
public   uint       ulCurrentSectorCapacity;     
          
public   ushort     wMultSectorStuff;     
          
public   uint       ulTotalAddressableSectors;     
          
public   ushort     wSingleWordDMA;     
          
public   ushort     wMultiWordDMA;     
          [   MarshalAs(   UnmanagedType.ByValArray,   SizeConst
=128   )]       
          
public   byte   []   bReserved;     
  }     
    
      [StructLayout(LayoutKind.Sequential)]       
      
internal   struct   DRIVERSTATUS     
      {     
          
public   byte     bDriverError;     
          
public   byte     bIDEStatus;     
          [   MarshalAs(   UnmanagedType.ByValArray,   SizeConst
=2   )]       
          
public   byte   []   bReserved;     
          [   MarshalAs(   UnmanagedType.ByValArray,   SizeConst
=2   )]       
          
public   uint   []   dwReserved;     
      }     
    
      [StructLayout(LayoutKind.Sequential)]       
      
internal   struct   SENDCMDOUTPARAMS     
      {     
          
public   uint   cBufferSize;     
          
public   DRIVERSTATUS     DriverStatus;     
          [   MarshalAs(   UnmanagedType.ByValArray,   SizeConst
=513   )]       
          
public   byte   []   bBuffer;     
      }     
    
      [StructLayout(LayoutKind.Sequential,   CharSet
=CharSet.Ansi)]       
      
internal   struct   SRB_IO_CONTROL     
      {     
          
public   uint   HeaderLength;     
          [   MarshalAs(   UnmanagedType.ByValTStr,   SizeConst
=8   )]       
          
public   string   Signature;     
          
public   uint   Timeout;     
          
public   uint   ControlCode;     
          
public   uint   ReturnCode;     
          
public   uint   Length;     
      }     
                  
      [StructLayout(LayoutKind.Sequential)]       
      
internal   struct   IDEREGS     
      {     
          
public   byte   bFeaturesReg;     
          
public   byte   bSectorCountReg;     
          
public   byte   bSectorNumberReg;     
          
public   byte   bCylLowReg;     
          
public   byte   bCylHighReg;     
          
public   byte   bDriveHeadReg;     
          
public   byte   bCommandReg;     
          
public   byte   bReserved;     
      }     
                  
      [StructLayout(LayoutKind.Sequential)]       
      
internal   struct   SENDCMDINPARAMS     
      {     
          
public   uint           cBufferSize;     
          
public   IDEREGS       irDriveRegs;     
          
public   byte   bDriveNumber;     
          [   MarshalAs(   UnmanagedType.ByValArray,   SizeConst
=3   )]       
          
public   byte   []   bReserved;     
          [   MarshalAs(   UnmanagedType.ByValArray,   SizeConst
=4   )]       
          
public   uint   []   dwReserved;     
          
public   byte             bBuffer;     
  }     
    
      [StructLayout(LayoutKind.Sequential)]       
      
internal   struct   GETVERSIONOUTPARAMS     
      {     
          
public   byte   bVersion;     
          
public   byte   bRevision;     
          
public   byte   bReserved;     
          
public   byte   bIDEDeviceMap;     
          
public   uint   fCapabilities;     
          [   MarshalAs(   UnmanagedType.ByValArray,   SizeConst
=4   )]       
          
public   uint   []   dwReserved;   //   For   future   use.     
      }     
    
      [DllImport(
"kernel32.dll")]     
      
private   static   extern   int   CloseHandle(uint   hObject);     
    
      [DllImport(
"kernel32.dll")]     
      
private   static   extern   int   DeviceIoControl(uint   hDevice,     
        
uint   dwIoControlCode,     
        
ref   SENDCMDINPARAMS   lpInBuffer,     
        
int   nInBufferSize,     
        
ref   SENDCMDOUTPARAMS   lpOutBuffer,     
        
int   nOutBufferSize,     
        
ref   uint   lpbytesReturned,     
        
int   lpOverlapped);     
    
      [DllImport(
"kernel32.dll")]     
      
private   static   extern   int   DeviceIoControl(uint   hDevice,     
        
uint   dwIoControlCode,     
        
int   lpInBuffer,     
        
int   nInBufferSize,     
        
ref   GETVERSIONOUTPARAMS   lpOutBuffer,     
        
int   nOutBufferSize,     
        
ref   uint   lpbytesReturned,     
        
int   lpOverlapped);     
    
      [DllImport(
"kernel32.dll")]     
      
private   static   extern   uint   CreateFile(string   lpFileName,     
        
uint   dwDesiredAccess,     
        
uint   dwShareMode,     
        
int   lpSecurityAttributes,     
        
uint   dwCreationDisposition,     
        
uint   dwFlagsAndAttributes,     
        
int   hTemplateFile);     
    
      
private   const   uint   GENERIC_READ   =   0x80000000;     
      
private   const   uint   GENERIC_WRITE   =   0x40000000;     
      
private   const   uint   FILE_SHARE_READ   =   0x00000001;     
      
private   const   uint   FILE_SHARE_WRITE   =   0x00000002;     
      
private   const   uint   OPEN_EXISTING   =   3;     
      
private   const   uint   INVALID_HANDLE_VALUE   =   0xffffffff;     
      
private   const   uint   DFP_GET_VERSION   =   0x00074080;     
      
private   const   int   IDE_ATAPI_IDENTIFY   =   0xA1;     //     Returns   ID   sector   for   ATAPI.     
      private   const   int   IDE_ATA_IDENTIFY   =   0xEC;     //     Returns   ID   sector   for   ATA.     
      private   const   int   IDENTIFY_BUFFER_SIZE   =   512;     
      
private   const   uint   DFP_RECEIVE_DRIVE_DATA   =   0x0007c088;     
    
      
public   static   string   Read(byte   drive)     
      {     
            OperatingSystem   os   
=   Environment.OSVersion;     
            
if   (os.Platform   !=   PlatformID.Win32NT)   throw   new   NotSupportedException("仅支持WindowsNT/2000/XP");     
            
//我没有NT4,请哪位大大测试一下NT4下能不能用     
            
//if   (os.Version.Major   <   5)   throw   new   NotSupportedException("仅支持WindowsNT/2000/XP");     
    
          
string   driveName   =   "\\\\.\\PhysicalDrive"   +   drive.ToString();     
          
uint   device   =   CreateFile(driveName,     
        GENERIC_READ   
|   GENERIC_WRITE,       
        FILE_SHARE_READ   
|   FILE_SHARE_WRITE,     
        
0,   OPEN_EXISTING,   0,   0);     
          
if   (device   ==   INVALID_HANDLE_VALUE)   return   "";     
          GETVERSIONOUTPARAMS   verPara   
=   new   GETVERSIONOUTPARAMS();     
          
uint   bytRv   =   0;     
    
          
if   (0   !=   DeviceIoControl(device,   DFP_GET_VERSION,     
        
0,   0,   ref   verPara,   Marshal.SizeOf(verPara),     
        
ref   bytRv,   0))     
          {     
                
if   (verPara.bIDEDeviceMap   >   0)     
                {     
        
byte   bIDCmd   =   (byte)(((verPara.bIDEDeviceMap   >>   drive   &   0x10)   !=   0)   ?       IDE_ATAPI_IDENTIFY   :   IDE_ATA_IDENTIFY);     
        SENDCMDINPARAMS   scip   
=   new   SENDCMDINPARAMS();     
        SENDCMDOUTPARAMS   scop   
=   new   SENDCMDOUTPARAMS();     
    
        scip.cBufferSize   
=   IDENTIFY_BUFFER_SIZE;     
        scip.irDriveRegs.bFeaturesReg   
=   0;     
        scip.irDriveRegs.bSectorCountReg   
=   1;     
        scip.irDriveRegs.bCylLowReg   
=   0;     
        scip.irDriveRegs.bCylHighReg   
=   0;     
        scip.irDriveRegs.bDriveHeadReg   
=   (byte)(0xA0   |   ((drive   &   1)   <<   4));     
        scip.irDriveRegs.bCommandReg   
=   bIDCmd;     
        scip.bDriveNumber   
=   drive;     
    
        
if   (0   !=   DeviceIoControl(device,   DFP_RECEIVE_DRIVE_DATA,     
              
ref   scip,   Marshal.SizeOf(scip),   ref   scop,     
              Marshal.SizeOf(scop),   
ref   bytRv,   0))     
        {     
            StringBuilder   s   
=   new   StringBuilder();     
            
for   (int   i   =   20;   i   <   40;   i   +=   2)     
            {     
                s.Append((
char)(scop.bBuffer[i+1]));     
                s.Append((
char)scop.bBuffer[i]);     
            }     
            CloseHandle(device);     
            
return   s.ToString().Trim();     
        }     
                  }     
            }     
            CloseHandle(device);     
            
return   "";     
      }     
  }