Ищет MAC-адрес физического адаптера

Я хотел бы использовать уникальный идентификатор, чтобы определить, переместилось ли мое приложение на другой компьютер. Кажется, что MAC-адрес подходит для этой цели. Код, который я использую, таков:

Procedure TForm4.GetMacAddress;
var item: TListItem;
    objWMIService : OLEVariant;
    colItems      : OLEVariant;
    colItem       : OLEVariant;
    oEnum         : IEnumvariant;
    iValue        : LongWord;
    wmiHost, root, wmiClass: string;
    i: Int32;

  function GetWMIObject(const objectName: String): IDispatch;
  var
    chEaten: Integer;
    BindCtx: IBindCtx;//for access to a bind context
    Moniker: IMoniker;//Enables you to use a moniker object
  begin
    OleCheck(CreateBindCtx(0, bindCtx));
    OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));//Converts a string into a moniker that identifies the object named by the string
    OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));//Binds to the specified object
  end;

begin
   wmiHost       := '.';
   root          := 'root\CIMV2';
   wmiClass      := 'Win32_NetworkAdapterConfiguration';
   objWMIService := GetWMIObject(Format('winmgmts:\\%s\%s',[wmiHost,root]));
   colItems      := objWMIService.ExecQuery(Format('SELECT * FROM %s',[wmiClass]),'WQL',0);
   oEnum         := IUnknown(colItems._NewEnum) as IEnumVariant;
   i := 0;
   while oEnum.Next(1, colItem, iValue) = 0 do
   begin
      Item := View.Items.Add;
      item.Caption := Copy (colItem.Caption, 2, 8);

      Item.SubItems.Add (colItem.Description);
      Item.SubItems.Add (colItem.ServiceName);
      Item.SubItems.Add (VarToStrNil (colItem.MACAddress));
      if (VarToStrNil(colItem.MACAddress) <> '')
         then Item.SubItems.Add ('yes')
         else Item.SubItems.Add ('no');
      if colItem.IPEnabled
         then Item.SubItems.Add ('yes')
         else Item.SubItems.Add ('no');
     Item.SubItems.Add (VarToStrNil (colItem.SettingID));
     Item.SubItems.Add (IntToStr (colItem.InterfaceIndex));
   end; // if
end; // GetMacAddress //

Моя машина имеет один сетевой порт, но этот код находит 18 сетевых портов/вещей/что-то еще. Среди них четыре MAC-адреса. Я предполагаю, что сетевой порт должен быть включен IP, чтобы оставить два слева (обозначенный MAC на изображении). Правильно ли считать, что из фильтров, фильтрованных таким образом, один с самым низким индексом является аппаратным портом?

enter image description here

Изменить в снимке выше адаптера Realtek является единственным физическим адаптером в машине. Другой адаптер - виртуальный адаптер VirtualBox. Ответ TLama идентифицирует эти два адаптера, но есть ли способ найти адрес единственного адаптера Physical (Realtek)?

Обновление 1 EJP указал, что MAC-адрес можно изменить. Это несколько подрывает мою цель, но поскольку я ищу решение, которое подходит для большинства ситуаций, я решил жить с ним.

TLama и Tndrej указали на несколько решений. Оба заканчиваются ситуацией, когда физический адаптер не может быть найден без каких-либо сомнений.

Обновление 2 Отличный список чтения TLama показывает, что, вероятно, не существует определенного способа определить физический адаптер. Статья, упомянутая в первой брошюре, показывает, как уменьшить количество адаптеров на основе некоторых простых допущений. В статье в третьей брошюре показано, как выбрать адаптер, подключенный к шине PCI, что на самом деле именно то, что я хотел знать. Есть некоторые странные исключения, упомянутые в статье, но я думаю, что это даст ответ в большинстве случаев.

Спасибо всем за ваш вклад!

6
15 мая '12 в 11:10
источник поделиться
2 ответов

Вместо этого используйте Win32_NetworkAdapter. Он имеет член PhysicalAdapter. В следующем примере вы должны указать MAC-адреса физических адаптеров:

program Program1;

{$APPTYPE CONSOLE}

uses
  SysUtils, ActiveX, ComObj, Variants;

procedure GetWin32_NetworkAdapterInfo;
const
  WbemUser = '';
  WbemPassword = '';
  WbemComputer = 'localhost';
  wbemFlagForwardOnly = $00000020;
var
  ElementCount: LongWord;
  FWMIService: OleVariant;
  FWbemObject: OleVariant;
  EnumVariant: IEnumVARIANT;
  FSWbemLocator: OleVariant;
  FWbemObjectSet: OleVariant;
begin;
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
  FWbemObjectSet := FWMIService.ExecQuery('SELECT * FROM Win32_NetworkAdapter WHERE PhysicalAdapter = 1', 'WQL', wbemFlagForwardOnly);
  EnumVariant := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  while EnumVariant.Next(1, FWbemObject, ElementCount) = 0 do
  begin
    Writeln(Format('MACAddress %s', [VarToStr(FWbemObject.MACAddress)]));
    FWbemObject := Unassigned;
  end;
end;

begin
  try
    CoInitialize(nil);
    try
      GetWin32_NetworkAdapterInfo;
    finally
      CoUninitialize;
    end;
  except
    on E:EOleException do
      Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
    on E:Exception do
      Writeln(E.Classname, ':', E.Message);
  end;
  Writeln('Press Enter to exit');
  Readln;
end.

На основе кода, сгенерированного WMI Delphi Code Creator.

Update:

На самом деле вы пытаетесь отфильтровать адаптеры, принадлежащие виртуальным машинам, что не так просто, поскольку они имитируются как физические (вы даже можете увидеть их в Диспетчере устройств в качестве физических адаптеров), поэтому вы не могут различать их, например:

  • членом DHCPEnabled класса Win32_NetworkAdapter, поскольку даже виртуальные машины могут быть настроены таким образом, что они получают IP-адрес от Сервер DHCP
  • членом AdapterTypeId класса Win32_NetworkAdapter, поскольку для виртуальных адаптеров нет специального типа
  • членом PhysicalAdapter класса Win32_NetworkAdapter, потому что они имитируются как физические

Дополнительное чтение:

7
15 мая '12 в 11:53
источник

Связанные вопросы


Похожие вопросы

Вы также можете использовать GetAdaptersAddresses API из IP Helper библиотека. Для перевода Delphi Magenta Systems IP Helper Component выглядит на первый взгляд хорошо.

4
15 мая '12 в 11:56
источник

Посмотрите другие вопросы по меткам или Задайте вопрос