如何获取机器码?

时间:2020-12-07 17:10:42
如何获取电脑的机器码呀?

怎样获取网卡的物理地址?

6 个解决方案

#1


function LanCardID: string;//获取网卡物理地址
var guid: TGUID;
    i: integer;
begin
   result := '';
   CoCreateGUID(guid);
   for i := Low(guid.D4)+2 to High(guid.D4) do
   begin
      result := result + IntToHex(guid.D4[i],2);
   end;
end;

#2


学习!

#3


*      这个模块是用来获取CPU、硬盘序列号,CPU的*
*                                              *
*   速率、显示器的刷新率网卡的MAC地址等信息    *

Unit HardInfo;

interface

uses 
   Windows,SysUtils,Nb30;

const
   ID_BIT = $200000; // EFLAGS ID bit

type 
   TCPUID = array[1..4] of Longint;
   TVendor = array [0..11] of char;
   
   function IsCPUID_Available : Boolean; register;       //判断CPU序列号是否可用函数
   function GetCPUID: TCPUID; assembler; register;       //获取CPU序列号函数
   function GetCPUVendor: TVendor; assembler; register;  //获取CPU生产厂家函数
   function GetCPUInfo: string;                          //CPU序列号(格式化成字符串)
   function GetCPUSpeed: Double;                         //获取CPU速度函数
   function GetDisplayFrequency: Integer;                //获取显示器刷新率
   function GetIdeSerialNumber: pchar;                   //获取IDE硬盘序列号函数
   function MonthMaxDay(year,month:integer):Integer;     //获取某年某月的最大天数
   function GetAdapterMac(ANo:Integer):String;

implementation 

  function IsCPUID_Available : Boolean; register;
   asm
    PUSHFD {direct access to flags no possible, only via stack}
    POP EAX {flags to EAX}
    MOV EDX,EAX {save current flags}
    XOR EAX,ID_BIT {not ID bit}
    PUSH EAX {onto stack}
    POPFD {from stack to flags, with not ID bit}
    PUSHFD {back to stack}
    POP EAX {get back to EAX}
    XOR EAX,EDX {check if ID bit affected}
    JZ @exit {no, CPUID not availavle}
    MOV AL,True {Result=True}
    @exit:
  end;



  function GetCPUID: TCPUID; assembler; register;
    asm
    PUSH    EBX         {Save affected register}
    PUSH    EDI
    MOV     EDI,EAX     {@Resukt}
    MOV     EAX,1
    DW      $A20F       {CPUID Command}
    STOSD                {CPUID[1]}
    MOV     EAX,EBX
    STOSD               {CPUID[2]}
    MOV     EAX,ECX
    STOSD               {CPUID[3]}
    MOV     EAX,EDX
    STOSD               {CPUID[4]}
    POP     EDI         {Restore registers}
    POP     EBX
    end; 

  function GetCPUVendor : TVendor; assembler; register;
  //获取CPU生产厂家函数
  //调用方法:EDIT.TEXT:='Current CPU Vendor:'+GetCPUVendor;
    asm
      PUSH EBX {Save affected register}
      PUSH EDI
      MOV EDI,EAX {@Result (TVendor)}
      MOV EAX,0
      DW $A20F {CPUID Command}
      MOV EAX,EBX
      XCHG EBX,ECX {save ECX result}
      MOV ECX,4
      @1:
      STOSB
      SHR EAX,8
      LOOP @1
      MOV EAX,EDX
      MOV ECX,4
      @2:
      STOSB
      SHR EAX,8
      LOOP @2
      MOV EAX,EBX
      MOV ECX,4
      @3:
      STOSB
      SHR EAX,8
      LOOP @3
      POP EDI {Restore registers}
      POP EBX
    end;

  function GetCPUInfo: string;
  var
    CPUID: TCPUID;
        I: Integer;
        S: TVendor;
  begin
    for I:=Low(CPUID) to High(CPUID) do CPUID[I]:=-1;
    if IsCPUID_Available then
      begin
         CPUID:= GetCPUID;
         S:=GetCPUVendor;
         Result:= IntToHex(CPUID[1], 8)
                 +'-'+ IntToHex(CPUID[2], 8)
                 +'-'+ IntToHex(CPUID[3], 8)
                 +'-'+ IntToHex(CPUID[4], 8);
      end
    else Result:='CPUID not available';
  end;

  
 function GetCPUSpeed: Double;
 //获取CPU速率函数
 //调用方法:EDIT.TEXT:='Current CPU Speed:'+floattostr(GetCPUSpeed)+'MHz';
 const
  DelayTime = 500; // 时间单位是毫秒
 var
  TimerHi, TimerLo: DWORD;
  PriorityClass, Priority: Integer;
 begin
     PriorityClass := GetPriorityClass(GetCurrentProcess);
     Priority := GetThreadPriority(GetCurrentThread);
     SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);
     SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
     Sleep(10);
     asm
        dw 310Fh // rdtsc
        mov TimerLo, eax
        mov TimerHi, edx
     end;
     Sleep(DelayTime);
     asm
        dw 310Fh // rdtsc 
        sub eax, TimerLo 
        sbb edx, TimerHi
        mov TimerLo, eax
        mov TimerHi, edx
     end;

     SetThreadPriority(GetCurrentThread, Priority);
     SetPriorityClass(GetCurrentProcess, PriorityClass);
     Result := TimerLo / (1000.0 * DelayTime);
 end;

 function GetDisplayFrequency: Integer;
 // 这个函数返回的显示刷新率是以Hz为单位的
 //调用方法:EDIT.TEXT:='Current DisplayFrequency:'+inttostr(GetDisplayFrequency)+' Hz';
 var
    DeviceMode: TDeviceMode;
 begin
   EnumDisplaySettings(nil, Cardinal(-1), DeviceMode);
   Result := DeviceMode.dmDisplayFrequency;
 end;

#4



  function GetIdeSerialNumber : pchar;
  //获取第一个IDE硬盘的序列号
  //调用方法:EDIT.TEXT:='HardDriver SerialNumber:'+strpas(GetIdeSerialNumber);
  const IDENTIFY_BUFFER_SIZE = 512;
  type
   TIDERegs = packed record
    bFeaturesReg     : BYTE; // Used for specifying SMART "commands".
    bSectorCountReg  : BYTE; // IDE sector count register
    bSectorNumberReg : BYTE; // IDE sector number register
    bCylLowReg       : BYTE; // IDE low order cylinder value
    bCylHighReg      : BYTE; // IDE high order cylinder value
    bDriveHeadReg    : BYTE; // IDE drive/head register
    bCommandReg      : BYTE; // Actual IDE command.
    bReserved        : BYTE; // reserved for future use.  Must be zero.
  end;
  TSendCmdInParams = packed record
    // Buffer size in bytes
    cBufferSize  : DWORD;
    // Structure with drive register values.
    irDriveRegs  : TIDERegs;
    // Physical drive number to send command to (0,1,2,3).
    bDriveNumber : BYTE;
    bReserved    : Array[0..2] of Byte;
    dwReserved   : Array[0..3] of DWORD;
    bBuffer      : Array[0..0] of Byte;  // Input buffer.
  end;
  TIdSector = packed record
    wGenConfig                 : Word;
    wNumCyls                   : Word;
    wReserved                  : Word;
    wNumHeads                  : Word;
    wBytesPerTrack             : Word;
    wBytesPerSector            : Word;
    wSectorsPerTrack           : Word;
    wVendorUnique              : Array[0..2] of Word;
    sSerialNumber              : Array[0..19] of CHAR;
    wBufferType                : Word;
    wBufferSize                : Word;
    wECCSize                   : Word;
    sFirmwareRev               : Array[0..7] of Char;
    sModelNumber               : Array[0..39] of Char;
    wMoreVendorUnique          : Word;
    wDoubleWordIO              : Word;
    wCapabilities              : Word;
    wReserved1                 : Word;
    wPIOTiming                 : Word;
    wDMATiming                 : Word;
    wBS                        : Word;
    wNumCurrentCyls            : Word;
    wNumCurrentHeads           : Word;
    wNumCurrentSectorsPerTrack : Word;
    ulCurrentSectorCapacity    : DWORD;
    wMultSectorStuff           : Word;
    ulTotalAddressableSectors  : DWORD;
    wSingleWordDMA             : Word;
    wMultiWordDMA              : Word;
    bReserved                  : Array[0..127] of BYTE;
  end;
  PIdSector = ^TIdSector;
  TDriverStatus = packed record
    // 驱动器返回的错误代码,无错则返回0
    bDriverError : Byte;
    // IDE出错寄存器的内容,只有当bDriverError 为 SMART_IDE_ERROR 时有效
    bIDEStatus   : Byte;
    bReserved    : Array[0..1] of Byte;
    dwReserved   : Array[0..1] of DWORD;
  end;
  TSendCmdOutParams = packed record
    // bBuffer的大小
    cBufferSize  : DWORD;
    // 驱动器状态
    DriverStatus : TDriverStatus;
    // 用于保存从驱动器读出的数据的缓冲区,实际长度由cBufferSize决定
    bBuffer      : Array[0..0] of BYTE;
  end;
  var hDevice : THandle;
      cbBytesReturned : DWORD;
      SCIP : TSendCmdInParams;
      aIdOutCmd : Array [0..(SizeOf(TSendCmdOutParams)+IDENTIFY_BUFFER_SIZE-1)-1] of Byte;
      IdOutCmd  : TSendCmdOutParams absolute aIdOutCmd;
  procedure ChangeByteOrder( var Data; Size : Integer );
  var ptr : PChar;
      i : Integer;
      c : Char;
  begin
    ptr := @Data;
    for i := 0 to (Size shr 1)-1 do begin
      c := ptr^;
      ptr^ := (ptr+1)^;
      (ptr+1)^ := c;
      Inc(ptr,2);
    end;
 end;
 begin
    Result := ''; // 如果出错则返回空串
    if SysUtils.Win32Platform=VER_PLATFORM_WIN32_NT then begin// Windows NT, Windows 2000
        // 提示! 改变名称可适用于其它驱动器,如第二个驱动器: '\\.\PhysicalDrive1\'
        hDevice := CreateFile( '\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
          FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );
    end else // Version Windows 95 OSR2, Windows 98
      hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 );
      if hDevice=INVALID_HANDLE_VALUE then Exit;
     try
      FillChar(SCIP,SizeOf(TSendCmdInParams)-1,#0);
      FillChar(aIdOutCmd,SizeOf(aIdOutCmd),#0);
      cbBytesReturned := 0;
      // Set up data structures for IDENTIFY command.
      with SCIP do begin
        cBufferSize  := IDENTIFY_BUFFER_SIZE;
  //      bDriveNumber := 0;
        with irDriveRegs do begin
          bSectorCountReg  := 1;
          bSectorNumberReg := 1;
  //      if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0
  //      else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4);
          bDriveHeadReg    := $A0;
          bCommandReg      := $EC;
        end;
      end;
      if not DeviceIoControl( hDevice, $0007c088, @SCIP, SizeOf(TSendCmdInParams)-1,
        @aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil ) then Exit;
    finally
      CloseHandle(hDevice);
    end;
    with PIdSector(@IdOutCmd.bBuffer)^ do begin
      ChangeByteOrder( sSerialNumber, SizeOf(sSerialNumber) );
      (PChar(@sSerialNumber)+SizeOf(sSerialNumber))^ := #0;
      Result := PChar(@sSerialNumber);
    end;
    // 更多关于 S.M.A.R.T. ioctl 的信息可查看:
    // http://www.microsoft.com/hwdev/download/respec/iocltapi.rtf
    // MSDN库中也有一些简单的例子
    // Windows Development -> Win32 Device Driver Kit ->
    // SAMPLE: SmartApp.exe Accesses SMART stats in IDE drives
    // 还可以查看 http://www.mtgroup.ru/~alexk
    // IdeInfo.zip - 一个简单的使用了S.M.A.R.T. Ioctl API的Delphi应用程序
    // 注意:
    // WinNT/Win2000 - 你必须拥有对硬盘的读/写访问权限
    // Win98
    // SMARTVSD.VXD 必须安装到 \windows\system\iosubsys
    // (不要忘记在复制后重新启动系统)
  end;

  function MonthMaxDay(Year,Month:Integer) : Integer ;    //获取某年某月最大天数
  begin
    Case Month of
       1,3,5,7,8,10,12:  Result:=31;  //如是1、3、5、7、8、10、12则最大为31天
       2: if (Year mod 4=0) and (Year mod 100<>0) or (Year mod 400=0) then Result:=29
          else Result:=28;    //如是闰年2月则29天,否则2月最大为28天
       else Result:=30;       //其它的4、6、9、11则最大天数为30天
    end;
  end;

  
  function GetAdapterMac(ANo:Integer):String;
  //获取网卡的MAC地址
  var
     Ncb:TNcb;
     Adapter:TAdapterStatus;
     Lanaenum:TLanaenum;
     IntIdx:Integer; //
     cRc:Char;
     StrTemp:String;
  begin
    Result:='';
    Try
       ZeroMemory(@Ncb,SizeOf(Ncb));
       Ncb.ncb_command:=Chr(NCbenum);
       NetBios(@NCb);
       Ncb.ncb_buffer:=@Lanaenum; //再处理enum命令
       Ncb.ncb_length:=SizeOf(Lanaenum);
       cRc:=NetBios(@Ncb);
       if Ord(cRc)<>0 then exit;
       ZeroMemory(@Ncb,SizeOf(Ncb)); //适配器清零
       Ncb.ncb_command:=Chr(NcbReset);
       Ncb.ncb_lana_num:=Lanaenum.lana[aNo];
       cRc:=NetBios(@Ncb);
       if Ord(cRc)<>0 then exit;
       //得到适配器状态
       ZeroMemory(@Ncb,SizeOf(Ncb));
       Ncb.ncb_command:=Chr(NcbAstat);
       Ncb.ncb_lana_num:=Lanaenum.lana[aNo];
       StrPcopy(Ncb.ncb_callname,'*');
       Ncb.ncb_buffer:=@Adapter;
       Ncb.ncb_length:=SizeOf(Adapter);
       NetBios(@Ncb);
       //将mac地址转换成字符串输出
       StrTemp:='';
       For IntIdx:=0 to 5 do
       StrTemp:=StrTemp+IntToHex(Integer(Adapter.adapter_address[intIdx]),2);
       Result:=StrTemp;
    finally
    end;
end;

end.

#5


谢谢

#6


楼主有没有c#版的,谢谢。

#1


function LanCardID: string;//获取网卡物理地址
var guid: TGUID;
    i: integer;
begin
   result := '';
   CoCreateGUID(guid);
   for i := Low(guid.D4)+2 to High(guid.D4) do
   begin
      result := result + IntToHex(guid.D4[i],2);
   end;
end;

#2


学习!

#3


*      这个模块是用来获取CPU、硬盘序列号,CPU的*
*                                              *
*   速率、显示器的刷新率网卡的MAC地址等信息    *

Unit HardInfo;

interface

uses 
   Windows,SysUtils,Nb30;

const
   ID_BIT = $200000; // EFLAGS ID bit

type 
   TCPUID = array[1..4] of Longint;
   TVendor = array [0..11] of char;
   
   function IsCPUID_Available : Boolean; register;       //判断CPU序列号是否可用函数
   function GetCPUID: TCPUID; assembler; register;       //获取CPU序列号函数
   function GetCPUVendor: TVendor; assembler; register;  //获取CPU生产厂家函数
   function GetCPUInfo: string;                          //CPU序列号(格式化成字符串)
   function GetCPUSpeed: Double;                         //获取CPU速度函数
   function GetDisplayFrequency: Integer;                //获取显示器刷新率
   function GetIdeSerialNumber: pchar;                   //获取IDE硬盘序列号函数
   function MonthMaxDay(year,month:integer):Integer;     //获取某年某月的最大天数
   function GetAdapterMac(ANo:Integer):String;

implementation 

  function IsCPUID_Available : Boolean; register;
   asm
    PUSHFD {direct access to flags no possible, only via stack}
    POP EAX {flags to EAX}
    MOV EDX,EAX {save current flags}
    XOR EAX,ID_BIT {not ID bit}
    PUSH EAX {onto stack}
    POPFD {from stack to flags, with not ID bit}
    PUSHFD {back to stack}
    POP EAX {get back to EAX}
    XOR EAX,EDX {check if ID bit affected}
    JZ @exit {no, CPUID not availavle}
    MOV AL,True {Result=True}
    @exit:
  end;



  function GetCPUID: TCPUID; assembler; register;
    asm
    PUSH    EBX         {Save affected register}
    PUSH    EDI
    MOV     EDI,EAX     {@Resukt}
    MOV     EAX,1
    DW      $A20F       {CPUID Command}
    STOSD                {CPUID[1]}
    MOV     EAX,EBX
    STOSD               {CPUID[2]}
    MOV     EAX,ECX
    STOSD               {CPUID[3]}
    MOV     EAX,EDX
    STOSD               {CPUID[4]}
    POP     EDI         {Restore registers}
    POP     EBX
    end; 

  function GetCPUVendor : TVendor; assembler; register;
  //获取CPU生产厂家函数
  //调用方法:EDIT.TEXT:='Current CPU Vendor:'+GetCPUVendor;
    asm
      PUSH EBX {Save affected register}
      PUSH EDI
      MOV EDI,EAX {@Result (TVendor)}
      MOV EAX,0
      DW $A20F {CPUID Command}
      MOV EAX,EBX
      XCHG EBX,ECX {save ECX result}
      MOV ECX,4
      @1:
      STOSB
      SHR EAX,8
      LOOP @1
      MOV EAX,EDX
      MOV ECX,4
      @2:
      STOSB
      SHR EAX,8
      LOOP @2
      MOV EAX,EBX
      MOV ECX,4
      @3:
      STOSB
      SHR EAX,8
      LOOP @3
      POP EDI {Restore registers}
      POP EBX
    end;

  function GetCPUInfo: string;
  var
    CPUID: TCPUID;
        I: Integer;
        S: TVendor;
  begin
    for I:=Low(CPUID) to High(CPUID) do CPUID[I]:=-1;
    if IsCPUID_Available then
      begin
         CPUID:= GetCPUID;
         S:=GetCPUVendor;
         Result:= IntToHex(CPUID[1], 8)
                 +'-'+ IntToHex(CPUID[2], 8)
                 +'-'+ IntToHex(CPUID[3], 8)
                 +'-'+ IntToHex(CPUID[4], 8);
      end
    else Result:='CPUID not available';
  end;

  
 function GetCPUSpeed: Double;
 //获取CPU速率函数
 //调用方法:EDIT.TEXT:='Current CPU Speed:'+floattostr(GetCPUSpeed)+'MHz';
 const
  DelayTime = 500; // 时间单位是毫秒
 var
  TimerHi, TimerLo: DWORD;
  PriorityClass, Priority: Integer;
 begin
     PriorityClass := GetPriorityClass(GetCurrentProcess);
     Priority := GetThreadPriority(GetCurrentThread);
     SetPriorityClass(GetCurrentProcess, REALTIME_PRIORITY_CLASS);
     SetThreadPriority(GetCurrentThread, THREAD_PRIORITY_TIME_CRITICAL);
     Sleep(10);
     asm
        dw 310Fh // rdtsc
        mov TimerLo, eax
        mov TimerHi, edx
     end;
     Sleep(DelayTime);
     asm
        dw 310Fh // rdtsc 
        sub eax, TimerLo 
        sbb edx, TimerHi
        mov TimerLo, eax
        mov TimerHi, edx
     end;

     SetThreadPriority(GetCurrentThread, Priority);
     SetPriorityClass(GetCurrentProcess, PriorityClass);
     Result := TimerLo / (1000.0 * DelayTime);
 end;

 function GetDisplayFrequency: Integer;
 // 这个函数返回的显示刷新率是以Hz为单位的
 //调用方法:EDIT.TEXT:='Current DisplayFrequency:'+inttostr(GetDisplayFrequency)+' Hz';
 var
    DeviceMode: TDeviceMode;
 begin
   EnumDisplaySettings(nil, Cardinal(-1), DeviceMode);
   Result := DeviceMode.dmDisplayFrequency;
 end;

#4



  function GetIdeSerialNumber : pchar;
  //获取第一个IDE硬盘的序列号
  //调用方法:EDIT.TEXT:='HardDriver SerialNumber:'+strpas(GetIdeSerialNumber);
  const IDENTIFY_BUFFER_SIZE = 512;
  type
   TIDERegs = packed record
    bFeaturesReg     : BYTE; // Used for specifying SMART "commands".
    bSectorCountReg  : BYTE; // IDE sector count register
    bSectorNumberReg : BYTE; // IDE sector number register
    bCylLowReg       : BYTE; // IDE low order cylinder value
    bCylHighReg      : BYTE; // IDE high order cylinder value
    bDriveHeadReg    : BYTE; // IDE drive/head register
    bCommandReg      : BYTE; // Actual IDE command.
    bReserved        : BYTE; // reserved for future use.  Must be zero.
  end;
  TSendCmdInParams = packed record
    // Buffer size in bytes
    cBufferSize  : DWORD;
    // Structure with drive register values.
    irDriveRegs  : TIDERegs;
    // Physical drive number to send command to (0,1,2,3).
    bDriveNumber : BYTE;
    bReserved    : Array[0..2] of Byte;
    dwReserved   : Array[0..3] of DWORD;
    bBuffer      : Array[0..0] of Byte;  // Input buffer.
  end;
  TIdSector = packed record
    wGenConfig                 : Word;
    wNumCyls                   : Word;
    wReserved                  : Word;
    wNumHeads                  : Word;
    wBytesPerTrack             : Word;
    wBytesPerSector            : Word;
    wSectorsPerTrack           : Word;
    wVendorUnique              : Array[0..2] of Word;
    sSerialNumber              : Array[0..19] of CHAR;
    wBufferType                : Word;
    wBufferSize                : Word;
    wECCSize                   : Word;
    sFirmwareRev               : Array[0..7] of Char;
    sModelNumber               : Array[0..39] of Char;
    wMoreVendorUnique          : Word;
    wDoubleWordIO              : Word;
    wCapabilities              : Word;
    wReserved1                 : Word;
    wPIOTiming                 : Word;
    wDMATiming                 : Word;
    wBS                        : Word;
    wNumCurrentCyls            : Word;
    wNumCurrentHeads           : Word;
    wNumCurrentSectorsPerTrack : Word;
    ulCurrentSectorCapacity    : DWORD;
    wMultSectorStuff           : Word;
    ulTotalAddressableSectors  : DWORD;
    wSingleWordDMA             : Word;
    wMultiWordDMA              : Word;
    bReserved                  : Array[0..127] of BYTE;
  end;
  PIdSector = ^TIdSector;
  TDriverStatus = packed record
    // 驱动器返回的错误代码,无错则返回0
    bDriverError : Byte;
    // IDE出错寄存器的内容,只有当bDriverError 为 SMART_IDE_ERROR 时有效
    bIDEStatus   : Byte;
    bReserved    : Array[0..1] of Byte;
    dwReserved   : Array[0..1] of DWORD;
  end;
  TSendCmdOutParams = packed record
    // bBuffer的大小
    cBufferSize  : DWORD;
    // 驱动器状态
    DriverStatus : TDriverStatus;
    // 用于保存从驱动器读出的数据的缓冲区,实际长度由cBufferSize决定
    bBuffer      : Array[0..0] of BYTE;
  end;
  var hDevice : THandle;
      cbBytesReturned : DWORD;
      SCIP : TSendCmdInParams;
      aIdOutCmd : Array [0..(SizeOf(TSendCmdOutParams)+IDENTIFY_BUFFER_SIZE-1)-1] of Byte;
      IdOutCmd  : TSendCmdOutParams absolute aIdOutCmd;
  procedure ChangeByteOrder( var Data; Size : Integer );
  var ptr : PChar;
      i : Integer;
      c : Char;
  begin
    ptr := @Data;
    for i := 0 to (Size shr 1)-1 do begin
      c := ptr^;
      ptr^ := (ptr+1)^;
      (ptr+1)^ := c;
      Inc(ptr,2);
    end;
 end;
 begin
    Result := ''; // 如果出错则返回空串
    if SysUtils.Win32Platform=VER_PLATFORM_WIN32_NT then begin// Windows NT, Windows 2000
        // 提示! 改变名称可适用于其它驱动器,如第二个驱动器: '\\.\PhysicalDrive1\'
        hDevice := CreateFile( '\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
          FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );
    end else // Version Windows 95 OSR2, Windows 98
      hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 );
      if hDevice=INVALID_HANDLE_VALUE then Exit;
     try
      FillChar(SCIP,SizeOf(TSendCmdInParams)-1,#0);
      FillChar(aIdOutCmd,SizeOf(aIdOutCmd),#0);
      cbBytesReturned := 0;
      // Set up data structures for IDENTIFY command.
      with SCIP do begin
        cBufferSize  := IDENTIFY_BUFFER_SIZE;
  //      bDriveNumber := 0;
        with irDriveRegs do begin
          bSectorCountReg  := 1;
          bSectorNumberReg := 1;
  //      if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0
  //      else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4);
          bDriveHeadReg    := $A0;
          bCommandReg      := $EC;
        end;
      end;
      if not DeviceIoControl( hDevice, $0007c088, @SCIP, SizeOf(TSendCmdInParams)-1,
        @aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil ) then Exit;
    finally
      CloseHandle(hDevice);
    end;
    with PIdSector(@IdOutCmd.bBuffer)^ do begin
      ChangeByteOrder( sSerialNumber, SizeOf(sSerialNumber) );
      (PChar(@sSerialNumber)+SizeOf(sSerialNumber))^ := #0;
      Result := PChar(@sSerialNumber);
    end;
    // 更多关于 S.M.A.R.T. ioctl 的信息可查看:
    // http://www.microsoft.com/hwdev/download/respec/iocltapi.rtf
    // MSDN库中也有一些简单的例子
    // Windows Development -> Win32 Device Driver Kit ->
    // SAMPLE: SmartApp.exe Accesses SMART stats in IDE drives
    // 还可以查看 http://www.mtgroup.ru/~alexk
    // IdeInfo.zip - 一个简单的使用了S.M.A.R.T. Ioctl API的Delphi应用程序
    // 注意:
    // WinNT/Win2000 - 你必须拥有对硬盘的读/写访问权限
    // Win98
    // SMARTVSD.VXD 必须安装到 \windows\system\iosubsys
    // (不要忘记在复制后重新启动系统)
  end;

  function MonthMaxDay(Year,Month:Integer) : Integer ;    //获取某年某月最大天数
  begin
    Case Month of
       1,3,5,7,8,10,12:  Result:=31;  //如是1、3、5、7、8、10、12则最大为31天
       2: if (Year mod 4=0) and (Year mod 100<>0) or (Year mod 400=0) then Result:=29
          else Result:=28;    //如是闰年2月则29天,否则2月最大为28天
       else Result:=30;       //其它的4、6、9、11则最大天数为30天
    end;
  end;

  
  function GetAdapterMac(ANo:Integer):String;
  //获取网卡的MAC地址
  var
     Ncb:TNcb;
     Adapter:TAdapterStatus;
     Lanaenum:TLanaenum;
     IntIdx:Integer; //
     cRc:Char;
     StrTemp:String;
  begin
    Result:='';
    Try
       ZeroMemory(@Ncb,SizeOf(Ncb));
       Ncb.ncb_command:=Chr(NCbenum);
       NetBios(@NCb);
       Ncb.ncb_buffer:=@Lanaenum; //再处理enum命令
       Ncb.ncb_length:=SizeOf(Lanaenum);
       cRc:=NetBios(@Ncb);
       if Ord(cRc)<>0 then exit;
       ZeroMemory(@Ncb,SizeOf(Ncb)); //适配器清零
       Ncb.ncb_command:=Chr(NcbReset);
       Ncb.ncb_lana_num:=Lanaenum.lana[aNo];
       cRc:=NetBios(@Ncb);
       if Ord(cRc)<>0 then exit;
       //得到适配器状态
       ZeroMemory(@Ncb,SizeOf(Ncb));
       Ncb.ncb_command:=Chr(NcbAstat);
       Ncb.ncb_lana_num:=Lanaenum.lana[aNo];
       StrPcopy(Ncb.ncb_callname,'*');
       Ncb.ncb_buffer:=@Adapter;
       Ncb.ncb_length:=SizeOf(Adapter);
       NetBios(@Ncb);
       //将mac地址转换成字符串输出
       StrTemp:='';
       For IntIdx:=0 to 5 do
       StrTemp:=StrTemp+IntToHex(Integer(Adapter.adapter_address[intIdx]),2);
       Result:=StrTemp;
    finally
    end;
end;

end.

#5


谢谢

#6


楼主有没有c#版的,谢谢。