1

I'm using one popular Delphi function and one laptop with Wi-fi adapter connected on attempt to set preferred and alternative dns server address and catch an error saying - "Invalid Syntax". I think "Win32_NetworkAdapterConfiguration" function work only in Ethernet adapters and not in Wi-fi adapters, or I'm wrong?

Exceptions generated:

http://prntscr.com/4qvjmz enter image description here http://prntscr.com/4qvjvn
enter image description here

And this is the function:

uses
ComObj, ActiveX, UrlMon, Variants;

    function SetDnsServers(const APrimaryDNS : string;
                           const AAlternateDNS : string = '') : integer;
    var Retvar : integer;
        oBindObj : IDispatch;
        oNetAdapters,oNetAdapter,
        oDnsAddr,oWMIService : OleVariant;
        i,iValue,iSize : longword;
        oEnum : IEnumvariant;
        oCtx : IBindCtx;
        oMk : IMoniker;
        sFileObj : widestring;
    begin
      Retvar := 0;
      sFileObj := 'winmgmts:\\.\root\cimv2';
      iSize := 0;
      if APrimaryDNS <> '' then inc(iSize);
      if AAlternateDNS <> '' then inc(iSize);

      if iSize = 0 then begin
       oDnsAddr := VarArrayCreate([1,iSize],varOleStr);
       oDnsAddr[1] := APrimaryDNS;
       if iSize > 1 then oDnsAddr[2] := AAlternateDNS;
      end;

      OleCheck(CreateBindCtx(0,oCtx));
      OleCheck(MkParseDisplayNameEx(oCtx,PWideChar(sFileObj),i,oMk));
      OleCheck(oMk.BindToObject(oCtx,nil,IUnknown,oBindObj));
      oWMIService := oBindObj;

      oNetAdapters := oWMIService.ExecQuery('Select * from ' +
                                            'Win32_NetworkAdapterConfiguration ' +
                                            'where IPEnabled=TRUE');
      oEnum := IUnknown(oNetAdapters._NewEnum) as IEnumVariant;

      while oEnum.Next(1,oNetAdapter,iValue) = 0 do begin
        try
          if iSize > 0 then
            Retvar := oNetAdapter.SetDNSServerSearchOrder(oDnsAddr)
          else
            Retvar := oNetAdapter.SetDNSServerSearchOrder();
        except
          Retvar := -1;
        end;

        oNetAdapter := Unassigned;
      end;

      oDnsAddr := Unassigned;
      oNetAdapters := Unassigned;
      oWMIService := Unassigned;
      Result := Retvar;
    end;



//Usage:

    begin
    SetDnsServers('104.131.220.61','104.131.220.61');

    end.
Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
  • Use the debugger. Which line of code in `SetDNSServers` is raising the exception? – Ken White Sep 27 '14 at 22:02
  • @Ken White, is raising the exception only in this line, and not indicate any other line into `SetDNSServers` function. –  Sep 27 '14 at 22:11
  • Step into the SetDNSServers` function, and see which line **in that function** is raising the exception. (Set a breakpoint on the line you've highlighted, and when the debugger stops at that breakpoint use F7 to step into the function's code.) One of the lines inside that function is causing the exception to be raised, and you need to use the debugger to determine which one. – Ken White Sep 27 '14 at 22:17
  • @Ken White, the breakpoint show this exception in this line `OleCheck(MkParseDisplayNameEx(oCtx,PWideChar(sFileObj),i,oMk));` –  Sep 27 '14 at 22:37
  • OK. So now you know that `MkParseDisplayNameEx` is the function causing the problem, so check the documentation for `MkParseDisplayNameEx` (Google should help you find it) and see what the proper syntax is, and examine the parameters being passed into it in `sFileObj` and `i` to see if they are proper according to that documentation. You have the information we don't have (the actual contents of those values when the exception is raised), and I for one don't have anything set up where I can try to change my DNS server in order to debug your code for you. – Ken White Sep 27 '14 at 22:43

2 Answers2

3

I solved my problem with other function, thank you all!

function ArrayToVarArray(Arr : Array Of string):OleVariant; overload;
var
 i : integer;
begin
    Result   :=VarArrayCreate([0, High(Arr)], varVariant);
    for i:=Low(Arr) to High(Arr) do
     Result[i]:=Arr[i];
end;

procedure  SetDNS();
const
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator : OLEVariant;
  FWMIService   : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject   : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;
  vIPAddress         : OleVariant;
begin
CoInitialize(nil);
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService   := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
  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
    vIPAddress   := ArrayToVarArray(['104.131.220.61']);
    if FWbemObject.SetDNSServerSearchOrder(vIPAddress) = 0 then
    begin
    exit;
    end;
    VarClear(vIPAddress);
    FWbemObject:=Unassigned;
    CoUninitialize;
  end;
end;

2

oDnsAddr is unassigned because iSize is being incremented but your condition means it will never be populated.

if iSize = 0 then
begin
    oDnsAddr := VarArrayCreate([1,iSize],varOleStr);
    oDnsAddr[1] := APrimaryDNS;
    if iSize > 1 then oDnsAddr[2] := AAlternateDNS;
end;

Then your later condition is being met

if iSize > 0 then
    Retvar := oNetAdapter.SetDNSServerSearchOrder(oDnsAddr)

Providing an unassigned OleVariant.

It should be:

iSize := 0;

if APrimaryDNS <> '' then inc(iSize);
if AAlternateDNS <> '' then inc(iSize);

if iSize > 0 then
begin
    oDnsAddr := VarArrayCreate([1,iSize],varOleStr);
    oDnsAddr[1] := APrimaryDNS;
    if iSize > 1 then oDnsAddr[2] := AAlternateDNS;
end;
TheStatehz
  • 310
  • 2
  • 7
  • I followed your hint, but still appear the same erro. Sincerely, based in this post where author show a configuration screen of WinXP (http://stackoverflow.com/questions/15427269/change-dns-address-using-vb-net) and that also use WMI `"Win32_NetworkAdapterConfiguration"` class in C#. I think this kind of code works only in WinXP :(. I hope that I'm wrong :) –  Sep 28 '14 at 01:25
  • Why would the code only work in XP? You are running as admin under Win 7/8 right? – David Heffernan Sep 28 '14 at 08:59
  • Yes @David Heffernan. Could test this code to me on your computer and say me if worked? –  Sep 28 '14 at 12:53
  • No thanks. I don't really see why an app should be changing dns settings. – David Heffernan Sep 28 '14 at 13:27