Update, October 2026 — read this part first.
This post is from 2014 and it keeps getting traffic, so here is the short answer for anyone arriving from a search engine today. Do not dig through the registry. On .NET Core, .NET 5 and everything after,
UseShellExecutedefaults tofalse, which is exactly whyProcess.Start(url)fails. Set it back totrueand the operating system picks the default browser for you:Process.Start(new ProcessStartInfo("https://www.royalapps.com/") { UseShellExecute = true });That is the whole fix, and it is cross-platform: Windows uses the shell association, macOS goes through
open, Linux throughxdg-open.The original 2014 problem had a different cause — a Chrome bug, fixed a year later (see the remark at the bottom, which was already in the post in 2015). The registry-walking code below is obsolete and should not be copied into new projects. It stays here because the registry layout it describes is still accurate and still occasionally useful if you need to identify the default browser rather than merely launch something in it.
The text from here on is the 2014 original, unchanged.
For launching a URL in the default browser, I used to write this simple C# code:
Process.Start("http://www.royal-server.com/");But during my tests today I got a nice exception when I execute this code:
System.ComponentModel.Win32Exception was unhandled
HResult=-2147467259
Message=The system cannot find the file specified
Source=System
ErrorCode=-2147467259
NativeErrorCode=2
StackTrace:
at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start(String fileName)
at ConsoleApplication6.Program.Main(String[] args)Now, it seems that this code in previous versions of Windows worked. And the reason why it is not working on my system is simply because I have Chrome as my default browser (the code works with Firefox as default browser).
Setting it back to IE solved the problem — but: who wants this? … ;)
So I googled a bit and found code that reads the path to the current default browser in the registry in HKEY_CLASSES_ROOT\http. But — lo and behold! — the subtree does not change if you change to another default browser. This registry place seems to be a dead end (it maybe was used in earlier versions of Windows?).
The Solution
Starting with Windows Vista a new “Default Programs” concept was introduced. The value a user sets as their own choice of browser (per user, not per machine!) is saved under the following registry key:
HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice\ProgidThere, you can find a string that identifies the browser:
FirefoxURL— for FirefoxChromeHTML— for ChromeIE.HTTP— for Internet Explorer- and probably some more (but I have not tested others)
The value here is a pointer to HKEY_CLASSES_ROOT\<Name>, e.g. HKEY_CLASSES_ROOT\IE.HTTP. The concrete starting path to the executable can be found under HKEY_CLASSES_ROOT\<Name>\shell\open\command.
This led to the following — though in my opinion huge amount of — code to actually launch a URL in the default browser:
public static string GetDefaultBrowserPath()
{
string urlAssociation = @"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http";
string browserPathKey = @"$BROWSER$\shell\open\command";
RegistryKey userChoiceKey = null;
string browserPath = "";
try
{
// Read default browser path from userChoiceKey
userChoiceKey = Registry.CurrentUser.OpenSubKey(urlAssociation + @"\UserChoice", false);
// If user choice was not found, try machine default
if (userChoiceKey == null)
{
// Read default browser path from Win XP registry key
var browserKey = Registry.ClassesRoot.OpenSubKey(@"HTTP\shell\open\command", false);
// If browser path wasn't found, try Win Vista (and newer) registry key
if (browserKey == null)
{
browserKey = Registry.CurrentUser.OpenSubKey(urlAssociation, false);
}
var path = CleanifyBrowserPath(browserKey.GetValue(null) as string);
browserKey.Close();
return path;
}
else
{
// user defined browser choice was found
string progId = userChoiceKey.GetValue("ProgId").ToString();
userChoiceKey.Close();
// now look up the path of the executable
string concreteBrowserKey = browserPathKey.Replace("$BROWSER$", progId);
var kp = Registry.ClassesRoot.OpenSubKey(concreteBrowserKey, false);
browserPath = CleanifyBrowserPath(kp.GetValue(null) as string);
kp.Close();
return browserPath;
}
}
catch (Exception)
{
return "";
}
}This way, you open the URL in the browser the user actually specified (or that is configured system-wide — depending on the OS).
Process.Start(GetDefaultBrowserPath(), url);REMARK 06/11/15:
After updating to the latest Google Chrome version (in my case I updated from 35.0.1916.114 to 35.0.1916.153) Process.Start worked also for Google Chrome. So it seems that only some versions of Chrome had this issue.
