API??

解决方案 »

  1.   

    看看这里两段代码:
    //获得mac address
    // Fetches the MAC address and prints it
    static void GetMACaddress(void)
    {
      IP_ADAPTER_INFO AdapterInfo[16];       // Allocate information 
                                             // for up to 16 NICs
      DWORD dwBufLen = sizeof(AdapterInfo);  // Save memory size of buffer  DWORD dwStatus = GetAdaptersInfo(      // Call GetAdapterInfo
        AdapterInfo,                 // [out] buffer to receive data
        &dwBufLen);                  // [in] size of receive data buffer
      assert(dwStatus == ERROR_SUCCESS);  // Verify return value is 
                                          // valid, no buffer overflow  PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo; // Contains pointer to
                                                   // current adapter info
      do {
        PrintMACaddress(pAdapterInfo->Address); // Print MAC address
        pAdapterInfo = pAdapterInfo->Next;    // Progress through 
                                              // linked list
      }
      while(pAdapterInfo);                    // Terminate if last adapter
    }
    //详细请见(source code ):
    http://codeguru.earthweb.com/network/GetMAC.html
    // Fetches the MAC address and prints it
    static void GetMACaddress(void)
    {
      unsigned char MACData[8];      // Allocate data structure 
                                     // for MAC (6 bytes needed)  WKSTA_TRANSPORT_INFO_0 *pwkti; // Allocate data structure 
                                     // for NetBIOS
      DWORD dwEntriesRead;
      DWORD dwTotalEntries;
      BYTE *pbBuffer;
        
      // Get MAC address via NetBIOS's enumerate function
      NET_API_STATUS dwStatus = NetWkstaTransportEnum(
       NULL,                 // [in]  server name
       0,                    // [in]  data structure to return
       &pbBuffer,            // [out] pointer to buffer
       MAX_PREFERRED_LENGTH, // [in]  maximum length
       &dwEntriesRead,       // [out] counter of elements 
                             //       actually enumerated
       &dwTotalEntries,      // [out] total number of elements 
                             //       that could be enumerated
       NULL);                // [in/out] resume handle
      assert(dwStatus == NERR_Success);  pwkti = (WKSTA_TRANSPORT_INFO_0 *)pbBuffer; // type cast the buffer  for(DWORD i=1; i< dwEntriesRead; i++)  // first address is
                                                // 00000000, skip it
      {                                         // enumerate MACs & print
        swscanf((wchar_t *)pwkti[i].wkti0_transport_address,
                L"%2hx%2hx%2hx%2hx%2hx%2hx",
                &MACData[0],
                &MACData[1],
                &MACData[2], 
                &MACData[3],
                &MACData[4],
                &MACData[5]);
        PrintMACaddress(MACData);
      }  // Release pbBuffer allocated by above function
      dwStatus = NetApiBufferFree(pbBuffer);
      assert(dwStatus == NERR_Success);
    }
      

  2.   

    //use IpHlpapi
    // Note: Win2000 only
    //   NOT NT 4.0, Win9x, WinME#pragma comment( lib, "Iphlpapi" )
    #pragma comment( lib, "Ws2_32" )#include <windows.h>
    #include <Iphlpapi.h>int main( ) {IPAddr ip = 0;
    ULONG  mac = 0;
    DWORD  error = 0;    DWORD dwSize = sizeof( ULONG) ;
        ip = inet_addr("192.168.0.100");
        //ip = inet_addr("xxx.xxx.xxx.xxx");
        error = SendARP(ip,0,&mac,&dwSize);    return 0;
    }
      

  3.   

    第一种方法使用Microsoft的Netbios API。 这是一套通过Winsock提供底层网络支持的命令。使用Netbios的最大缺点是您必须在系统中安装了Netbios服务(如果您在windows网络中启用了文件共享的话,这就不是问题了)。除此此外,这种方法又快又准确。Netbios API只包括了一个函数,就叫做Netbios。这个函数使用网络控制块(network control block)结构作为参数,这个结构告诉函数要做什么。结构的定义如下:
      typedef struct _NCB {
        UCHAR  ncb_command;
        UCHAR  ncb_retcode;
        UCHAR  ncb_lsn;
        UCHAR  ncb_num;
        PUCHAR ncb_buffer;
        WORD   ncb_length;
        UCHAR  ncb_callname[NCBNAMSZ];
        UCHAR  ncb_name[NCBNAMSZ];
        UCHAR  ncb_rto;
        UCHAR  ncb_sto;
        void (CALLBACK *ncb_post) (struct _NCB *);
        UCHAR  ncb_lana_num;
        UCHAR  ncb_cmd_cplt;
     #ifdef _WIN64
        UCHAR  ncb_reserve[18];
     #else
        UCHAR  ncb_reserve[10];
     #endif
        HANDLE ncb_event;
    } NCB, *PNCB; 重点在于ncb_command 成员。这个成员告诉Netbios该作什么。我们使用三个命令来探测MAC地址。他们在MSDN的定义如下:
    命令描述:
    NCBENUM Windows NT/2000: 列举系统中网卡的数量。使用此命令后,ncb_buffer成员指向由LANA_ENUM结构填充的缓冲区。
    NCBENUM 不是标准的 NetBIOS 3.0 命令。NCBRESET 重置网卡。网卡在接受新的NCB命令之前必须重置。
    NCBASTAT 接受本地或远程接口卡的状态。使用此命令后,ncb_buffer成员指向由ADAPTER_STATUS结构填充的缓冲区,随后是NAME_BUFFER结构的数组。下面就是取得您系统MAC地址的步骤:
    1》列举所有的接口卡。
    2》重置每块卡以取得它的正确信息。
    3》查询接口卡,取得MAC地址并生成标准的冒号分隔格式。下面就是实例源程序。
    netbios.cpp#include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <iostream>
    #include <string>using namespace std;
    #define bzero(thing,sz) memset(thing,0,sz)bool GetAdapterInfo(int adapter_num, string &mac_addr)
    {
      // 重置网卡,以便我们可以查询
      NCB Ncb;
      memset(&Ncb, 0, sizeof(Ncb));
      Ncb.ncb_command = NCBRESET;
      Ncb.ncb_lana_num = adapter_num;
      if (Netbios(&Ncb) != NRC_GOODRET) {
        mac_addr = "bad (NCBRESET): ";
        mac_addr += string(Ncb.ncb_retcode);
        return false;
      }  // 准备取得接口卡的状态块
      bzero(&Ncb,sizeof(Ncb);
      Ncb.ncb_command = NCBASTAT;
      Ncb.ncb_lana_num = adapter_num;
      strcpy((char *) Ncb.ncb_callname, "*");
      struct ASTAT
      {
        ADAPTER_STATUS adapt;
        NAME_BUFFER NameBuff[30];
      } Adapter;
      bzero(&Adapter,sizeof(Adapter));
      Ncb.ncb_buffer = (unsigned char *)&Adapter;
      Ncb.ncb_length = sizeof(Adapter);  // 取得网卡的信息,并且如果网卡正常工作的话,返回标准的冒号分隔格式。
      if (Netbios(&Ncb) == 0)
      {
        char acMAC[18];
        sprintf(acMAC, "%02X:%02X:%02X:%02X:%02X:%02X",
                int (Adapter.adapt.adapter_address[0]),
                int (Adapter.adapt.adapter_address[1]),
                int (Adapter.adapt.adapter_address[2]),
                int (Adapter.adapt.adapter_address[3]),
                int (Adapter.adapt.adapter_address[4]),
                int (Adapter.adapt.adapter_address[5]));
        mac_addr = acMAC;
        return true;
      }
      else
      {
        mac_addr = "bad (NCBASTAT): ";
        mac_addr += string(Ncb.ncb_retcode);
        return false;
      }
    }int main()
    {
      // 取得网卡列表
      LANA_ENUM AdapterList;
      NCB Ncb;
      memset(&Ncb, 0, sizeof(NCB));
      Ncb.ncb_command = NCBENUM;
      Ncb.ncb_buffer = (unsigned char *)&AdapterList;
      Ncb.ncb_length = sizeof(AdapterList);
      Netbios(&Ncb);  // 取得本地以太网卡的地址
      string mac_addr;
      for (int i = 0; i < AdapterList.length - 1; ++i)
      {
        if (GetAdapterInfo(AdapterList.lana[i], mac_addr))
        {
          cout << "Adapter " << int (AdapterList.lana[i]) <<
                  "'s MAC is " << mac_addr << endl;
        }
        else
        {
          cerr << "Failed to get MAC address! Do you" << endl;
          cerr << "have the NetBIOS protocol installed?" << endl;
          break;
        }
      }  return 0;
    }
    file://---------------------------------------------------------------------------/
    第二种方法-使用COM GUID API
    这种方法使用COM API创建一个GUID(全局唯一标识符)并从那里继承MAC地址。GUID通常用来标识COM组件以及系统中的其他对象。它们是由MAC地址(结合其他东西)计算得来的,表面上MAC地址就包含在其中。我说表面上是因为事实上并没有包含。
    我提供这种方法更多的是为了作为反面教材。您也许用这种方法能够得到MAC地址,但有时候您只会得到随机的十六进制数值。
    下面的例子十分简单,无需多讲。我们使用CoCreateGuid创建GUID,并将最后六个字节放入字符串中。它们可能是MAC地址,但并不是必然的。uuid.cpp
    #include <windows.h>
    #include <iostream>
    #include <conio.h>using namespace std;int main()
    {
        cout << "MAC address is: ";    // 向COM要求一个UUID。如果机器中有以太网卡,
        // UUID最后的六个字节(Data4的2-7字节)应该是本地以太网卡的MAC地址。
        GUID uuid;
        CoCreateGuid(&uuid);
        // Spit the address out
        char mac_addr[18];
        sprintf(mac_addr,"%02X:%02X:%02X:%02X:%02X:%02X",
                uuid.Data4[2],uuid.Data4[3],uuid.Data4[4],
                uuid.Data4[5],uuid.Data4[6],uuid.Data4[7]);
        cout << mac_addr << endl;
        getch();
        return 0;
    }
      

  4.   

    第三种方法- 使用SNMP扩展API
    我要讨论的第三种方法是使用Windows的SNMP(简单网络管理协议)扩展来取得MAC地址。在我的经验里,这个协议很简单。代码也是直勾勾的向前的。基本步骤和Netbios相同:
    1》取得网卡列表
    2》查询每块卡的类型和MAC地址
    3》保存当前网卡
    我个人对SNMP了解不多,但如我刚刚所言,代码十分清楚。snmp.cpp
    #include <snmp.h>
    #include <conio.h>
    #include <stdio.h>typedef bool(WINAPI * pSnmpExtensionInit) (
            IN DWORD dwTimeZeroReference,
            OUT HANDLE * hPollForTrapEvent,
            OUT AsnObjectIdentifier * supportedView);typedef bool(WINAPI * pSnmpExtensionTrap) (
            OUT AsnObjectIdentifier * enterprise,
            OUT AsnInteger * genericTrap,
            OUT AsnInteger * specificTrap,
            OUT AsnTimeticks * timeStamp,
            OUT RFC1157VarBindList * variableBindings);typedef bool(WINAPI * pSnmpExtensionQuery) (
            IN BYTE requestType,
            IN OUT RFC1157VarBindList * variableBindings,
            OUT AsnInteger * errorStatus,
            OUT AsnInteger * errorIndex);typedef bool(WINAPI * pSnmpExtensionInitEx) (
            OUT AsnObjectIdentifier * supportedView);void main()
    {
      HINSTANCE m_hInst;
      pSnmpExtensionInit m_Init;
      pSnmpExtensionInitEx m_InitEx;
      pSnmpExtensionQuery m_Query;
      pSnmpExtensionTrap m_Trap;
      HANDLE PollForTrapEvent;
      AsnObjectIdentifier SupportedView;
      UINT OID_ifEntryType[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 3};
      UINT OID_ifEntryNum[] = {1, 3, 6, 1, 2, 1, 2, 1};
      UINT OID_ipMACEntAddr[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 6};
      AsnObjectIdentifier MIB_ifMACEntAddr =
        { sizeof(OID_ipMACEntAddr)  sizeof(UINT), OID_ipMACEntAddr };
      AsnObjectIdentifier MIB_ifEntryType =
        {sizeof(OID_ifEntryType)  sizeof(UINT), OID_ifEntryType};
      AsnObjectIdentifier MIB_ifEntryNum =
        {sizeof(OID_ifEntryNum)  sizeof(UINT), OID_ifEntryNum};
      RFC1157VarBindList varBindList;
      RFC1157VarBind varBind[2];
      AsnInteger errorStatus;
      AsnInteger errorIndex;
      AsnObjectIdentifier MIB_NULL = {0, 0};
      int ret;
      int dtmp;
      int i = 0, j = 0;
      bool found = false;
      char TempEthernet[13];
      m_Init = NULL;
      m_InitEx = NULL;
      m_Query = NULL;
      m_Trap = NULL;  /* 载入SNMP DLL并取得实例句柄 */
      m_hInst = LoadLibrary("inetmib1.dll");
      if (m_hInst < (HINSTANCE) HINSTANCE_ERROR)
      {
        m_hInst = NULL;
        return;
      }
      m_Init =
        (pSnmpExtensionInit) GetProcAddress(m_hInst, "SnmpExtensionInit");
      m_InitEx =
        (pSnmpExtensionInitEx) GetProcAddress(m_hInst,
                                              "SnmpExtensionInitEx");
      m_Query =
        (pSnmpExtensionQuery) GetProcAddress(m_hInst,
                                             "SnmpExtensionQuery");
      m_Trap =
        (pSnmpExtensionTrap) GetProcAddress(m_hInst, "SnmpExtensionTrap");
      m_Init(GetTickCount(), &PollForTrapEvent, &SupportedView);  /* 初始化用来接收m_Query查询结果的变量列表 */
      varBindList.list = varBind;
      varBind[0].name = MIB_NULL;
      varBind[1].name = MIB_NULL;  /* 在OID中拷贝并查找接口表中的入口数量 */
      varBindList.len = 1;        /* Only retrieving one item */
      SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryNum);
      ret =
        m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus,
                &errorIndex);
      printf("# of adapters in this system : %in",
           varBind[0].value.asnValue.number);
      varBindList.len = 2;  /* 拷贝OID的ifType-接口类型 */
      SNMP_oidcpy(&varBind[0].name, &MIB_ifEntryType);  /* 拷贝OID的ifPhysAddress-物理地址 */
      SNMP_oidcpy(&varBind[1].name, &MIB_ifMACEntAddr);  do
      {    /* 提交查询,结果将载入 varBindList。
           可以预料这个循环调用的次数和系统中的接口卡数量相等 */
        ret =
          m_Query(ASN_RFC1157_GETNEXTREQUEST, &varBindList, &errorStatus,
                  &errorIndex);
        if (!ret)
          ret = 1;
        else
            /* 确认正确的返回类型 */
          ret =
              SNMP_oidncmp(&varBind[0].name, &MIB_ifEntryType,
                           MIB_ifEntryType.idLength); if (!ret) {
        j++;
        dtmp = varBind[0].value.asnValue.number;
        printf("Interface #%i type : %in", j, dtmp);    /* Type 6 describes ethernet interfaces */
        if (dtmp == 6)
        {      /* 确认我们已经在此取得地址 */
          ret =
              SNMP_oidncmp(&varBind[1].name, &MIB_ifMACEntAddr,
                           MIB_ifMACEntAddr.idLength);
          if ((!ret) && (varBind[1].value.asnValue.address.stream != NULL))
          {
            if((varBind[1].value.asnValue.address.stream[0] == 0x44)
              && (varBind[1].value.asnValue.address.stream[1] == 0x45)
              && (varBind[1].value.asnValue.address.stream[2] == 0x53)
              && (varBind[1].value.asnValue.address.stream[3] == 0x54)
              && (varBind[1].value.asnValue.address.stream[4] == 0x00))
            {
              /* 忽略所有的拨号网络接口卡 */
              printf("Interface #%i is a DUN adaptern", j);
              continue;
            }
            if ((varBind[1].value.asnValue.address.stream[0] == 0x00)
                && (varBind[1].value.asnValue.address.stream[1] == 0x00)
                && (varBind[1].value.asnValue.address.stream[2] == 0x00)
                && (varBind[1].value.asnValue.address.stream[3] == 0x00)
                && (varBind[1].value.asnValue.address.stream[4] == 0x00)
                && (varBind[1].value.asnValue.address.stream[5] == 0x00))
            {
              /* 忽略由其他的网络接口卡返回的NULL地址 */
              printf("Interface #%i is a NULL addressn", j);
              continue;
            }
            sprintf(TempEthernet, "%02x%02x%02x%02x%02x%02x",
                    varBind[1].value.asnValue.address.stream[0],
                    varBind[1].value.asnValue.address.stream[1],
                    varBind[1].value.asnValue.address.stream[2],
                    varBind[1].value.asnValue.address.stream[3],
                    varBind[1].value.asnValue.address.stream[4],
                    varBind[1].value.asnValue.address.stream[5]);
            printf("MAC Address of interface #%i: %sn", j,
                   TempEthernet);}
          }
        }
      } while (!ret);         /* 发生错误终止。 */
      getch();  FreeLibrary(m_hInst);
      /* 解除绑定 */
      SNMP_FreeVarBind(&varBind[0]);
      SNMP_FreeVarBind(&varBind[1]);
    } --------------------------------
    NO.4
        int ip = 0; //here
        unsigned char   mac[6];
        DWORD  error = 0;
        ULONG dwSize = 6;
            m_szRemoteIP.GetWindowText(m_szremoteip);
        ip = inet_addr(m_szremoteip);
        error = SendARP(ip,0,(PULONG)&mac,&dwSize);
        if (error == NO_ERROR )
            {
            //    printf( "MacAddress: " );
                //    printf( "%d\n", mac );
                    m_szRemoteMAC.Format("%02X-%02X-%02X-%02X-%02X-%02X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);//here
            }
            else
            //    printf( "SendARP Error:%d\n", GetLastError());
            return;
        m_remotemac.SetWindowText(m_szRemoteMAC);
      

  5.   

    得到远程机器的mac地址
    #include "..."
    #include "iphlpapi.h"#pragma comment ( lib, "ws2_32.lib" )
    #pragma comment ( lib, "Iphlpapi.lib" )void main( int argc, char ** argv )
    {
        int numberOfHost = 1;
        struct hostent *remoteHostent;    //处理命令行参数
        if ( argc == 3 )
        numberOfHost = atoi( argv[2] );
        if ( ( argc >3 ) || ( argc < 2 ) )
        {
            printf( "RmtHost v0.2 - Get remote HostName /MacAddress\n" );
            printf( "by ShotgunLabs ( [email protected] )\n\n" );
            printf( "Usage :\n\tRmtHost.exe [RemoteIP] \n\n" );
            printf( "Example:\n\tRmtHost.exe 192.168.0.3\n" );
            printf( "\tRmtHost.exe 192.168.0.3 255\n\n" );
            exit( 0 );
        }     //初始化SOCKET
        WSADATA wsaData;
        int iRet = WSAStartup(MAKEWORD(2,1), &wsaData);
        if ( iRet != 0 )
        {
            printf( "WSAStartup Error:%d\n", GetLastError() );
            exit( 0 );
        }
        int nRemoteAddr = inet_addr( argv[1] );
        remoteHostent= (struct hostent*)malloc( sizeof(struct hostent ));
        struct in_addr sa;
        for ( int i = 0; i < numberOfHost; i ++ )
        {
            //获取远程机器名
            sa.s_addr = nRemoteAddr;
            printf( "\nIpAddress : %s\n", inet_ntoa( sa ) );
            remoteHostent = gethostbyaddr( (char*)&nRemoteAddr,4, AF_INET );
            if ( remoteHostent )
                printf( "HostName : %s\n",remoteHostent->h_name );
            else
                printf( "gethostbyaddr Error:%d\n",GetLastError() );
            //发送ARP查询包获得远程MAC地址        unsigned char macAddress[6];
            ULONG macAddLen = 6;
            iRet=SendARP(nRemoteAddr, (unsigned long)NULL,(PULONG)&macAddress, &macAddLen);
            if ( iRet == NO_ERROR )
            {
                printf( "MacAddress: " );
                for( int i =0; i<6; i++ )
                {
                    printf( "%.2x", macAddress[i] );
                    if ( i<5 ) printf( "-" );
                }
                printf( "\n" );
            }
            else
                printf( "SendARP Error:%d\n", GetLastError());
                nRemoteAddr = htonl( ntohl( nRemoteAddr ) + 1 );
        }
    }
      

  6.   

    IpHlpapi.lib-->Platform SDK
    Get mac address:
    NetBIOS(可以抓到所有安装NetBIOS的机器的Mac,一般为windows机器)
    SNMP(可以抓到所有安装SNMP的机器的Mac,并且可以抓到一台所有的Mac address)
    GetIpNetTable(可以得到存放于Arp cache中的机器的Mac address,作用类似于
    arp -a,但是这些机器不包括本机,并且只能记录router table中存在的网段)
      

  7.   

    NetBios有时候不能得到便携机的MAC,建议使用IP助手,我上次就有这个问题,在本论坛中已界贴,去找找
      

  8.   

    Iphlpapi.lib我的确有,可是Iphlpapi.h我就怎么都找不到。
    我上google查,看到很多说同样问题的,可是除了说下载platform SDK的就没别的方法了,那东西可是要上百兆的啊!
      

  9.   

    function GetMac:string;
         procedure NBGetMac(Strings: TStrings);
          function HexBL(by: Byte): String;
          begin
            Result := Format('%x', [by]);
            if Length(Result) < 2 then
              Result := '0' + Result;
          end;
        var
          NCB: TNCB;
          Adapter: TAdapterStatus;
          LanaEnum: TLanaEnum;
          I, J: Integer;
          Str: String;
        begin
          Strings.Clear;
          ZeroMemory(@NCB,SizeOf(NCB));      NCB.ncb_command := Chr(NCBENUM);
          NetBios(@NCB);      NCB.ncb_buffer := @LanaEnum;
          NCB.ncb_length := SizeOf(LanaEnum);
          NCB.ncb_command := Chr(NCBENUM);
          NetBios(@NCB);      for I := 0 to Ord(LanaEnum.length) - 1 do
          begin
            ZeroMemory(@NCB,SizeOf(NCB));
            NCB.ncb_command := Chr(NCBRESET);
            NCB.ncb_lana_num := LanaEnum.lana[I];
            NetBios(@NCB);        ZeroMemory(@NCB,SizeOf(NCB));
            NCB.ncb_command := Chr(NCBASTAT);
            NCB.ncb_lana_num := LanaEnum.lana[I];
            StrPCopy(NCB.ncb_callname,'*');
            NCB.ncb_buffer := @Adapter;
            NCB.ncb_length := SizeOf(Adapter);
            NetBios(@NCB);        Str := '';
            if  (Adapter.xmit_success<>0) and (Adapter.recv_success<>0) then
            begin
              for J := 0 to 5 do
              begin
                if J > 0 then Str := Str + '-';
                Str := Str + HexBL(Byte(Adapter.adapter_address[J]));
              end;
              Strings.Add(Str);
            end;
          end;
        end;
    var
      cardlist:Tstrings;
      stemp:string;begin
      cardlist:=Tstringlist.Create;  NBGetMac(cardlist);
      //if cardlist.Count>=4 then
         stemp:= cardlist.Strings[0];
      //else
      //  stemp:=cardlist.Strings[round(((cardlist.Count+1)/2)+0.2)-1];  while pos('-',stemp)>0 do
         system.Delete(stemp,pos('-',stemp),1);
      result:=stemp
    end;
      

  10.   

    这些方法都是个注册表读取的,
     见::  如何从EPROM直接得到本机的MAC地址???,我正在请教
      

  11.   

     &&NetBios不推荐,因为会获得一些虚拟网卡地址。IpHlp不错,ipconfig就是用的这种方法。若缺少头文件可以安装一个SDK。