Vista Wi-Fi Signal Strength

** Works only with Vista **

I've been trying to make an object to display Wi-Fi signal strength in DX, on a Vista machine.  There are several Widgets and objects in the WinCustomize library but none seem to work on Vista.  I've been doing some research on the subject and can't find much solid info, other than recurring comments that the standard methods(using VBscript) that work on XP don't work on Vista. 

I believe the MSNdis_80211_ReceivedSignalStrengt WMI Class (and other MSNdis_80211) classes don't play nice on Vista.  This is the likely reason NetStumbler won't run on Vista.

A developer at: http://www.codeproject.com/KB/gadgets/WifiScanner.aspx used the command line info below to get SSID, strength, and other info.  This command is normally run from the command line, but he runs it from code and he redirects the output to a text file and parses the info to get what he needs.  I think this approach could be done with DX but I don't have the DX brainpower to make DX execute the command and redirect it to a text file.  The parsing I could figure out.

netsh wlan show networks mode=bssi

I did run netsh wlan show networks mode=bssi > c:\text.txt from the command line and was able to redierct it to a text file, but that's as far as I can get and need to do it from code without a command window opening.

Any suggestions would be appreciated.

Thanks!

13,186 views 19 replies
Reply #1 Top

Figured it out!

Set oShell  = CreateObject("WScript.shell")
strCommand = "cmd /c netsh wlan show networks mode=bssid > c:\testing.txt"
oShell.run strCommand, 0, True

Won't be long and I'll have a working Wi-Fi meter that runs in Vista!

Reply #2 Top

I just submitted a working Vista Wi-Fi meter.  Pending moderation, it should be available in a couple of days.  Here is the script if anyone is interested:

 

Code: vbscript
  1. Const ForReading = 1, ForWriting = 2, ForAppending = 8
  2. 'Declare the file system object
  3. Dim fso, f, Msg
  4. Dim signal
  5. Dim SSID
  6. Set fso = CreateObject("Scripting.FileSystemObject")
  7. '************************************************************
  8. 'Called when the script is executed
  9. Sub Object_OnScriptEnter
  10. Dim UpdateInterval
  11. UpdateInterval = 60000 'Update this value to chabge the update interval
  12.  
  13.   Update
  14.   Object.SetTimer 800 , UpdateInterval
  15.  
  16. End Sub
  17.  
  18. Sub Object_OnTimer800 
  19.   Update
  20. End Sub
  21.  
  22. 'Called when the script is terminated
  23. Sub Object_OnScriptExit
  24.    Object.KillTimer 800
  25. End Sub
  26.  
  27. 'Called on mouse over object
  28. Sub Object_OnMouseEnter
  29.   DesktopX.Object("WIFI Signal Text3").visible=True
  30.   DesktopX.Object("WIFI Signal Text3").text = "SSID:" & SSID
  31. End Sub
  32.  
  33. 'Called when mouse leaves object
  34. Sub Object_OnMouseLeave
  35.   DesktopX.Object("WIFI Signal Text3").visible=False
  36.   DesktopX.Object("WIFI Signal Text3").text = "SSID:" & SSID
  37. End Sub
  38.  
  39. 'Called when L-click is pressed
  40. Function Object_OnLButtonDown(x,y)
  41.    Update
  42. End Function
  43.  
  44. Sub Update
  45.  textfile = "c:\wifiinfo.txt"
  46.  tempstring=""
  47.  Set oShell  = CreateObject("WScript.shell")
  48.   strCommand = "cmd /c netsh wlan show networks mode=bssid > c:\wifiinfo.txt"
  49.   oShell.run strCommand, 0, True  'runs the command and suppresses the command window
  50.  
  51.  
  52.  'Check if file exists
  53.  If fso.FileExists(textfile) Then
  54.   Set f = fso.OpenTextFile(textfile, ForReading)
  55.   While Not f.AtEndOfStream        
  56.    getline = f.ReadLine
  57.    fileinfo = fileinfo & getline & vbcrlf
  58.   Wend
  59.   f.Close
  60.  Else
  61.   msgbox "File does not exist"
  62.  End If
  63.  
  64.  'file loaded into fileinfo
  65.  
  66.  '**** parse out signal strength & SSID ****
  67.  
  68.  'find the location of the 1st occurence of "%"
  69.  pos=InStr(fileinfo,"%")
  70.  'move left 3 places and get 3 characters - this is the signal strength
  71.  signal=Mid(fileinfo,(pos-3),3)
  72.  signal=LTrim(signal)
  73.  
  74.  'find SSID and strip stuff from left and right
  75.  pos=InStr(fileinfo,"Network type")  'this is the next thing after the SSID name - find the position
  76.  tempstring=Left(fileinfo,pos-1) 'strip everything after and including Network Type
  77.  tempstring=RTrim(tempstring)
  78.  tempstring=Left(tempstring,(Len(tempstring)-2))  'this strips off the newline characters from the right
  79.  
  80.  pos=InStr(fileinfo,"SSID1 :") 'find the location of this in the remaining string
  81.  tempstring=Right(tempstring,(pos+7))  'then move over 7 spaces and strip everything from the left
  82.  SSID = tempstring   'only the SSID with no spaces to the left or right remains
  83.  
  84.  ' **** parsing is done: netsh can return a string with data from more than one network,          ****
  85.  ' **** but parsing is done from the start of the string to find the first occurence of"%", which ****
  86.  ' **** will be the currently active SSID and signal strength                                     ****
  87.  
  88.  Select Case signal
  89.     Case "100","99","98","97","96","95","94","93","92","91","90","89","88"
  90.           object.State="6"
  91.           DesktopX.Object("WIFI Status reflection").state ="6"
  92.     Case "87","86","85","84","83","82","81","80","79","78","77","76","75","74","73"
  93.           object.State="5"
  94.           DesktopX.Object("WIFI Status reflection").state ="5"
  95.     Case "72","71","70","69","68","67","66","65","64","63","62","61","60","59","58","57"
  96.         object.State="4"
  97.         DesktopX.Object("WIFI Status reflection").state ="4"
  98.     Case "56","55","54","53","52","51","50","49","48","47","46","45","44","43","42"
  99.         object.State="3" 
  100.         DesktopX.Object("WIFI Status reflection").state ="3"       
  101.     Case "41","40","39","38","37","36","35","34","33","32","31","30","29","28","27"
  102.         object.State="2" 
  103.         DesktopX.Object("WIFI Status reflection").state ="2"
  104.     Case "26","25","24","23","22","21","20","19","18","17","16","15","14","13","12","11"
  105.         object.State="1" 
  106.         DesktopX.Object("WIFI Status reflection").state ="1"
  107.     Case "10","9","8","7","6","5","4","3","2","1","0"
  108.         object.State="1"
  109.         DesktopX.Object("WIFI Status reflection").state ="1"
  110.    
  111.     Case Else
  112.           object.State="No Signal"
  113.           DesktopX.Object("WIFI Status reflection").state ="No Signal"
  114.    
  115.  End Select
  116.  
  117.  
  118.  DesktopX.Object("WIFI Signal Text").text = signal &"%"
  119.   DesktopX.Object("WIFI Signal Text2").text = signal &"%"
  120.   DesktopX.Object("WIFI Signal Text3").visible=False
  121.   DesktopX.Object("WIFI Signal Text3").text = "SSID:" & SSID
  122.  
  123.  
  124. End Sub

Reply #3 Top

That is so cool Cap'n!

Can't wait to see it!

Reply #4 Top

Well, the first version isn't too fancy.  It's more of a proof of concept for me than anything else.  I plan to spruce it up with more user definable options, and fancier graphics.  I designed this version to fit on my DX built taskbar, so it's small and basic so it does not take up much space. 

 

Reply #5 Top

Does it work on XP too?

Reply #6 Top

It should.  It uses the standard netsh (Network Services Shell) command to do its business, which is included with XP. 

 

 

Reply #7 Top

Quoting Zubaz, reply 5
Does it work on XP too?

I will try to test it on my XP machine so I can give a definate answer.  The existing Wi-Fi meter objects in the Wincustomize library look like they work fine on XP(and are very nice) - based on the user comments.  I would have been content to use one of these, but I tried a long time to get them to work on Vista and after some research found out that the WMI calls used won't work, so that's why I made it.

Reply #8 Top

Just tested it on my XP machine.  Does NOT work on XP.  I geuss the netsh command has a little more functionality in Vista then in XP.  XP users will have to use one of the other existing wifi widgets, sorry.

Reply #9 Top

Going to update the description to indicate that?

Reply #10 Top

Hey CaptainBeaker!

A little bit of feedback:

  • creating a file at the root folder isn't really nice (plus you might not have the rights to do it anyway). It might be better to put that file in the temp directory. You can get it with the following script:

Code: vbscript
  1. Dim tempFolder Set WshShell = CreateObject("WScript.Shell") tempFolder = WshShell.ExpandEnvironmentStrings("%temp%")

  • you can probably save the whole file creation and use the Exec command on the WScript.Shell object. It returns a WshScriptExec object with access to the StdOut and StdErr channels (ie. no need to redirect output). Take a look at the WScript help, there are a few examples on how to use it.
  •  that big switch case is hurting my eyes XD . What's wrong with a few ifs and elses?
Reply #11 Top

Sorry for the garbled script (and the edit button is not working X( ).

Good job on the widget. Looking forward for a version using the canvas :-"

Reply #12 Top

Thanks for the suggestions.  I have done away with the select case and used your code to place the file in the user temp folder.

 

I'm still reading about WshScriptExec.  It would be nice to capture the output of netsh without having to mess with a file.  I did a quick test.  The Exec command seems to call up a command window briefly when executing the NETSH command.  I have to find a way to supress this command window or I'll be stuck with my method.

Reply #13 Top

Quoting Littleboy, reply 11
Looking forward for a version using the canvas

Me too!  However, I have to get Canvas working on my Vista machine(s) first.  I imported your .dxpack included in the latest build and still nothing.  I put one of my drawing scripts into a new object and started the script.  Got a (Null) error from my script on the following line:

Set ctx = canvas.getContext("2d")

The Canvas plug-in was added to the 'Additional Abilities' of the object

Reply #14 Top

Mmmh, not good. I'm going to add some logging to the next beta so we can track down that problem. There is an error when creating the cairo surface and context for some reason (and it's strange that it's not crashing, given that this part is done earlier and lacks some error checking... oops :| )

Reply #15 Top

Quoting Littleboy, reply 10
you can probably save the whole file creation and use the Exec command on the WScript.Shell object. It returns a WshScriptExec object with access to the StdOut and StdErr channels (ie. no need to redirect output). Take a look at the WScript help, there are a few examples on how to use it.
 that big switch case is hurting my eyes . What's wrong with a few ifs and elses?

I've been (partly) successful using Exec instead of Run and capturing the stdout  and putting the result into a variable.   The code bolw does exactly what I need it to do, but... It does not run under DX.  It runs from the desktop fine - suppresses the cmd window and puts stdout into a variable.  I don't think Wscript attributes are visible from within DX. I get object undefined errors wherever I have Wscript when I run the script from inside a Dx object.  Telling the object to use an external script (containing the code below) still results in the same errors.

However, I have found a better solution which still uses the Run command and does not use a file.  I had a revelation of sorts...Output from most command line functions can be directed to a file using ">", but starting with Server 2003, this same output can be directed to the Clipboard using "|clip" .

I've replaced all of the file saving and reading stuff with:

strCommand = "netsh wlan show networks mode=bssid |clip"

oShell.run strCommand, 0, True 

netshresults = System.Clipboard

In my code, I save the current clipboard contents into a temp variable before I put the netsh stuff into it, then read the clipboard into a variable so I can parse it up.  I then put the original contents of the clipboard back.

I'm currently testing everything right now and everything seems to be working.  I'll post the update tonight. 

Code: vbscript
  1. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">Set oShell = CreateObject("WScript.Shell")</span></span>
  2. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">' Make script run in Cscript so we can capture the std out of the Exec command.</span></span>
  3. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">' Must run in cscript because under wscript there is no way to suppress the command window</span></span>
  4. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">If Instr(1, WScript.FullName, "CScript", vbTextCompare) = 0 Then </span></span>
  5. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">   oShell.Run "cscript """ &amp; WScript.ScriptFullName &amp; """", 0, False </span></span>
  6. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">   WScript.Quit </span></span>
  7. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">End If</span></span>
  8. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;"></span></span>
  9. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">&lsquo; execute command here</span></span>
  10. <p class="MsoNormal">
  11. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;"></span></span>
  12. <span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">strCommand = "<strong>netsh wlan show networks mode=bssi</strong>"</span></span>
  13. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;"></span></span>
  14. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">set objShell = CreateObject("Wscript.Shell")</span></span>
  15. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">set objProc  = objShell.Exec(strCommand)</span></span>
  16. <span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">
  17. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">Do</span></span>
  18. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">   WScript.Sleep 100</span></span>
  19. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">Loop Until objProc.Status &lt;&gt; 0</span></span>
  20. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;"> </span></span><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">if objProc.ExitCode &lt;&gt; 0 then</span></span>
  21. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">   WScript.Echo "XXXXXX EXIT CODE: " &amp; objProc.ExitCode</span></span>
  22. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">   WScript.Echo "XXXXXX ERROR: " &amp; objProc.StdErr.ReadAll</span></span>
  23. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">end if</span></span>
  24. <p class="MsoNormal"><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;"> </span></span><span style="font-size: x-small; font-family: Arial;"><span style="font-size: 10pt; font-family: Arial;">netsh_output = objProc.StdOut.ReadAll</span></span>
  25. </span></span>

Reply #16 Top

You could add some code to see if they are running XP or Vista, then use the above code for Vista and this WMI Call for XP:

Function to get Windows Version:

Code: vbscript
  1. Function Get_OSVersion()&lt;br&gt;
  2.    strComputer = "."
  3.    Set objWMIService = GetObject("winmgmts:\\" &amp; strComputer &amp; "\root\CIMV2")
  4.     Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem",,48)
  5.    cnt = 0
  6.    For Each objItem In colItems
  7.       cnt = cnt + 1
  8.        Get_OSVersion =  objItem.Caption
  9.    Next
  10. End Function
  11.  
  12.  t = instr(1,UCase(Get_OSVersion),UCase("Vista"))
  13.  If t&gt; 0 Then
  14.    '---    VISTA CODE HERE ---
  15.  Else
  16.   strComputer = "."
  17. <pre class="codeSample">Set objWMIService = GetObject("winmgmts:\\" &amp; strComputer &amp; "\root\wmi")
  18. Set colItems = objWMIService.ExecQuery("Select * From MSNdis_80211_ReceivedSignalStrength")
  19. For Each objItem in colItems
  20. intStrength = objItem.NDIS80211ReceivedSignalStrength
  21. If intStrength &gt; -57 Then
  22. strBars = "5 Bars"
  23. ElseIf intStrength &gt; -68 Then
  24. strBars = "4 Bars"
  25. ElseIf intStrength &gt; -72 Then
  26. strBars = "3 Bars"
  27. ElseIf intStrength &gt; -80 Then
  28. strBars = "2 Bars"
  29. ElseIf intStrength &gt; -90 Then
  30. strBars = "1 Bar"
  31. Else
  32. strBars = "Strength cannot be determined"
  33. End If
  34. Next
  35. end if</pre>

Reply #17 Top

yep.. EDIT btn aint working.. ignore the <br> in the Function call at the top of the code..

Enjoy

Reply #18 Top

Great idea!

Might be better to check for XP and use WMI only there, since it probably won't work with Windows 7 either.

Reply #19 Top

I never used DX and don't know how it exactly works, but i needed to know the signal of the wlan i'm connected to for samurize and used:

C:\Windows\System32\cmd.exe /c FOR /F "tokens=2 delims=: " %i IN ('netsh wlan show interfaces ^| find " Señal"') DO @echo %i

or directly on a command prompt

FOR /F "tokens=2 delims=: " %i IN ('netsh wlan show interfaces ^| find " Señal"') DO @echo %i

IMPORTANT NOTE: it works for me both in Vista and 7. But my system is in spanish, so probably you'll have to use "Signal" instead of "Señal" or you could also get any other info shown in netsh wlan show interfaces.

EDIT: For the 'show network' command it should be:

Code: DOS
  1. FOR /F "tokens=2* delims=: " %i IN ('netsh wlan show network mode^=bssid ^| find="Se&ntilde;al" ') DO @echo %i

Again, changing "Señal" to "Signal" (or however it's written in english) for it to work in english systems.

Hope this helps