Results 1 to 10 of 10

Thread: Connect to wifi

  1. #1

    Connect to wifi

    Hallo,

    Ik ben bezig om met een applicatie kijkt of een SSID aanwezig en zo ja daarmee verbinding maakt.
    Hiervoor maak ik gebruik van de wlanapi van windows Althans dat is de bedoeling)
    Met de nodige voorbeelden kan ik nu de actieve wifi interfaces ophalen en de daarbij gevonden SSID's
    Echter om een connectie te maken met een SSID is mij nog niet gelukt.
    De code hiervoor heb ik wel maar mijn kennis van pointers e.d. is wat roestig.
    Voor nu heb ik het opgelost door netsh commando's uit te voeren via de shellexecute functies van de shellAPI.
    Graag zou ik alles om willen schrijven naar de native wlanapi.

    hierbij mijn code (let op de functie connect2 werkt dus nog niet)

    Wellicht weet 1 van jullie hoe ik dit verder op kan pakken

    (de API kan hier gevonden worden https://github.com/coolshou/WlanAPI)

    Code:
    unit WifiObj;
    
    interface
    uses
      Types,SysUtils,ActiveX,Windows,ComObj,Variants,Generics.Collections, Classes,
      ShellApi,nduWlanAPI,nduWlanTypes,Forms, Vcl.Dialogs;  //,
    
    type
     TWifiInfo = record
      SSID: string;
      Profile: string;
      Connectable: Boolean
     end;
    
     TWifiConnectionInfo = record
        Name                   : string; //Wi-Fi
        Description            : string; //Intel(R) Dual Band Wireless-AC 7265
        GUID                   : string; //3bce2cb5-7a1d-4c23-a2a3-7337e985db13
        Physical_address       : string; //5c:e0:c5:4a:9b:42
        State                  : string; //connected
        SSID                   : string; //..............
        BSSID                  : string; //c0:ea:e4:c1:f6:ad
        Network_type           : string; //Infrastructure
        Radio_type             : string; //802.11ac
        Authentication         : string; //WPA2-Personal
        Cipher                 : string; //CCMP
        Connection_mode        : string; //Profile
        Channel                : integer; //44
        Receive_rate           : integer; //130
        Transmit_rate          : integer; //130
        Signal                 : integer; //46%
        Profile                : string; //...............
     end;
    
     TWifiObj = class(Tobject)
      Private
       FAdapter: boolean;
       procedure GetWifiList;
      public
       WifiList:Tlist<TWifiInfo>;
       Constructor Create;
       Destructor Destroy; override;
       function Connect(aSSID:string):boolean;
       function Connect2(aSSID:string):boolean;
       function GetConnectionInfo():TWifiConnectionInfo;
      published
       property Adapter:boolean read FAdapter;
    
     end;
    
    implementation
    
    { TWifiObj }
    
    function TWifiObj.GetConnectionInfo():TWifiConnectionInfo;
     const
       CReadBuffer = 2400;
     var
       saSecurity: TSecurityAttributes;
       hRead: THandle;
       hWrite: THandle;
       suiStartup: TStartupInfo;
       piProcess: TProcessInformation;
       pBuffer: array[0..CReadBuffer] of AnsiChar;  //    <----- update
       dRead: DWord;
       dRunning: DWord;
       ACommand,AParameters:string;
       TempResult:string;
       strArray  : Tarray<String>;
     begin
       saSecurity.nLength := SizeOf(TSecurityAttributes);
       saSecurity.bInheritHandle := True;
       saSecurity.lpSecurityDescriptor := nil;
       TempResult:='';
       ACommand  :='netsh';
       AParameters :=  'wlan show interface';
    
       if CreatePipe(hRead, hWrite, @saSecurity, 0) then
       begin
         FillChar(suiStartup, SizeOf(TStartupInfo), #0);
         suiStartup.cb := SizeOf(TStartupInfo);
         suiStartup.hStdInput := hRead;
         suiStartup.hStdOutput := hWrite;
         suiStartup.hStdError := hWrite;
         suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
         suiStartup.wShowWindow := SW_HIDE;
    
         if CreateProcess(nil, PChar(ACommand + ' ' + AParameters), @saSecurity,
           @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess)
           then
         begin
           repeat
             dRunning  := WaitForSingleObject(piProcess.hProcess, 100);
             Application.ProcessMessages();
             repeat
               dRead := 0;
               ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
               pBuffer[dRead] := #0;
               OemToAnsi(pBuffer, pBuffer);
               TempResult:=TempResult +String(pBuffer);
             until (dRead < CReadBuffer);
           until (dRunning <> WAIT_TIMEOUT);
           CloseHandle(piProcess.hProcess);
           CloseHandle(piProcess.hThread);
         end;
    
         CloseHandle(hRead);
         CloseHandle(hWrite);
       end;
    
       strArray:= TempResult.Split([#13#10]);
    
       if TempResult<>'' then
       begin
        Result.Name := copy(strArray[3], pos(':',strArray[3])+2,length(strArray[3])-pos(':',strArray[3])+1);
        Result.Description := copy(strArray[4], pos(':',strArray[4])+2,length(strArray[4])-pos(':',strArray[4]));
        Result.GUID := copy(strArray[5], pos(':',strArray[5])+2,length(strArray[5])-pos(':',strArray[5]));
        Result.Physical_address := copy(strArray[6], pos(':',strArray[6])+2,length(strArray[6])-pos(':',strArray[6]));
        Result.State := copy(strArray[7], pos(':',strArray[7])+2,length(strArray[7])-pos(':',strArray[7]));
        if Result.State = 'connected' then
        begin
         Result.SSID := copy(strArray[8], pos(':',strArray[8])+2,length(strArray[8])-pos(':',strArray[8]));
         Result.BSSID := copy(strArray[9], pos(':',strArray[9])+2,length(strArray[9])-pos(':',strArray[9]));
         Result.Network_type := copy(strArray[10], pos(':',strArray[10])+2,length(strArray[10])-pos(':',strArray[10]));
    
         Result.Radio_type := copy(strArray[11], pos(':',strArray[11])+2,length(strArray[11])-pos(':',strArray[11]));
         Result.Authentication := copy(strArray[12], pos(':',strArray[12])+2,length(strArray[12])-pos(':',strArray[12]));
         Result.Cipher := copy(strArray[13], pos(':',strArray[13])+2,length(strArray[13])-pos(':',strArray[13]));
         Result.Connection_mode := copy(strArray[14], pos(':',strArray[14])+2,length(strArray[14])-pos(':',strArray[14]));
    
         Result.Channel := strtoint(copy(strArray[15], pos(':',strArray[15])+2,length(strArray[15])-pos(':',strArray[15])));
         Result.Receive_rate := strtoint(copy(strArray[16], pos(':',strArray[16])+2,length(strArray[16])-pos(':',strArray[16])));
         Result.Transmit_rate := strtoint(copy(strArray[17], pos(':',strArray[17])+2,length(strArray[17])-pos(':',strArray[17])));
         Result.Signal := strtoint(copy(strArray[18], pos(':',strArray[18])+2,pos('%',strArray[18])-pos(':',strArray[18])-2));
         Result.Profile := copy(strArray[19], pos(':',strArray[19])+2,length(strArray[19])-pos(':',strArray[19]));
        end;
       end;
    
    end;
    
    function TWifiObj.Connect(aSSID: string): boolean;
    var PAram: string;
    i:integer;
    
    begin
    result:=false;
    if wifilist.count = 0 then exit;
    
    i:=0;
    while (i<wifilist.count)and (aSSID<>Wifilist[i].SSID) do i:=i+1;
    if i=wifilist.count then exit;
    
    param:='wlan connect ssid= '+ wifilist[i-1].SSID +
           ' name= '+wifilist[i-1].Profile;
    result:=ShellExecute(0, nil, 'netsh.exe',Pchar(Param), nil, SW_HIDE) =0 ;
    end;
    
    function TWifiObj.Connect2(aSSID: string): boolean;
    const
    WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES =$00000001;
    var
      hClient              : THandle;
      dwVersion            : DWORD;
      ResultInt            : DWORD;
      pInterface           : Pndu_WLAN_INTERFACE_INFO_LIST;
      i                    : Integer;
      j                    : Integer;
      pAvailableNetworkList: Pndu_WLAN_AVAILABLE_NETWORK_LIST;
      pInterfaceGuid       : PGUID;
      NetworkFound         : Boolean;
      connectionParams     : Pndu_WLAN_CONNECTION_PARAMETERS;
      infoForSSID          : Pndu_DOT11_SSID;
    begin
      ResultInt:=WlanOpenHandle(1, nil, @dwVersion, @hClient);
    
      if  ResultInt<> ERROR_SUCCESS then
      begin
         WriteLn('Error Open CLient'+IntToStr(ResultInt));
         Exit;
      end;
    
      ResultInt:=WlanEnumInterfaces(hClient, nil, @pInterface);
      if  ResultInt<> ERROR_SUCCESS then
      begin
         WriteLn('Error Enum Interfaces '+IntToStr(ResultInt));
         exit;
      end;
    
    
      i:=0;
      NetWorkFound:=false;
      while (i<pInterface^.dwNumberOfItems) and not NetWorkFound do
      begin
       pInterfaceGuid:= @pInterface^.InterfaceInfo[pInterface^.dwIndex].InterfaceGuid;
       ResultInt:=WlanGetAvailableNetworkList(hClient,pInterfaceGuid,WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES,nil,pAvailableNetworkList);
       if  ResultInt<> ERROR_SUCCESS then
       begin
        writeln('Error WlanGetAvailableNetworkList '+IntToStr(ResultInt));
        Exit;
       end;
    
       j:=0;
       while (j<pAvailableNetworkList^.dwNumberOfItems)and not NetWorkFound do
       Begin
        if aSSID = PAnsiChar(@pAvailableNetworkList^.Network[j].dot11Ssid.ucSSID) then
        begin
         connectionParams.wlanConnectionMode := wlan_connection_mode_discovery_unsecure;
         connectionParams.strProfile := Nil;
         Move(aSSID[1], infoForSSID.ucSSID, Length(aSSID));
         infoForSSID.uSSIDLength := length(aSSID);
    		 connectionParams.pDot11Ssid := &infoForSSID;
    		 connectionParams.pDesiredBssidList := nil;
    		 connectionParams.dot11BssType := dot11_BSS_type_independent;
    		 connectionParams.dwFlags := NDU_WLAN_CONNECTION_ADHOC_JOIN_ONLY;
    
         ResultInt := WlanConnect(hClient, pInterfaceGuid, @connectionParams, Nil);
        end;
    
        j:=j+1;
       End;
       i:=i+1;
      end;
    
    WlanCloseHandle(hClient, nil);
    
    
    end;
    
    constructor TWifiObj.Create;
    begin
    WifiList:=TList<TWifiInfo>.Create;
    GetWifiList;
    GetConnectionInfo();
    end;
    
    destructor TWifiObj.Destroy;
    begin
      WifiList.Free;
      inherited;
    end;
    
    procedure TWifiObj.GetWifiList;
    const
    WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES =$00000001;
    var
      hClient              : THandle;
      dwVersion            : DWORD;
      ResultInt            : DWORD;
      pInterface           : Pndu_WLAN_INTERFACE_INFO_LIST;
      i                    : Integer;
      j                    : Integer;
      pAvailableNetworkList: Pndu_WLAN_AVAILABLE_NETWORK_LIST;
      pInterfaceGuid       : PGUID;
      TempWifiInfo         : TwifiInfo;
    begin
      FAdapter:=true;
      ResultInt:=WlanOpenHandle(1, nil, @dwVersion, @hClient);
    
      if  ResultInt<> ERROR_SUCCESS then
      begin
         WriteLn('Error Open CLient'+IntToStr(ResultInt));
         Exit;
      end;
    
      ResultInt:=WlanEnumInterfaces(hClient, nil, @pInterface);
      if  ResultInt<> ERROR_SUCCESS then
      begin
         WriteLn('Error Enum Interfaces '+IntToStr(ResultInt));
         exit;
      end;
    
      for i := 0 to pInterface^.dwNumberOfItems - 1 do
      begin
       pInterfaceGuid:= @pInterface^.InterfaceInfo[pInterface^.dwIndex].InterfaceGuid;
       ResultInt:=WlanGetAvailableNetworkList(hClient,pInterfaceGuid,WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES,nil,pAvailableNetworkList);
       if  ResultInt<> ERROR_SUCCESS then
       begin
    //    writeln('Error WlanGetAvailableNetworkList '+IntToStr(ResultInt));
        FAdapter:=false;
        Exit;
       end;
    
       for j := 0 to pAvailableNetworkList^.dwNumberOfItems - 1 do
       Begin
        TempWifiInfo.SSID :=PAnsiChar(@pAvailableNetworkList^.Network[j].dot11Ssid.ucSSID);
        TempWifiInfo.Profile :=pAvailableNetworkList^.Network[j].strProfileName;
        TempWifiInfo.Connectable :=pAvailableNetworkList^.Network[j].bNetworkConnectable;
        WifiList.Add(TempWifiInfo);
       End;
      end;
    
    WlanCloseHandle(hClient, nil);
    
    end;
    end.

  2. #2
    hierbij mijn code (let op de functie connect2 werkt dus nog niet)
    Met het risico dat ik lui lijk, maar zou je misschien willen omschrijven wat er dan niet werkt, zodat ik niet zelf uit hoef te zoeken wat de vraag is voordat ik die eventueel beantwoord?
    1+1=b

  3. #3
    Het stuk waar ik niet uit kom heet betrekking op de functie Wlanconnect (in de routine Connect2)
    Bij het toekennen van de waardes de ConnectionParams structure krijg ik een AV
    Code:
         connectionParams.wlanConnectionMode := wlan_connection_mode_discovery_unsecure;  //Hier krijg ik de AV als ik deze regel uitcommentariëer krijg ik de AV op de volgende regel
         connectionParams.strProfile := Nil;
         Move(aSSID[1], infoForSSID.ucSSID, Length(aSSID));
         infoForSSID.uSSIDLength := length(aSSID);
    		 connectionParams.pDot11Ssid := &infoForSSID;
    		 connectionParams.pDesiredBssidList := nil;
    		 connectionParams.dot11BssType := dot11_BSS_type_independent;
    		 connectionParams.dwFlags := NDU_WLAN_CONNECTION_ADHOC_JOIN_ONLY;
    
         ResultInt := WlanConnect(hClient, pInterfaceGuid, @connectionParams, Nil);

  4. #4
    connectionParams is van het type Pndu_WLAN_CONNECTION_PARAMETERS.
    Die P in het begin staat in 99% van de gevallen voor het feit dat het een pointer type is.
    En je kunt dat ook zien.
    Delphi Code:
    1. type
    2.   Pndu_WLAN_CONNECTION_PARAMETERS = ^Tndu_WLAN_CONNECTION_PARAMETERS;
    3.  
    4.   Tndu_WLAN_CONNECTION_PARAMETERS = record
    5.     wlanConnectionMode: Tndu_WLAN_CONNECTION_MODE;
    6.     strProfile: LPCTSTR;
    7.     pDot11Ssid: Pndu_DOT11_SSID;
    8.     pDesiredBssidList: Pndu_DOT11_BSSID_LIST;
    9.     dot11BssType: Tndu_DOT11_BSS_TYPE;
    10.     dwFlags: DWORD;
    11.   end;

    Je zult dus eerst die connectionParams aan moeten maken (net als Create bij een object).

    Maar wellicht is het makkelijker om gewoon van de definitie direct te verwijzen naar het record en niet een pointer. Dan hoef je niets te creeren.
    Delphi Code:
    1. var
    2.   connectionParams     : Tndu_WLAN_CONNECTION_PARAMETERS;

  5. #5
    Thanks voor de update, zoals ik al zij mijn kennis van pointers is erg roestig
    Ik heb nu idd mijn connectionParams als Tndu_WLAN_CONNECTION_PARAMETERS gedefinieerd.
    de tweede stap is dan het vullen van de infoForSSID parameter.
    Hiervoor heb ik de zelfde truuk gebruikt echter de connectionParams.pDot11Ssid verwacht een Pndu_DOT11_SSID
    Kortom hiervoor moet ik dan eerst een infoForSSID aanmaken, de vraag is hoe doe ik dat

    Alvast bedankt

  6. #6
    Wat doet de & eigenlijk in deze regel.
    Nu gebruik al zo lang Delphi maar dat heb ik nog nooit zo gedaan.

    Delphi Code:
    1. connectionParams.pDot11Ssid := &infoForSSID;

    Als pDot11Ssid een pointer is naar een Tndu_DOT11_SSID dan kun je inderdaad een Pndu_DOT11_SSID aanmaken.

    Maar je kunt het ook gewoon zo doen:
    Delphi Code:
    1. var
    2.   infoForSSID          : Tndu_DOT11_SSID;
    3. ...
    4.   connectionParams.pDot11Ssid := @infoForSSID;

  7. #7
    Ok de & was idd een foutje van mij ;-)
    Inmiddels runt de code wel (geen AV's meer) maar de regel ResultInt := WlanConnect(hClient, pInterfaceGuid, @connectionParams, Nil); doet niks.
    Kortom wel een stap verder maar nog niet waar we zijn moeten.
    Heb de connectie parameters wan aangepast maar krijg nogsteeds error 97 terug (Invalid arguments)

    Code:
         Move(aSSID[1], infoForSSID.ucSSID, Length(aSSID));
         infoForSSID.uSSIDLength := length(aSSID);
         connectionParams.wlanConnectionMode := wlan_connection_mode_profile;
         connectionParams.strProfile := pAvailableNetworkList^.Network[j].strProfileName;
    		 connectionParams.pDot11Ssid := @infoForSSID;
    		 connectionParams.pDesiredBssidList := nil;
    		 connectionParams.dot11BssType := pAvailableNetworkList^.Network[i].dot11BssType;
    		 connectionParams.dwFlags := 0;
         ResultInt := WlanConnect(hClient, pInterfaceGuid, @connectionParams, Nil);
         networkfound:=true;

  8. #8
    Ik kreeg een error 87 (invalid parameters).
    (maar aangezien je geen werkend voorbeeld hebt gegeven weet ik niet of ik het goed doe).

    Maar wat betreft die infoForSSID... waarom zou je die opnieuw zelf aanmaken.
    Je hebt een loop over pAvailableNetworkList^.Network waar PRECIES dat record dot11Ssid voor je WiFi netwerk al instaat.
    Dus je hoeft hem helemaal zelf toe te kennen.
    Je kunt gewoon een pointer naar die pAvailableNetworkList^.Network[j].dot11Ssid geven.

    Delphi Code:
    1. // Move(aSSID[1], infoForSSID.ucSSID, length(aSSID));
    2. // infoForSSID.uSSIDLength := length(aSSID);
    3. // connectionParams.pDot11Ssid := @infoForSSID;
    4. connectionParams.pDot11Ssid := @pAvailableNetworkList^.Network[j].dot11Ssid;

    Hier krijg ik dan een ResultInt van 0.
    (maar geen verbinding maar ik geef ook nergens een wachtwoord op.)

  9. #9
    Dit werkt overigens bij mij:

    Delphi Code:
    1. connectionParams.wlanConnectionMode := wlan_connection_mode_profile;
    2. // connectionParams.wlanConnectionMode := wlan_connection_mode_discovery_unsecure;
    3. // LET OP. Mode_profile werkt alleen met een geldige profile.
    4. // EN DIT HOEFT NIET DEZELFDE NAAM TE HEBBEN ALS DE SSID
    5.  
    6. // connectionParams.strProfile := @pAvailableNetworkList^.Network[j].strProfileName;
    7. connectionParams.strProfile := pChar('dd-wrt 2'); // ik moest hier ' 2' achter zetten
    8.  
    9. connectionParams.pDot11Ssid := @pAvailableNetworkList^.Network[j].dot11Ssid;
    10. connectionParams.pDesiredBssidList := nil;
    11. connectionParams.dot11BssType := pAvailableNetworkList^.Network[j].dot11BssType; // geen i !!
    12. connectionParams.dwFlags := 0;
    13. ResultInt := WlanConnect(hClient, pInterfaceGuid, @connectionParams, Nil);
    14. NetworkFound := True;

    Mijn SSID is dd-wrt maar onder Windows heet ie dd-wrt 2.
    Ik moest als profile dus ook dd-wrt 2 opgeven en voor SSID dd-wrt.

    Je kunt er dus niet vanuit gaan dat deze altijd identiek zijn.

    (tevens stond er nog een tikfoutje voor index i bij dot11BssType.)

    Bovenstaand snippet maakte bij mij automatisch verbinding.

  10. #10
    Yess het werkt.

    Bedankt voor de tips

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •