【问题标题】:How to find default web browser using C#?如何使用 C# 查找默认 Web 浏览器?
【发布时间】:2021-11-12 16:49:37
【问题描述】:

有没有一种方法可以使用 C# 找出我的默认 Web 浏览器的名称? (火狐、谷歌浏览器等)

你能举个例子吗?

【问题讨论】:

    标签: c#


    【解决方案1】:

    当 Internet Explorer 设置为默认浏览器时,other answer 对我不起作用。在我的 Windows 7 PC 上,HKEY_CLASSES_ROOT\http\shell\open\command 没有针对 IE 进行更新。这背后的原因可能是从 Windows Vista 开始对默认程序的处理方式进行了更改。

    您可以在注册表项Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice 中找到默认选择的浏览器,其值为Progid。 (thanks goes to Broken Pixels)

    const string userChoice = @"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice";
    string progId;
    BrowserApplication browser;
    using ( RegistryKey userChoiceKey = Registry.CurrentUser.OpenSubKey( userChoice ) )
    {
        if ( userChoiceKey == null )
        {
            browser = BrowserApplication.Unknown;
            break;
        }
        object progIdValue = userChoiceKey.GetValue( "Progid" );
        if ( progIdValue == null )
        {
            browser = BrowserApplication.Unknown;
            break;
        }
        progId = progIdValue.ToString();
        switch ( progId )
        {
            case "IE.HTTP":
                browser = BrowserApplication.InternetExplorer;
                break;
            case "FirefoxURL":
                browser = BrowserApplication.Firefox;
                break;
            case "ChromeHTML":
                browser = BrowserApplication.Chrome;
                break;
            case "OperaStable":
                browser = BrowserApplication.Opera;
                break;
            case "SafariHTML":
                browser = BrowserApplication.Safari;
                break;
            case "AppXq0fevzme2pys62n3e0fbqa7peapykr8v":
                browser = BrowserApplication.Edge;
                break;
            default:
                browser = BrowserApplication.Unknown;
                break;
        }
    }
    

    如果您还需要浏览器可执行文件的路径,您可以按如下方式访问它,使用Progid 从ClassesRoot 检索它。

    const string exeSuffix = ".exe";
    string path = progId + @"\shell\open\command";
    FileInfo browserPath;
    using ( RegistryKey pathKey = Registry.ClassesRoot.OpenSubKey( path ) )
    {
        if ( pathKey == null )
        {
            return;
        }
    
        // Trim parameters.
        try
        {
            path = pathKey.GetValue( null ).ToString().ToLower().Replace( "\"", "" );
            if ( !path.EndsWith( exeSuffix ) )
            {
                path = path.Substring( 0, path.LastIndexOf( exeSuffix, StringComparison.Ordinal ) + exeSuffix.Length );
                browserPath = new FileInfo( path );
            }
        }
        catch
        {
            // Assume the registry value is set incorrectly, or some funky browser is used which currently is unknown.
        }
    }
    

    【讨论】:

    • 不过,我个人认为,与其检索可执行路径,不如在检索到的字符串中填写 %1 参数,将其拆分为程序和参数,然后按原样执行。在注册表中定义。
    • @Darren 感谢您加入 Opera、Safari 和 Edge!不过,Edge 在注册表中的名字到底是怎么回事?你确定这是所有系统上的相同标识符(它看起来像一个随机字符串)吗?
    • @StevenJeuris 我不能确定 Edge 的价值,几乎没有添加那个。我发现这个answer 具有相同的值,所以它几乎两年没有改变。希望这是安全的,但我和你一样有点怀疑。 Opera 看起来不错,Safari 从 2012 年开始就没有在 Windows 上开发,但仍然有一个副本,并认为包含在内会很好。
    • 我刚安装了opera,“UserChoice”键是空的,所以这似乎不适用于Opera。 Windows 7 专业版 64 位。
    【解决方案2】:

    你可以看here的例子,但主要是这样:

    internal string GetSystemDefaultBrowser()
    {
        string name = string.Empty;
        RegistryKey regKey = null;
    
        try
        {
            //set the registry key we want to open
            regKey = Registry.ClassesRoot.OpenSubKey("HTTP\\shell\\open\\command", false);
    
            //get rid of the enclosing quotes
            name = regKey.GetValue(null).ToString().ToLower().Replace("" + (char)34, "");
    
            //check to see if the value ends with .exe (this way we can remove any command line arguments)
            if (!name.EndsWith("exe"))
                //get rid of all command line arguments (anything after the .exe must go)
                name = name.Substring(0, name.LastIndexOf(".exe") + 4);
    
        }
        catch (Exception ex)
        {
            name = string.Format("ERROR: An exception of type: {0} occurred in method: {1} in the following module: {2}", ex.GetType(), ex.TargetSite, this.GetType());
        }
        finally
        {
            //check and see if the key is still open, if so
            //then close it
            if (regKey != null)
                regKey.Close();
        }
        //return the value
        return name;
    
    }
    

    【讨论】:

    • 当我将 Internet Explorer 设置为默认浏览器时,它似乎对我不起作用。 :/ 该特定注册表位置未更新为指向 IE。
    • @tofutim 你能详细说明一下吗?
    • 在我的 Win 8.1 机器上,这种技术会启动 Firefox(伴随的消息是 Firefox 不是默认浏览器)。这应该是 Jeuris 答案的后备(对于较旧的操作系统)(需要进行一些编辑才能工作)。
    • 我会提供一个在某些情况下可能有用的解决方案 - 打开一个页面 System.Diagnostics.Process.Start("http://google.com"); 然后检查 chrome、opera,即 firefox、safary 的运行进程。这是一个答案,因为您想要“名称”而不是路径。
    【解决方案3】:

    我刚刚为此做了一个函数:

        public void launchBrowser(string url)
        {
            string browserName = "iexplore.exe";
            using (RegistryKey userChoiceKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice"))
            {
                if (userChoiceKey != null)
                {
                    object progIdValue = userChoiceKey.GetValue("Progid");
                    if (progIdValue != null)
                    {
                        if(progIdValue.ToString().ToLower().Contains("chrome"))
                            browserName = "chrome.exe";
                        else if(progIdValue.ToString().ToLower().Contains("firefox"))
                            browserName = "firefox.exe";
                        else if (progIdValue.ToString().ToLower().Contains("safari"))
                            browserName = "safari.exe";
                        else if (progIdValue.ToString().ToLower().Contains("opera"))
                            browserName = "opera.exe";
                    }
                }
            }
    
            Process.Start(new ProcessStartInfo(browserName, url));
        }
    

    【讨论】:

      【解决方案4】:

      这已经过时了,但我只会添加我自己的发现供其他人使用。 HKEY_CURRENT_USER\Software\Clients\StartMenuInternet 的值应该为您提供该用户的默认浏览器名称。

      如果要枚举所有已安装的浏览器,请使用 HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet

      您可以使用在HKEY_CURRENT_USER 中找到的名称来识别HKEY_LOCAL_MACHINE 中的默认浏览器,然后以此方式查找路径。

      【讨论】:

      • 不。在Win10中没有这样做。它说 Firefox,而我的默认设置是 Chrome。
      • 这个方法还不错。 HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet 下的浏览器列表非常适合显示已安装的内容,同时还提供了一些有用的信息,例如 ...StartMenuInternet\<Browser Name Here>\Capabilities\FileAssociations,并安装了可用于更改默认浏览器的字符串。
      • 然而,实际的“默认浏览器”在功能上主要由 HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associati‌​ons\UrlAssociations\‌​http\UserChoice 下的 progid 确定。根据我的测试,这就是浏览器本身确定它们是否为“默认值”的方式。 Firefox 认为自己默认只有 http,Chrome 也会检查 https,而 IE 希望填充所有可能的默认值
      • 此外,这种方法在 Windows 10 上似乎效果不佳...在 Windows 7 上效果很好。
      【解决方案5】:

      WINDOWS 10

      internal string GetSystemDefaultBrowser()
          {
              string name = string.Empty;
              RegistryKey regKey = null;
      
              try
              {
                  var regDefault = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.htm\\UserChoice", false);
                  var stringDefault = regDefault.GetValue("ProgId");
      
                  regKey = Registry.ClassesRoot.OpenSubKey(stringDefault + "\\shell\\open\\command", false);
                  name = regKey.GetValue(null).ToString().ToLower().Replace("" + (char)34, "");
      
                  if (!name.EndsWith("exe"))
                      name = name.Substring(0, name.LastIndexOf(".exe") + 4);
      
              }
              catch (Exception ex)
              {
                  name = string.Format("ERROR: An exception of type: {0} occurred in method: {1} in the following module: {2}", ex.GetType(), ex.TargetSite, this.GetType());
              }
              finally
              {
                  if (regKey != null)
                      regKey.Close();
              }
      
              return name;
          }
      

      【讨论】:

      • 工作,在 2021 年 3 月与使用 .NET Core 3.1 的 windows 10 确认。谢谢
      【解决方案6】:

      以下是我通过将此处的响应与正确的协议处理相结合而得出的结论:

      /// <summary>
      ///     Opens a local file or url in the default web browser.
      ///     Can be used both for opening urls, or html readme docs.
      /// </summary>
      /// <param name="pathOrUrl">Path of the local file or url</param>
      /// <returns>False if the default browser could not be opened.</returns>
      public static Boolean OpenInDefaultBrowser(String pathOrUrl)
      {
          // Trim any surrounding quotes and spaces.
          pathOrUrl = pathOrUrl.Trim().Trim('"').Trim();
          // Default protocol to "http"
          String protocol = Uri.UriSchemeHttp;
          // Correct the protocol to that in the actual url
          if (Regex.IsMatch(pathOrUrl, "^[a-z]+" + Regex.Escape(Uri.SchemeDelimiter), RegexOptions.IgnoreCase))
          {
              Int32 schemeEnd = pathOrUrl.IndexOf(Uri.SchemeDelimiter, StringComparison.Ordinal);
              if (schemeEnd > -1)
                  protocol = pathOrUrl.Substring(0, schemeEnd).ToLowerInvariant();
          }
          // Surround with quotes
          pathOrUrl = "\"" + pathOrUrl + "\"";
          Object fetchedVal;
          String defBrowser = null;
          // Look up user choice translation of protocol to program id
          using (RegistryKey userDefBrowserKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\" + protocol + @"\UserChoice"))
              if (userDefBrowserKey != null && (fetchedVal = userDefBrowserKey.GetValue("Progid")) != null)
                  // Programs are looked up the same way as protocols in the later code, so we just overwrite the protocol variable.
                  protocol = fetchedVal as String;
          // Look up protocol (or programId from UserChoice) in the registry, in priority order.
          // Current User registry
          using (RegistryKey defBrowserKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Classes\" + protocol + @"\shell\open\command"))
              if (defBrowserKey != null && (fetchedVal = defBrowserKey.GetValue(null)) != null)
                  defBrowser = fetchedVal as String;
          // Local Machine registry
          if (defBrowser == null)
              using (RegistryKey defBrowserKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\" + protocol + @"\shell\open\command"))
                  if (defBrowserKey != null && (fetchedVal = defBrowserKey.GetValue(null)) != null)
                      defBrowser = fetchedVal as String;
          // Root registry
          if (defBrowser == null)
              using (RegistryKey defBrowserKey = Registry.ClassesRoot.OpenSubKey(protocol + @"\shell\open\command"))
                  if (defBrowserKey != null && (fetchedVal = defBrowserKey.GetValue(null)) != null)
                      defBrowser = fetchedVal as String;
          // Nothing found. Return.
          if (String.IsNullOrEmpty(defBrowser))
              return false;
          String defBrowserProcess;
          // Parse browser parameters. This code first assembles the full command line, and then splits it into the program and its parameters.
          Boolean hasArg = false;
          if (defBrowser.Contains("%1"))
          {
              // If url in the command line is surrounded by quotes, ignore those; our url already has quotes.
              if (defBrowser.Contains("\"%1\""))
                  defBrowser = defBrowser.Replace("\"%1\"", pathOrUrl);
              else
                  defBrowser = defBrowser.Replace("%1", pathOrUrl);
              hasArg = true;
          }
          Int32 spIndex;
          if (defBrowser[0] == '"')
              defBrowserProcess = defBrowser.Substring(0, defBrowser.IndexOf('"', 1) + 2).Trim();
          else if ((spIndex = defBrowser.IndexOf(" ", StringComparison.Ordinal)) > -1)
              defBrowserProcess = defBrowser.Substring(0, spIndex).Trim();
          else
              defBrowserProcess = defBrowser;
      
          String defBrowserArgs = defBrowser.Substring(defBrowserProcess.Length).TrimStart();
          // Not sure if this is possible / allowed, but better support it anyway.
          if (!hasArg)
          {
              if (defBrowserArgs.Length > 0)
                  defBrowserArgs += " ";
              defBrowserArgs += pathOrUrl;
          }
          // Run the process.
          defBrowserProcess = defBrowserProcess.Trim('"');
          if (!File.Exists(defBrowserProcess))
              return false;
          ProcessStartInfo psi = new ProcessStartInfo(defBrowserProcess, defBrowserArgs);
          psi.WorkingDirectory = Path.GetDirectoryName(defBrowserProcess);
          Process.Start(psi);
          return true;
      }
      

      【讨论】:

      • 这对我的解决方案非常有用,尽管在客户端的 Windows 10 机器上我必须切换 Process.Start 才能让 ProcessStartInfo 能够设置工作目录。但是,它并没有将 Yandex 选为默认浏览器,我还没有研究过。
      • 老实说,我曾让 Visual Studio 在两次单击完全相同的链接时打开两个不同的浏览器。整个事情是一个巨大的混乱。不过,他的工作目录是公平的。我将在其中进行编辑。
      【解决方案7】:

      正如我在Steven's answer 下评论的那样,我遇到了这种方法不起作用的情况。我正在运行 Windows 7 Pro SP1 64 位。我下载并安装了the Opera browser,发现他的回答中描述的HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice reg 键是空的,即没有ProgId 值。

      我使用Process Monitor 来观察在默认浏览器中打开 URL 时发生的情况(通过单击开始 > 运行并键入“https://www.google.com”)并发现在检查上述注册表项并失败后为了找到ProgId 的值,它在HKEY_CLASSES_ROOT\https\shell\open\command 中找到了它需要的东西(在检查并未能在少数其他键中找到它之后)。虽然 Opera 被设置为默认浏览器,但该键中的 Default 值包含以下内容:

      "C:\Users\{username}\AppData\Local\Programs\Opera\launcher.exe" -noautoupdate -- "%1"
      

      我继续在 Windows 10 上对此进行了测试,它的行为有所不同——更符合 Steven 的回答。它在HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice 中找到了“OperaStable”ProgId 值。此外,Windows 10 计算机上的HKEY_CLASSES_ROOT\https\shell\open\command 键不将默认浏览器的命令行路径存储在HKEY_CLASSES_ROOT\https\shell\open\command 中——我发现那里的值是

      "C:\Program Files\Internet Explorer\iexplore.exe" %1
      

      以下是我根据我在 Process Monitor 中观察到的建议:

      先试试Steven的流程,如果HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice里面没有ProgID,那么看HKEY_CLASSES_ROOT\https\shell\open\command里面的默认值。当然,我不能保证这会起作用,主要是因为我在找到它之前看到它在一堆其他位置中查找。但是,如果我或其他人遇到不符合我描述的模型的场景,当然可以在此处改进和记录该算法。

      【讨论】:

        【解决方案8】:
            public void launchBrowser(string url)
            {
                using (RegistryKey userChoiceKey = Registry.CurrentUser.OpenSubKey(@"Software\Clients\StartMenuInternet"))
                {
                    var first = userChoiceKey?.GetSubKeyNames().FirstOrDefault();
                    if (userChoiceKey == null || first == null) return;
                    var reg = userChoiceKey.OpenSubKey(first + @"\shell\open\command");
                    var prog = (string)reg?.GetValue(null);
                    if (prog == null) return;
                    Process.Start(new ProcessStartInfo(prog, url));
                }
            }
        

        【讨论】:

          【解决方案9】:

          根据 rory.ap(下),我发现这适用于今天的 Windows 10 中的 Firefox、iexplore 和 edge。

          我在设置中检查了更改默认应用程序正确更改了注册表项。

          您可能会遇到 iexplore 和 edge 的 hmtl 文件名中的空格问题。所以“C#”在使用返回的字符串时会有所作为。

          private string FindBrowser()
          {
              using var key = Registry.CurrentUser.OpenSubKey(
                  @"SOFTWARE\Microsoft\Windows\Shell\Associations\URLAssociations\http\UserChoice");
              var s = (string) key?.GetValue("ProgId");
              using var command = Registry.ClassesRoot.OpenSubKey($"{s}\\shell\\open\\command");
              // command == null if not found
              // GetValue(null) for default value.
              // returned string looks like one of the following:
              // "C:\Program Files\Mozilla Firefox\firefox.exe" -osint -url "%1"
              // "C:\Program Files\Internet Explorer\iexplore.exe" %1
              // "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --single-argument %1
              return (string) command?.GetValue(null);
          }
          

          【讨论】:

            猜你喜欢
            • 2018-05-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-08-11
            • 1970-01-01
            • 2010-09-24
            相关资源
            最近更新 更多