Scott Hanselman

How to change the default browser in Visual Studio programmatically with PowerShell and possibly poke yourself in the eye

August 21, '10 Comments [29] Posted in ASP.NET | ASP.NET MVC | PowerShell | VS2010
Sponsored By

UPDATE: Why my own MacGyver solution was brilliant in its horrible way, the folks over at World of VS have taken up the challenge and created a proper Visual Studio extension that you should use. I'll chat with them and get some details and maybe a write-up of how they did it. So, while I encourage you to enjoy my tale below, go get the World of VS Default Browser Switcher now!

I've heard and seen lots of complaints about how it's hard to set the default browser that Visual Studio launches when you launch a debug session for a website.

Step 0 - Adequate

Folks spend time hunting around the Tools|Options dialog in Visual Studio looking for setting. They eventually realize it's not in there at all, but instead you have to right-click on an ASPX page within a Web Project and click "Browse With..."

Right Click | Browse With

From this dialog you can click Set Default, which is totally obvious, right my daimies? Um, no. This doesn't work for ASP.NET MVC people who use other view engines and might not even have a .ASPX file in their solution. Plus, it's slow and irritating. Sa da tay.

Browse With - Default.aspx 

It IS interesting that I can add other browsers, like Google Chrome to this dialog via Add. Note that Google Chrome installs in C:\Users\Scott\appdata\Local\Google\Chrome\Application\chrome.exe which may not be c:\Program Files where you usually go hunting for these things.

"What my thought process was" - or - "CSI: Visual Studio Default Browser"

Where is this browser information stored? That was my first question. Remember that your computer is NOT a black box. Even good programmers make this mistake and they "flip this switch and hope that light turns on" without confirming that the switch and the light are connected with good wire and they know how electricity works.

I can guess all day, or I can open up ProcMon and just see for myself. Seriously, learn how to use this freaking tool. You can flip light switches all day or you can just open up the wall and see the wires. If you know how to use Process Monitor competently, people of both sexes will immediately find you more attractive. It's true. I get all sorts of free Tacos and Chips when folks look can I run ProcMon like Keanu Reeves can look sad.

I fired ProcMon up set it to only show the devenv.exe process, and I took a chance and set 'contains browser' for the path. If this didn't work I'd open the flood gates and start sifting a bit. I could also have said 'highlight' things with the word browser if I liked.

Process Monitor Filter (2)

I launch VS, open the Browse With dialog and sweet sassy mollassy. Look at all that good stuff.

Process Monitor - Sysinternals www.sysinternals.com

Oh, fonts too small, let me zoom in.

Registry Zoomed In

Looks like we're reading values out of the registry at HKCU:\Software\Microsoft\VisualStudio\10.0\WebBrowser\ConfigTimestamp and...

image 

...reading out of the browsers.xml file at C:\Users\Scott\AppData\Local\Microsoft\VisualStudio\10.0\browsers.xml.

What's in that file? I'm guessing XML with no schema, given it was probably 2003 when someone wrote this.

<?xml version="1.0"?>
<BrowserInfo>
<BrowserInfo>
<Browser>
<Name>Google Chrome</Name>
<Path>"C:\Users\Scott\AppData\Local\Google\Chrome\Application\chrome.exe"</Path>
<Resolution>0</Resolution>
<IsDefault>False</IsDefault>
</Browser>
</BrowserInfo>
</BrowserInfo>

I've seen folks attempt to change this with various extensions in Visual Studio and using automation calls within Visual Studio, but to the best of my knowledge, this feature has been in here for years and years and there's no way to get at it programmatically.

Step 1 - Slightly Awesome

Interestingly as well, my first attempt at changing the browser programmatically consisted of this brilliance:

C:\Users\Scott\AppData\Local\Microsoft\VisualStudio\10.0>copy "browsers - firefox.xml" browsers.xml /y
1 file(s) copied.

But, it seems that those registry keys are serious and really used for something, because each time I opened Browse With... I found my changes thrown away, probably because VS isn't watching for file for change notification, but rather caching the file in memory.

Looks like a job for PowerShell (yes, I know can do this with batch files, but PowerShell is way batter, so nyah. Learn it.)

First I need to figure out what's going on in this registry. If I got to that key (by right-clicking the key within ProcMon and clicking Jump To), then right-click on the key in the Registry Editor I get:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0\WebBrowser\ConfigTimestamp]
"CacheFilePath"="C:\\Users\\Scott\\AppData\\Local\\Microsoft\\VisualStudio\\10.0\\browsers.xml"
"CacheFileSizeBytes"=dword:000000e6
"CacheFileDateLastMod"=hex(b):6f,18,a4,ee,17,41,cb,01
"LastConfigurationTimestamp"=hex(b):00,26,aa,86,09,41,cb,01

Ok, so that's the location of the file we already know about, and  looks like the file size in hex, as well as some magic goo for CacheFileDateLastMod and LastConfigurationTimestamp.

One at a time. The CacheFileSizeBytes is easy. Did you know that the Windows 7 calculator was quietly upgraded while you were out there not learning how to convert hex in your head? It's true! (Yes, you can also just look at the decimal value in the Registry, but again, this is more fun. Yes, you could always convert between Hex and Dec in calc.exe, but again, fun. What's your beef? ;) )

Calculator in Windows 7 - Being Awesome in Programmer Mode

Click Dec(imal) and looks like 230 bytes, the size of my browser.xml file. What's the deal with those mod dates, though? They a probably a Windows file time, if they aren't ticks. Ticks are seconds since 1970-1-1 and a Windows FileTime is the number of 100-nanosecond ticks since 1601-1-1 rounded to the nearest millisecond. Why? Because 1601 was an awesome year. I mean, the Battle of Kinsale stopped the siege in Kinsale, Ireland, and famine killed half the Estonians. Sheesh, that was a horrible year! What were we thinking!?

Anyway, the easiest way to convert something you think might be a Date into a Date (and reason number 0x3b for you to finally learn PowerShell) is this line in PowerShell.

PS C:\> [DateTime]129268523480000000
Saturday, August 21, 0410 8:19:08 AM

Lemme do that again against a blue background with a screenshot so you really believe me.

Windows PowerShell, again, being awesome.

Oh yes, I'm on a horse. Cool. Those are FileTimes. So, tappity tappity and here's a PowerShell script to check the current values and output them for testing.

cd C:\Users\Scott\AppData\Local\Microsoft\VisualStudio\10.0

$browsers = [xml](get-content 'browsers.xml')
$browsers.BrowserInfo.Browser.Name + " " + $browsers.BrowserInfo.Browser.Path

$regkey = "HKCU:\Software\Microsoft\VisualStudio\10.0\WebBrowser\ConfigTimestamp"

"LastConfigTimestamp: " + ([DateTime](get-itemproperty $regkey).LastConfigurationTimestamp).ToLocalTime()
"CacheFileDateLastMod: " + ([DateTime](get-itemproperty $regkey).CacheFileDateLastMod).ToLocalTime()
"CacheFileSizeBytes: " + (get-itemproperty $regkey).CacheFileSizeBytes

I'll go and develop and run this script in the PowerShell ISE (that's S for Scripting) that you already have on your computer. Freaky how Microsoft sneaks stuff like this on your machine. If you've got Windows 7, you're already got this.

Windows PowerShell ISE (x86)

I run Visual Studio and click Browse|With... a few times and watch the values change. Seems I need the SET to my GET script, so why not something like this. I've made copies of browsers.xml like browsers-chrome and browsers-firefox. You can do the same if you like.

cd C:\Users\Scott\AppData\Local\Microsoft\VisualStudio\10.0 

copy '.\browsers - firefox.xml' .\browsers.xml
$regkey = "HKCU:\Software\Microsoft\VisualStudio\10.0\WebBrowser\ConfigTimestamp"

set-itemproperty $regkey -name LastConfigurationTimestamp -value (&{[DateTime]::Now.ToUniversalTime().ToFileTime()}) -type qword
set-itemproperty $regkey -name CacheFileDateLastMod -value (&{((dir .\browsers.xml).LastWriteTimeUtc).ToFileTime()}) -type qword
set-itemproperty $regkey -name CacheFileSizeBytes -value (&{(dir .\browsers.xml).Length}) -type dword

What I am doing in this script? I'm copying my browser xml over the main one AND I'm updating the TimeStamp to now to get Visual Studio to re-read the file. Visual Studio seems to be checking and triple checking and if the CacheFileDateLastMod and CacheFileSizeBytes don't reflect reality, it will freak out and just delete my file completely and rebuild a new browsers.xml from scratch. Paranoid.

You can go and fancy these scripts up with command-line parameters all you want because you're a better programmer than I, but I am all Save|As, baby. I have "UpdateDefaultBrowserToChrome.ps1" and, yes, wait for it, "UpdateDefaultBrowserToFireFox.ps1" and I sleep at night just fine, thank you very much.

I can right click on them on my desktop and select Run with PowerShell if I like.

Right clicking on my PowerShell script on my desktop

But...still....it could be more awesome. Darn my parents and the work ethic they instilled in me as a small child.

Step 2 - Extremely Awesome

You can run PowerShell scripts from the regular not-really-DOS command line like this if you like.

C:\Users\Scott\Desktop>powershell .\UpdateDefaultVSBrowserToChrome.ps1

I could even install PowerConsole and run these commands from INSIDE Visual Studio 2010 if I like and I want to rip a hole in the space time continuum. My, is that intellisense inside PowerShell inside Visual Studio? Double sun power!!!!

Powershell being awesome INSIDE Visual Studio 2010. Double Sun Power!!!!!

Still, this doesn't fit my mindless point and click mouse-like workflow. I'll go to Tools | External Tools and add two. Make sure you select the right PowerShell, which will be x86 even if you're on x64 so you correctly access the registry. I also checked Use Output window and added a single line of text at the bottom of each script.

External Tools 

Nice, but why not a toolbar?

Step 3 - Profit! I mean, Profoundly Awesome!

Right click on any Toolbar, this Customize and add buttons for External Tools (in my case #6 and #7) and...

Switchy Browser Toolbar buttons

Which gives me this when I click:

Pow, Sally. Browser changed to Chrome.

And shows this in Browse With, showing me it worked:

Browse With - Default.aspx again with Chrome

Yay! Enjoy.

Roll Up Instructions

  1. Go to C:\Users\YOURNAME\AppData\Local\Microsoft\VisualStudio\10.0
  2. Make a bunch of browser-whatever xml files for your browsers, or populate your list from Visual Studio, then make copies.
  3. Make yourself a few of these (or make one that switches if you're awesome)
cd C:\Users\YOURNAME\AppData\Local\Microsoft\VisualStudio\10.0

copy '.\browsers - CUSTOMBROWSER.xml' .\browsers.xml
$regkey = "HKCU:\Software\Microsoft\VisualStudio\10.0\WebBrowser\ConfigTimestamp"

set-itemproperty $regkey -name LastConfigurationTimestamp -value (&{[DateTime]::Now.ToUniversalTime().ToFileTime()}) -type qword
set-itemproperty $regkey -name CacheFileDateLastMod -value (&{((dir .\browsers.xml).LastWriteTimeUtc).ToFileTime()}) -type qword
set-itemproperty $regkey -name CacheFileSizeBytes -value (&{(dir .\browsers.xml).Length}) -type dword
"Bam, son. Browser changed to CUSTOM BROWSER."
  1. Add some external tools that call PowerShell with your new scripts as parameters.
  2. Add toolbar buttons if you feel like it.
  3. Go write a proper Visual Studio 2010 extension that does all this and packages it up in one click, put in on the VS Gallery and impress your friends and family. Crap. Now *I* need to do that for my next post, don't I? Shoot. Kzu? Give me a call and teach me how to do this.

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
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Saturday, August 21, 2010 11:00:20 AM UTC
I can't help but notice where that blue ribbon icon overlay has gone in your PowerShell window.
Anonymous
Saturday, August 21, 2010 11:04:04 AM UTC
Ah, this was not a Visual Studio PowerShell window, it was a regular one.
Saturday, August 21, 2010 11:30:32 AM UTC
Sir u r g8
sohelelite
Saturday, August 21, 2010 12:08:29 PM UTC
Pity you can't do that with a shortcut! It's almost like you want people to lose time while developing...
Saturday, August 21, 2010 1:56:08 PM UTC
Awesome post! I'll be using procmon a ton now!

Quick question: ur obviously running this on Win 7. Any permissions "issues", like dealing with the "Run as Administrator" verification dialog action?
Saturday, August 21, 2010 4:38:36 PM UTC
Sa-da-tay, my damies!”
Saturday, August 21, 2010 4:50:19 PM UTC
Your procman and Powershell fu is admirable. Should adding browser options to Visual Studio be <sarcasm>this easy</sarcasm>?
Saturday, August 21, 2010 7:38:06 PM UTC
This is a bit off topic I know, but I was wondering, is there any nifty PowerShell (or any) mojo that will allow IIS to update the location of your current project directory when you launch a project in Visual Studio and are using IIS instead of Cassini?

We use TFS and so each of our branches of course has its own folder on our dev machine's hard drive. It becomes very annoying to have to manually update IIS and point it to the new location each time we change branches, and the project won't load unless it has IIS pointing where it needs to.

I don't suppose there is some way to use PowerShell to accomplish that?

Either by placing some sort of startup/load script inside the solution itself so that when you open the solution it executes and updates IIS, or failing that, perhaps an IIS script to first update IIS and then launch the VS 2010 solution?

Thank you, and sorry for straying off your topic.
Saturday, August 21, 2010 10:28:05 PM UTC
Great post.

You can also add the content of those scripts (wrapped in functions) to the PowerConsole profile. You can find it in $PowerConsoleUserProfile.

Then they are always available when you launch VS and PowerConsole.

Hey Scott, any chance of getting the source to PowerConsole vsix? It was created by Jianchun Xu of Microsoft.

Thanks.
Sunday, August 22, 2010 10:15:11 AM UTC
You are actually demonstrating why I frequently fail to feel empowered by the big-iron IDEs like Visual Studio. If you want to get anything done, you are far better of using a powerhouse editor, a decent shell and ditto scripts. Best not to be hampered by silly undocumented timestamp blitting handicaps designed in hell.

I know I'm overstating (eclipse + Java is pretty awesome, as is VS+Resharper for C#) but I get so bogged down when hitting the limits that I have learned to accept the /preceived/ losses from not being in the IDE alltogether.

In other words, I stopped feeling triumphant about this type of hacks a while ago. Now, I'm only annoyed, even _if_ I do finally end up "taming the beast". It is not productive in any sense of the word.

Kudos for sharing your solution, though, because that will lift the burden for others
Seth
Sunday, August 22, 2010 7:07:21 PM UTC
Sa da tay!!!
Sunday, August 22, 2010 7:47:41 PM UTC
I bow down before your greatness. Now I'm waiting for that Visual Studio add-in, get cracking! (LOL)
Sunday, August 22, 2010 8:16:07 PM UTC
Hi Scott,

thanks for digging into this issue!

I havent made my way to powershell yet... so here is a macro :-)

http://lennybacon.com/2010/08/22/ReHowToChangeTheDefaultBrowserInVisualStudioProgrammatically.aspx

--Daniel
Monday, August 23, 2010 12:10:38 PM UTC
And what about attaching to external process? You can use any browser you want. Or I missed the point in changing default browser.
Monday, August 23, 2010 6:39:24 PM UTC
Wow -- very nice.

Too bad Scott after all this hacking that you'll lose all these custome settings and scripts when you reload Win7 in 6 months or whatever.
dm3281
Tuesday, August 24, 2010 1:52:47 AM UTC
Very interesting, thanks.
Wednesday, August 25, 2010 1:14:40 PM UTC
One other (and slightly easier) solution is Browser Chooser (http://browserchooser.codeplex.com/ ).
Wednesday, August 25, 2010 8:32:30 PM UTC
Oh, man, you were in a mood when you wrote this. : )
Wednesday, August 25, 2010 8:48:33 PM UTC
Hope you didn't poke yourself in the eye too hard.
Thursday, August 26, 2010 10:55:11 AM UTC
thanks you so much scott! I was so frustrated with this.
Thursday, August 26, 2010 10:06:36 PM UTC
Awesome post, but I keep getting "File cannot be loaded because the execution of scripts is disabled on this system" when I click my toolbar button in VS2010. When I run Get-ExecutionPolicy from a powershell window, however, it says my policy is "Unrestricted". Anyone have any ideas on what could be causing this?
Thursday, August 26, 2010 10:06:51 PM UTC
I liked the post content. Had to be said.
But, honest, what I really loved was the how. Did you eat Lion for breakfast this morning?

"Double sun power!"
Thursday, August 26, 2010 10:39:36 PM UTC
If you are getting script issue, did you try running them directly from PowerShell? Did that work? Did you "unblock" the scripts from the Properties dialog?

Double Sun Power!
Friday, August 27, 2010 7:55:45 PM UTC
Thanks for your suggestions, Scott.

The scripts do run if I run them directly from PowerShell. I see the contents of the browsers.xml file change when I run them directly, but VS2010 still uses the system default browser for some reason.

As far as the script execution issue goes, I only receive the error message when I try and run them as external tools in VS2010. I checked the properties dialog on the ps1 files, but the "Unblock" option doesn't show up.
Friday, August 27, 2010 7:58:37 PM UTC
Is this on x86 or x64? What if you open regedit...do those values change? You're the first and only person to say this doesn't work so there must be something interesting about your machine.
Saturday, August 28, 2010 9:55:16 PM UTC
sorry to spoil your fun scott but I'm also not able to make it work on my Win7 box. It runs fine, changes registry values (I print them before changing and after changing). If I change my browser and run solution it does not open any window or tab :(
Saturday, August 28, 2010 9:58:54 PM UTC
just noticed this is what it is printing:

PS C:\Users\amantur> F:\Code\SharedBinaries\BrowseWithIE.ps1
Internet Explorer
"C:\Program Files\Internet Explorer\iexplore.exe"
LastConfigTimestamp: 08/29/0410 03:07:31
CacheFileDateLastMod: 08/29/0410 00:33:35
CacheFileSizeBytes: 256
LastConfigTimestamp: 08/29/0410 03:26:40
CacheFileDateLastMod: 08/29/0410 00:33:35
CacheFileSizeBytes: 256
Browser changed to Internet Explorer.

see the date : 08/29/0410 powershell is messing the dates
Sunday, August 29, 2010 7:53:59 PM UTC
@amantur: I had the same problem - I couldn't get it to run from within VS2010 but when I right clicked the .ps1 files and selected "Run with PowerShell", it ran fine.

I had run the set-executionpolicy to "RemoteSigned" using the PowerShell ISE and couldn't figure out why it wouldn't run in VS2010. On a whim, I opened up powershell.exe (not the PowerShell ISE, and from the path "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe" ) and ran "set-executionpolicy RemoteSigned" and it magically started working in VS. I don't know why setting it through that worked and going through the ISE didn't, but that did the trick.

Also, to verify that's what fixed it, I ran "set-executionpolicy restricted" in powershell.exe and it started failing again in VS2010. Set it back to "remotesigned" and it resumed working, so setting it via PowerShell and not the PowerShell ISE is definitely what fixed it for me.
Monday, August 30, 2010 2:59:50 AM UTC
My default browser is Firefox, but I prefer IE when I am developing in VS. Almost all of my projects are MVC; so Browser setup is not available even for aspx files.

The poor man's solution: create a webforms project. right-click any aspx file and select "Browse with..." Choose the browser you want and click "set as default" (you don't even have to start it). It will change browsers.xml and registry settings, and now *all* projects, including MVC will use this newly defined default browser...

I know, PS and registry tinkering is cool - but sometimes I debug on other people's computer, and creating a quick throwaway project is faster than running my scripts...
Comments are closed.

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