WinBatch® Technical Support Forum

All Things WinBatch => WinBatch => Topic started by: airways on September 04, 2013, 02:36:12 PM

Title: Get name of active wireless network?
Post by: airways on September 04, 2013, 02:36:12 PM
Does anyone know of a way to get the name of the active access point / wifi network? I'd like to have a script that triggers on wake of my laptop and adjusts my DNS settings based on which network is discovered and connected to by Windows.
Title: Re: Get name of active wireless network?
Post by: td on September 06, 2013, 07:31:57 AM
I don't believe the WIFI WMI classes are supported on Windows 7 and newer version of Windows.  I haven't tried it so I can't guarantee success but there is a .Net class the wraps the Windows Native WIFI API and if properly written, should work with WinBatch's dotNet system.  It can be found here http://managedwifi.codeplex.com/ (http://managedwifi.codeplex.com/).  You could also take a look at using the WinBatch 'DllCall' function to directly access the Native WIFI API. The API documentation can be found here http://msdn.microsoft.com/en-us/library/windows/desktop/ms706556(v=vs.85).aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms706556(v=vs.85).aspx)
Title: Re: Get name of active wireless network?
Post by: stanl on September 09, 2013, 02:27:20 PM
Quote from: td on September 06, 2013, 07:31:57 AM
but there is a .Net class the wraps the Windows Native WIFI API and if properly written, should work with WinBatch's dotNet system.

I downloaded the .zip, and time permitting will try to code. I'm curious 'cuz I have a Verizon JetPack and our home wifi and would be curious to see difference in signal strength when both are active.
Title: Re: Get name of active wireless network?
Post by: Don Kelloway on September 09, 2013, 07:45:48 PM
Quote from: airways on September 04, 2013, 02:36:12 PM
Does anyone know of a way to get the name of the active access point / wifi network? I'd like to have a script that triggers on wake of my laptop and adjusts my DNS settings based on which network is discovered and connected to by Windows.

Not sure if this may help, but I did something similar in the past except I wrote a WB script to change the proxy server settings if my laptop was connected to the network at my place of employment.  And if the laptop wasn't connected to the corporate network, then no proxy server was used.  I achieved this by simply looking at the IP address that was assigned to my laptop upon connecting to the WiFi AP.  If it was within a specific subnet, then the proxy server settings were enabled to use a specific IP address.

As an alternative to this have you given any thought to using the netsh command?  For example if you open a DOS prompt and type netsh wlan show interface, then press Enter, you'll be informed what AP you are connected to
Title: Re: Get name of active wireless network?
Post by: td on September 10, 2013, 08:31:45 AM
The idea of creating a Native WIFI WIL extender has been kicked around a bit.  We have been more or less expecting MSFT to offer something in the FCL (dotNet Framework) so we haven't taken the plunge. I did do some prototyping with WinBatch to familiarize myself with the API. My apologies in advance for this script as it contains a lot of magic numbers and minimal documentation or error checking, but it does seem to kinda work on a Windows 8 notebook computer.     
Code (winbatch) Select

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Ugly bit of scripting with lots of magic numbers using the Native WIFI API.
;;;; http://msdn.microsoft.com/en-us/library/windows/desktop/ms706274(v=vs.85).aspx
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Returns a string containing the contents
;; of the input memory location.  Memory
;; location must contain ANSI character data.
;; but memory location string does not need to
;; be null terminated.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#DefineFunction MemToStr(_pMem, _nLen)
   hTemp = BinaryAlloc(_nLen+1)
   for x = 0 to _nLen - 1
      binaryPoke( hTemp, x, IntControl(32,_pMem+x, "BYTE", 0,0) )
   next
   strRet = BinaryPeekStr(hTemp, 0, _nLen)
   BinaryFree(hTemp)
   return strRet
#EndFunction

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Get the current WiFi connection SSID and radio signal strength.

lSsids = "<No Connections>" ; or is that El Cid?

while 1
   nRetCode = 0
   hWlanApi = DllLoad(DirWindows(1):"wlanapi.dll")
   
   hNetVer = BinaryAlloc(4)
   BinaryEODSet(hNetVer, 4)
   hClient = BinaryAlloc(4)
   BinaryEODSet(hClient, 4)
   
   ; Need a client handle for almost every function.
   nRetCode = DllCall(hWlanApi, long:"WlanOpenHandle", long:2, long:0, lpBinary:hNetVer, lpBinary:hClient)
   if nRetcode then break ; Error

   hClientHandle = BinaryPeek4(hClient, 0)
   hpLfList = BinaryAlloc(4)
   BinaryEODSet(hpLfList, 4)
   nRetCode = DllCall(hWlanApi, long:"WlanEnumInterfaces",long:hClientHandle, long:0, lpBinary:hpLfList)
   if nRetCode then break ; Error

   ; Number of interfaces is first structure member.
   pLfList = BinaryPeek4(hpLfList, 0)
   dwNumberOfItems = IntControl(32, pLfList, "LONG", 0, 0)
   
   ; Find a connected WIFI interface
   pInfoArray     = pLfList + 8  ; Pointer to array of infos is at this offset in the structure
   nInfoSize      = 16 + (256*2) + 4 ; Size of each structure in array.
   nisStateOffset = 16 + (256*2)       ; Offset of state member.
   isState        = 0
   for nIndex = 0 to dwNumberOfItems
      isState = IntControl(32,pInfoArray+nisStateOffset, "LONG", 0, 0)
      if isState == 1 then break ; Found one! - 1 means connected
      pInfoArray = pInfoArray + nInfoSize
   next

   ; Get the ssid as stored in the Bss list.
   if isState == 1
      lSsids = ""
      hpBssList = BinaryAlloc(4)
      if !hpBssList then break
      BinaryEODSet(hpBssList, 4)

      nRetCode = DllCall(hWlanApi, long:"WlanGetNetworkBssList",long:hClientHandle, long:pInfoArray, long:0, long:0, long:0, long:0, lpbinary:hpBssList)
      if nRetCode then break ; Error
   
      ;  Get a SSID from a BSS structure
      pBssList  = BinaryPeek4(hpBssList, 0)
      nEntries  = IntControl(32,pBssList+4, "LONG", 0, 0)  ; Number of elements in bss array here.
      pBssEntry = pBssList+8 ; Offset of bss array in list structure.
      for nIndex = 0 to  nEntries -1
   
         ; The length in chars of the SSID.
         nSsidLen = IntControl(32,pBssEntry, "LONG", 0, 0)

         ; Offset location of the SSID member.
         pSsid = pBssEntry + 4

         ; Get the SSID as a string.
         strSsid = MemToStr(pSsid, nSsidLen)

         ; lRssi stucture member contains the signal strength in dBm
         nSigStren = IntControl(32,pBssEntry+60, "LONG", 0,0) ; Strength at offset 60
         
         ; Add to our output.
         lSsids = ItemInsert( "SSID: ":strSsid:@tab:"Signal Strength: ":nSigStren:" (dBm)", -1, lSsids, @cr)
         
         ; Move to next entry in array.
         pBssEntry = pBssEntry + 140 ; 2 extra bytes added because of dot11Bssid member struct alignment.
      Next

   endif
   break ; out of while
endwhile

; Clean up as best we can.
if IsDefined(hTemp) then if hTemp then BinaryFree( hTemp)
if IsDefined(hpBssList) then if hpBssList then then BinaryFree(hpBssList)
if IsDefined(hLfList) then if hLfList then  BinaryFree(hLfList)
if IsDefined(hClient) then if hClient then  BinaryFree(hClient)
if IsDefined(hNetVer) then if hNetVer then BinaryFree(hNetVer)

if IsDefined(pLfList) then if pLfList then DllCall(hWlanApi, void:"WlanFreeMemory",long:pLfList)
if IsDefined(pBssList) then if pBssList then DllCall(hWlanApi, void:"WlanFreeMemory",long:pBssList)

if IsDefined(hClientHandle)
   if hClientHandle then nRetCode = DllCall(hWlanApi, long:"WlanCloseHandle", long:hClientHandle, long:0)
endif
DllFree(hWlanApi)

;  Emtpy test would mean no WIFI connections.
if !nRetCode then Message("WIFI Connection Info",lSsids)
else Message("Native WIFI API Error", nRetCode)
exit
Title: Re: Get name of active wireless network?
Post by: stanl on September 10, 2013, 02:48:31 PM
Nice.

Back to the .NET option.  The ManagedWifi.dll (once built in Studio) cannot be added to the GAC [at least I couldn't] as the assembly does not have a strong name.  I think I went through this before, using the sn .NET utility; but would make a nice tutorial.
Title: Re: Get name of active wireless network?
Post by: stanl on September 11, 2013, 04:01:22 AM
I know this may take the thread off-topic, but Tony did suggest using the ,NET dll.  Well, as I said I built the project with VS 2012 but did not load into the GAC. I used the article below to create a strong name for the dll

http://sujeetji.wordpress.com/2011/01/09/assign-change-strong-name-to-existing-assembly/ (http://sujeetji.wordpress.com/2011/01/09/assign-change-strong-name-to-existing-assembly/)

and everything worked fine. I created the snk key, I created the .il file, but when executing the final ilasm I got the attached error. This, of course is not a WB issue, per se... but it would help to integrate WB with .NET a little more if the error could be explained.
Title: Re: Get name of active wireless network?
Post by: td on September 11, 2013, 08:15:02 AM
You do realize that you can write a relatively simple WinBatch script to compile c# code and generate an output assembly and that you don't need to place your newly minted assembly into the GAC to use it in a WinBatch script?
Title: Re: Get name of active wireless network?
Post by: Deana on September 11, 2013, 12:36:50 PM
Further investigation into ManagedWifi assembly, showed that many of the methods require output parameters. ( see http://msdn.microsoft.com/en-us/library/windows/desktop/ms706759(v=vs.85).aspx (http://msdn.microsoft.com/en-us/library/windows/desktop/ms706759(v=vs.85).aspx) )Unfortunately WinBatch does not support 'out' parameters.  Method with out parameters can still be called but 'out' parameter values are not modified on the method's return.

The wLanOpenHandle method that is used to get the client handle ( that mostother methods depend on). That clienthandle is returned as an OUT parameter. Therefore ObjectClrNew will not be able to handle it.

For now you are limited to using NativeWifi API from WinBatch.
Title: Re: Get name of active wireless network?
Post by: td on September 11, 2013, 01:11:02 PM
While the interop Native WIFI cover methods require out parameters, the WlanClient class properties do not. This means that, in theory anyway, the assembly could be used in WinBatch  to obtain WIFI connection information because you don't need to use the interop methods.
Title: Re: Get name of active wireless network?
Post by: td on September 12, 2013, 08:15:29 AM
This is not particularly useful but it does demonstrate how to get the signal strength.  For some reason the type resolver will not allow WinBatch to call the parameterless version of the GetNetworkBssList method of the WlanInterface class and that member's return array is where the interesting information can be found.  Since we have the cs source, that problem could be addressed with a little code tweaking.  Anyway, here is a simple example that obtains the WIFI signal strength of the current connection.

Code (winbatch) Select

;; Don't try this on an XP system!
ObjectClrOption("version", "v2.0.50727")

; Set to wherever your ManagedWifi assembly resides.
ObjectClrOption("appbase", "C:\Projects\DotNet\Test\managedwifi-1.1\bin\Release")
ObjectClrOption("use", "ManagedWifi")
WlanClient = ObjectClrNew("NativeWifi.WlanClient")

; Get the available WIFI network interfaces
WlanIfaces = WLanClient.Interfaces
ForEach WlanIface in WlanIfaces
   
   ;  1 means connected.
   if WlanIface.InterfaceState == 1
      pause(WlanIface.InterfaceDescription,  "Signal Strength: ":WlanIface.RSSI)
   endif
next
Title: Re: Get name of active wireless network?
Post by: stanl on September 13, 2013, 06:56:48 AM
Tried it. worked fine. I then created the assembly with csc rather than VS and tested. Totally zoned out about not needed a GAC entry, though I assume there are benefits to that.
Title: Re: Get name of active wireless network?
Post by: td on September 13, 2013, 07:24:37 AM
For the curious, here is an example of how to create the ManagedWif.dll assembly on the fly using a WinBatch script and the FCL's c# compiler.

Code (winbatch) Select

ObjectClrOption("version", "v2.0.50727")

strAssembly =  DirScript():"ManagedWifi.dll"
if !FileExist(strAssembly)
   
   ;; Compile assembly from source files.
   ObjectClrOption("use","System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
   
   objCSharp = ObjectClrNew('Microsoft.CSharp.CSharpCodeProvider')
   objParams = ObjectClrNew('System.CodeDom.Compiler.CompilerParameters')
   objParams.ReferencedAssemblies.Add( "System.dll" )
   objParams.OutputAssembly  = strAssembly
   objParams.CompilerOptions = "/optimize"
   aSource = ArrDimension(3)
   aSource[0] = "C:\Projects\DotNet\managedwifi-1.1\Interop.cs"
   aSource[1] = "C:\Projects\DotNet\managedwifi-1.1\WlanApi.cs"
   aSource[2] = "C:\Projects\DotNet\managedwifi-1.1\Properties\AssemblyInfo.cs"
   objResult = objCSharp.CompileAssemblyFromFile(objParams, BSTR:aSource)
   
   ;; Check for compiler errors.
   if objResult.Errors.Count > 0
       foreach ce in objResult.Errors
         Pause("Error", ce.ToString())
      next
      exit
    endif
endif
exit
Title: Re: Get name of active wireless network?
Post by: Deana on September 13, 2013, 08:07:44 AM
Quote from: td on September 13, 2013, 07:24:37 AM
For the curious, here is an example of how to create the ManagedWif.dll assembly on the fly using a WinBatch script and the FCL's c# compiler.

Code (winbatch) Select

ObjectClrOption("version", "v2.0.50727")

strAssembly =  DirScript():"ManagedWifi.dll"
if !FileExist(strAssembly)
   
   ;; Compile assembly from source files.
   ObjectClrOption("use","System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
   
   objCSharp = ObjectClrNew('Microsoft.CSharp.CSharpCodeProvider')
   objParams = ObjectClrNew('System.CodeDom.Compiler.CompilerParameters')
   objParams.ReferencedAssemblies.Add( "System.dll" )
   objParams.OutputAssembly  = strAssembly
   objParams.CompilerOptions = "/optimize"
   aSource = ArrDimension(3)
   aSource[0] = "C:\Projects\DotNet\managedwifi-1.1\Interop.cs"
   aSource[1] = "C:\Projects\DotNet\managedwifi-1.1\WlanApi.cs"
   aSource[2] = "C:\Projects\DotNet\managedwifi-1.1\Properties\AssemblyInfo.cs"
   objResult = objCSharp.CompileAssemblyFromFile(objParams, BSTR:aSource)
   
   ;; Check for compiler errors.
   if objResult.Errors.Count > 0
       foreach ce in objResult.Errors
         Pause("Error", ce.ToString())
      next
      exit
    endif
endif
exit


Good Stuff Tony. I posted this in the tech database: http://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/tsleft.web+WinBatch/dotNet/Third~Party~Components+Create~an~Assembly~DLL~On~The~Fly.txt
Title: Re: Get name of active wireless network?
Post by: stanl on September 14, 2013, 11:01:59 AM
Quote from: td on September 13, 2013, 07:24:37 AM
For the curious, here is an example of how to create the ManagedWif.dll assembly on the fly

good stuff. Hope it gets more users into 2013 features.
Title: Re: Get name of active wireless network?
Post by: stanl on September 15, 2013, 09:29:03 AM
Still good stuff but when I changed the script to reflect where my .cs files were I got this error [attached]
Title: Re: Get name of active wireless network?
Post by: td on September 16, 2013, 07:46:21 AM
I guess you need to figure out why part of your path has gone missing.
Title: Re: Get name of active wireless network?
Post by: stanl on September 16, 2013, 10:05:57 AM
Quote from: td on September 16, 2013, 07:46:21 AM
I guess you need to figure out why part of your path has gone missing.
Yeah, was wondering if maybe the .NET assembly was looking for Project or Santa or whatever in the path.
Title: Re: Get name of active wireless network?
Post by: td on September 16, 2013, 11:01:52 AM
I have use the FCL's cs compiler multiple times on Windows XP, 7, and 8 and can't say that I have ever encountered that error.  As a sanity check you might want to consider using FileExist on the exact same filepath/name you pass in the source file array before you do the assignment. 
Title: Re: Get name of active wireless network?
Post by: stanl on September 17, 2013, 04:58:26 PM
All fixed. The file and path were correct. I have had problems with Windows updates of late (especially w/ Office 2013). I would get messages like 29 updates available, then 29 updates already installed, then installing updates, then locked up.
Once that latest debacle was handled the script worked as expected.