Scott Hanselman

How to delete Open or Insecure Wi-Fi HotSpots from Windows 8: Wifi.exe Command Line Utility with Source

June 07, 2013 Comment on this post [19] Posted in Open Source | Tools | Win7 | Win8
Sponsored By

image

For the most part I'm happy with Windows 8 but one feature was removed that makes no sense to me - the wireless networks dialog.

Sure, you can "Forget this network" by right clicking on a Wi-Fi Connection, but only when that network is in range. The old Wireless Networks dialog where you could add and remove networks is gone. Who knows how many saved Wi-Fi hotspot profile I have littering my system?

So, The Problem: I want to remove saved Wi-Fi Profiles whenever I feel like it. I wrote a command line util that will work in Windows 7 and Windows 8.

TL;DR Version

There's a build zipped up of Wifi.exe available here and the source is on GitHub.

UPDATE: I've put Wifi-Manager up on Chocolately so you can now "cinst wifi-manager." Thanks to Brendan Forster for the heavy lifting! Learn more about the Chocolatey package manager here!

Caveats and "Ya I know."

First, let me be clear that I have written a command line utility to replace another command line utility. I get it. I knew it when I did it. Others smarter than I have done similar things and written utilities that match their way of thinking rather than learning an unintuitive syntax. Don't hate the playa, hate the Regular Expression.

Aside: This is also a problem with my iPhone. I likely have 50+ saved Wi-Fi spots on my phone and no way to delete them without jail-breaking.

You can access Wi-Fi profiles with the netsh.exe that comes with Windows, so you could list out profiles like this:

c:\>netsh wlan show profiles

Profiles on interface Wi-Fi:

User profiles
-------------
All User Profile : Wayport_Access
All User Profile : HANSELMAN
All User Profile : HANSELMAN-N
All User Profile : HanselSpot
All User Profile : EliteWifi
All User Profile : Qdoba Free Wifi

Then, for each one, call

c:\>netsh wlan show profile "Qdoba Free Wifi"

Profile Qdoba Free Wifi on interface Wi-Fi:
=======================================================================

Profile information
-------------------
Version : 1
Type : Wireless LAN
Name : Qdoba Free Wifi
Control options :
Connection mode : Connect manually

Connectivity settings
---------------------
Number of SSIDs : 1
SSID name : "Qdoba Free Wifi"
Network type : Infrastructure

For each of these profiles, check if they are secure or open, and if you are connecting manually or automatically. Then, if you wanted, you could netsh wlan delete profile name="Qdoba Free Wifi" and remove a profile, even when it's not near you.

In my recent podcast with security expert Troy Hunt, he pointed out that it's easy to create a fake honeypot Wi-Fi spot that has the same name as a common open network, like Starbucks, for example.

  • Given: If my PC or phone is set up to automatically connect to any open hotspot named "Starbucks" then it will just connect to one...even an evil hotspot.
  • Therefore: it would be nice to automatically delete profiles for Wi-Fi spots that are both open (no security) and set to automatically connect.

I was tired, so I thought I'd bang out a little utility to do this. I could have used PowerShell or something but I felt like using C#. It's exercise.

UPDATE: Lee Holmes went and wrote it in PowerShell! Amazing.

Wifi.exe and it's Usage

Tired of reading? There's a build zipped up of Wifi.exe available here and the source is on GitHub. You may need to Right Click | Properties | Unblock the zip.

There's no warranty. The code sucks and I'm a horrible person and you're running a util you found on my blog. However, it works awesome on my machine. Issues appreciated, tidy PRs appreciated more, running Resharper and doing a PR, less so. I'll update the build if good bugs require it.

If you run Wifi.exe (I put it in my path) you'll see something like this:

c:\>wifi
AP-guest manual WPA2PSK
HANSELMAN-N auto WPA2PSK
HANSELMAN auto WPA2PSK
HanselSpot auto WPA2PSK
Qdoba Free Wifi manual open
Wayport_Access auto open Warning: AUTO connect to OPEN WiFi

Delete WiFi profiles that are OPEN *and* AUTO connect? [y/n]
n

Notice the columns, and the prompt. There's a warning when a hotspot is both open and set to auto-connect. If you answer Y to the prompt, the utility will delete that profile. You can also type 'wifi /deleteautoopen' to bypass the prompt and auto-delete just profiles that are auto and open.

A pull request a few minutes after I pushed this code also added the ability to

wifi delete "HOTSPOTNAME"

which is nice also. Thanks!

The Code

One of the great things about writing command line apps like this is that there's literally a dozen ways to do everything. They are trivial and silly but also useful and used daily. In this case I've got command line argument processing to think about, parsing output from a spawned process, doing the parsing in a clean way, making sure it works on a non-English machine (which I thought about but didn't test), as well as cleaning up of generated temp files.

It's hardly impressive code, but some of it was fun or interesting. Here's a few bits I liked.

Making Columns with Console.WriteLine and String.Format

Did you know that you can right- and left-align columns within a fixed with using String.Format? Few people know about this and I've seen whole libraries written custom to do the work that's built right in.

Console.WriteLine(String.Format("{0,-20} {1,10} {2,10} {3,30} ", a.Name, a.ConnectionMode, a.Authentication, warning));

Note the {0,-20} (left aligned) and the {1,10} (right aligned). Those are just like {0} and {1} in a String.Format but they include alignment and width.

Gratuitous use of Linq

It wouldn't be a silly utility without in crazy LINQ, eh? Who needs Regular Expressions when you can when you can do a SQL query over your string? ;) Actually, I don't know if this is a good thing or not. It was fun, though, and it works. Your thoughts?

This takes the output from wlan show profiles (seen above) and parses it into a list of just the AP Names. I think it should work in any language, assuming the : colons are there.

string result = ExecuteNetSh("wlan show profiles");
var listOfProfiles = from line in result.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)
where line.Contains(":")
let l = line
where l.Last() != ':'
select l.Split(':')[1].Trim();

foreach (string profile in listOfProfiles)
ExecuteNetSh(String.Format("wlan export profile \"{0}\" folder=\"{1}\"", profile, Environment.CurrentDirectory));

Cleaning up the temp XML files

I export a bunch of very specific XML files with a VERY non-specific extension. I can't control their file name and I don't want guess what their name is because I would need to recreate their AP Name encoding scheme. Instead, I look for any XML files in the current folder (given the rare chance that YOU, the utility runner, have XML files in the same folder already) and only delete the ones with the namespace that I know to be present in Wi-Fi profiles. I patted myself on the back for this one, but just lightly.

static XNamespace ns = "http://www.microsoft.com/networking/WLAN/profile/v1";

//Delete the exported profiles we made, making sure they are what we think they are!
foreach (string file in Directory.EnumerateFiles(Environment.CurrentDirectory, "*.xml"))
if (XElement.Load(file).Name.Namespace == ns)
File.Delete(file);

Capturing Command Line Output

Finally, here's how you get the output of a command line process you started:

Process p = new Process();
p.StartInfo.FileName = "netsh.exe";
p.StartInfo.Arguments = arguments ?? String.Empty;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();

string output = p.StandardOutput.ReadToEnd();
return output;

Pretty basic, but useful to bookmark.

Alternatives

After I wrote this I noticed there are some WinForms utilities to do this. That's great. I wouldn't mind making may own, except I'd want it to look exactly like the Windows 7 dialog. It'd be fun just to see if I could get it pixel perfect.

Feel free to go check out the code, play with it and make fun of me. https://github.com/shanselman/Windows-Wifi-Manager


Get Involved! Check out my latest production with TekPub. A meticulously edited TWO HOURS of video content where we cover everything we think a developer should know to "Get Involved" in the developer community.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
June 07, 2013 3:33
What I'd really like is an article explaining exactly what genius thought it was a good idea to remove the dialog that lets you control this.

Explicitly introducing gaping security holes is usually frowned upon.
K
June 07, 2013 3:41
Nice work Scott. You may want to re-read the alternatives paragraph again.

"I wouldn't might making may own, except I'd want it to look exactly like the Windows 7 dialog."
June 07, 2013 3:47
It's eye opening to run this and think, "Oh yeah. I remember connecting to that network last year."

Also, I need to talk to my dad to see why his network is apparently open...
June 07, 2013 4:14
Good Work Scott, it's very useful for me too.

While i was reading the post i was thinking how complicated the code will be and the most impressing thing that you are writing it in a very simple readable way. that makes me happy because i found you are dealing with Command Line as the way i use , that makes me feel "I'M ON THE RIGHT WAY".

Thanks Scott.
June 07, 2013 8:04
Thanks, I wanted a way to deleted saved hotspots, and hey, it's even classier by a command line.

A side effect or rather, something I didn't knew is that of course Windows 8 shares many things across Win8 installs where you use your Microsoft Account, and yeah, even network connections. So in this laptop I ran the utility and found networks I'm positive I haven't taken this laptop to. So, thanks for the heads up.
June 07, 2013 9:01
Here's how to do it in PowerShell: http://www.leeholmes.com/blog/2013/06/06/removing-insecure-wireless-connections-with-powershell/
June 07, 2013 12:55
Good tool, needs idiot-proof GUI.

A command line tool will only really appeal to people who already know the risks (and can do it in other ways - e.g. powershell solution above) - if you want to help those who are less fortunate than you (i.e. the millions of normal schleps out there who buy windows 8 machines "just to use as a PC") then get a GUI on it.

BTW I'm a programmer as well :-)
June 07, 2013 12:57
Also - you can delete them on iDevices, you just have to delete ALL stored Wifi access point details. Just to re-iterate something everybody probably already knows...

Settings / General / Reset Network Settings
June 07, 2013 16:30
:) Expected this post after that Wi-Fi Honeypot Podcast. thanks
June 08, 2013 0:30
Why did you choose to write a Command-line app vs., say, a PowerShell cmdlet? I find that PowerShell really simplifies a lot of this because I can just return an object and not have to worry about formatting.

Plus, it allows me to do something like:

Get-WifiNetwork | where { $_.Warning -ne $null } | Remove-WifiNetwork

I.e. I look at standard command line apps as being deprecated. It's much harder to pipe data from one utility to another without using a utility like grep.

P.S. Looks like somebody has beat me to this suggestion. ;P
June 09, 2013 15:47
Nice article.

A question for all your readers:
Relating to string.Format, can you apply more than one formatting to a column?
For example,
{0,-8} {1:d} {2,-16} {3, -32}
Is there a way to set the width, in addition to how the DateTime is formatted, in the 2nd column?
Thanks for any hints...
CB
June 10, 2013 6:37
CB - It'd be {0:d,-8), no?
June 10, 2013 15:55
Thanks for the reply.
Unfortunately, it doesn't seem to work.
Here's what I'm trying to do:
$dirs = get-childitem | sort CreationTime
foreach ($Item in ($dirs))
{
"{0:d} {1,-12} {2,-12} {3, -48}" -f $Item.CreationTime, $Item.Mode, $Item.length, $Item.name
}
This works as expected, but not with the spacing I'd like.
11/30/2012 -a--- 212 Commands.xml

If I change the first formatting term to "{0:d,-12}", the output is:
30,-12 -a--- 212 Commands.xml
CB
June 10, 2013 23:07
Thanks Scott for the great tool. It really helped me. But I agree with @AndyWatt. Unless it has a simple GUI, most people won't be able to use it. Can you or somebody work on it and add a user friendly GUI. I'm also waiting for Windows 8.1 to add an interface for this.
June 12, 2013 12:36
I second the request for this to be added to Windows 8.1 too.
June 15, 2013 16:22
Thanks, Scott. Just found on Twitter: ‏@ScriptingGuys Weekend Scripter: Use PowerShell to Find Auto-Connect Wireless Networks: http://bit.ly/16pYSbn . It is part one, so stay tuned for an exciting conclusion!
cn
June 17, 2013 1:58
Part 2 of ‏@ScriptingGuys 's Use PowerShell to Find Auto-Connect Wireless Networks is posted today. Enjoy!
cn
August 11, 2013 22:49
Netsh works only if you Run CMD "as administrator"
http://windows.microsoft.com/en-us/windows-8/manage-wireless-network-profiles
November 01, 2013 0:50
This is Great Scott. Now what if I want to "Unforget" a network. I accidently clicked "Forget this network" after windows unsuccessfully tried to connect to it. And for the life of me I cannot figure out how to bring the forgotten network back. Any thoughts?

Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.