2

I am looking for a way to be able to retrieve IP Subnet mask of the computer I am currently running on at run time, in Delphi.

Is there a way in code for me to retrieve the subnet mask and store it so that I may use it in other operations?

Thanks

Pippa Rose Smith
  • 1,377
  • 5
  • 18
  • 42
  • 3
    Will your application target also machines with Windows 2k ? If not, then I can try to make an example using [`GetAdaptersAddresses`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85).aspx) function instead (before RRUZ wake up with the WMI solution :-) – TLama Aug 28 '12 at 10:29
  • 1
    Yes please, an example using GetAdaptersAddresses would be good. We are using XP and above. – Pippa Rose Smith Aug 28 '12 at 10:47
  • When I got the `GetAdaptersAddresses` to work in Delphi with a brand new header translation I found one MS surprise - how to get the IP mask from this big structure. Check out [`this thread`](http://comp.newsgroups.archived.at/os.ms-windows.programmer.win32/200908/09081149950.html) to partially feel my current temper. I can post it here, but I really have no idea if there's a way to get the mask different from the use of `ConvertLengthToIpv4Mask` which is supported on Vista above systems. In all cases I'll review what I've already posted. More and more I feel, the WMI will be the easiest way. – TLama Aug 28 '12 at 14:53
  • @TLama, I just post the WMI alternative :-) – RRUZ Aug 28 '12 at 14:58

2 Answers2

5

You can use the Win32_NetworkAdapterConfiguration WMI class and the IPSubnet property.

Try this sample code

{$APPTYPE CONSOLE}


uses
  SysUtils,
  ActiveX,
  ComObj,
  Variants;

function VarArrayToStr(const vArray: variant): string;

    function _VarToStr(const V: variant): string;
    var
    Vt: integer;
    begin
    Vt := VarType(V);
        case Vt of
          varSmallint,
          varInteger  : Result := IntToStr(integer(V));
          varSingle,
          varDouble,
          varCurrency : Result := FloatToStr(Double(V));
          varDate     : Result := VarToStr(V);
          varOleStr   : Result := WideString(V);
          varBoolean  : Result := VarToStr(V);
          varVariant  : Result := VarToStr(Variant(V));
          varByte     : Result := char(byte(V));
          varString   : Result := String(V);
          varArray    : Result := VarArrayToStr(Variant(V));
        end;
    end;

var
i : integer;
begin
    Result := '[';
     if (VarType(vArray) and VarArray)=0 then
       Result := _VarToStr(vArray)
    else
    for i := VarArrayLowBound(vArray, 1) to VarArrayHighBound(vArray, 1) do
     if i=VarArrayLowBound(vArray, 1)  then
      Result := Result+_VarToStr(vArray[i])
     else
      Result := Result+'|'+_VarToStr(vArray[i]);

    Result:=Result+']';
end;

procedure  GetWin32_NetworkAdapterConfigurationInfo;
const
  WbemUser            ='';
  WbemPassword        ='';
  WbemComputer        ='localhost';
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator : OLEVariant;
  FWMIService   : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject   : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;
begin;
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService   := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
  FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_NetworkAdapterConfiguration Where IpEnabled=True','WQL',wbemFlagForwardOnly);
  oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  while oEnum.Next(1, FWbemObject, iValue) = 0 do
  begin
    Writeln(Format('Caption       %s',[String(FWbemObject.Caption)]));// String
    if not VarIsNull(FWbemObject.DHCPServer) then
      Writeln(Format('DHCPServer    %s',[String(FWbemObject.DHCPServer)]));// String
    if not VarIsNull(FWbemObject.IPAddress) then
      Writeln(Format('IPAddress     %s',[VarArrayToStr(FWbemObject.IPAddress)]));// array String

    if not VarIsNull(FWbemObject.IPSubnet) then
      Writeln(Format('IPSubnet      %s',[VarArrayToStr(FWbemObject.IPSubnet)]));// array String

    if not VarIsNull(FWbemObject.MACAddress) then
      Writeln(Format('MACAddress     %s',[VarArrayToStr(FWbemObject.MACAddress)]));// array String

    Writeln;
    FWbemObject:=Unassigned;
  end;
end;


begin
 try
    CoInitialize(nil);
    try
      GetWin32_NetworkAdapterConfigurationInfo;
    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. 
RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • 1
    +1, this is definitely easier than both methods I've been trying to use. The `GetAdaptersAddresses` with all structures and enumerations takes about 190 lines of code. That's a nice example for deep rooted WMI opponents. – TLama Aug 28 '12 at 15:06
0

1) computer may be opart of different Nets/Subnets. Each network adapter usually has some. OR even more than one sometimes.

2) Even if physically you only have one network card, ypou also have loopback network - 127.x.x.x subnet. If you have some VPN installed like Hamachi or Comodo - that would give one more network adapter. Same for phone modem when connected. Same for virtual machines like XP Compatibility Mode. So you anyway would have to filter them one some criteria.

3) You can enlist network cards with FindAdaptor function of WMI: http://www.magsys.co.uk/delphi/magwmi.asp Then you can read the properties of those adaptors. There are also mentioned functions to set IP's, probably there are also functiones to read them.

Even if not, how to read properties is shown in the demo at the URL. Which properties to read, you can determine using any WMI explorer out there. Personally i ended with WMI Explorer of ks-soft.net plus WMI Tools of Microsoft. You debug WMI request like you would do with SQLite, then pass it to WMI wrapper and read the result. However, returning back to aforementioned Set IP Address functions, their sources probably already do contain properties names, just to save on exploring.

Arioch 'The
  • 15,799
  • 35
  • 62