在WebBrowser控件中使用最新版本的Internet Explorer

96

在C# Windows Forms应用程序中,WebBrowser控件的默认版本是7。我已经通过文章浏览器仿真将其更改为9,但如何在WebBrowser控件中使用安装的Internet Explorer的最新版本呢?

14个回答

107
我看到了Veer的回答,我认为他是正确的,但是对我没有用。也许我正在使用.NET 4并且使用64位操作系统,所以请检查一下。
您可以在安装程序中添加或在应用程序启动时进行检查:
private void Form1_Load(object sender, EventArgs e)
{
    var appName = Process.GetCurrentProcess().ProcessName + ".exe";
    SetIE8KeyforWebBrowserControl(appName);
}

private void SetIE8KeyforWebBrowserControl(string appName)
{
    RegistryKey Regkey = null;
    try
    {
        // For 64 bit machine
        if (Environment.Is64BitOperatingSystem)
            Regkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\\Wow6432Node\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", true);
        else  //For 32 bit machine
            Regkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", true);

        // If the path is not correct or
        // if the user haven't priviledges to access the registry
        if (Regkey == null)
        {
            MessageBox.Show("Application Settings Failed - Address Not found");
            return;
        }

        string FindAppkey = Convert.ToString(Regkey.GetValue(appName));

        // Check if key is already present
        if (FindAppkey == "8000")
        {
            MessageBox.Show("Required Application Settings Present");
            Regkey.Close();
            return;
        }

        // If a key is not present add the key, Key value 8000 (decimal)
        if (string.IsNullOrEmpty(FindAppkey))
            Regkey.SetValue(appName, unchecked((int)0x1F40), RegistryValueKind.DWord);

        // Check for the key after adding
        FindAppkey = Convert.ToString(Regkey.GetValue(appName));

        if (FindAppkey == "8000")
            MessageBox.Show("Application Settings Applied Successfully");
        else
            MessageBox.Show("Application Settings Failed, Ref: " + FindAppkey);
    }
    catch (Exception ex)
    {
        MessageBox.Show("Application Settings Failed");
        MessageBox.Show(ex.Message);
    }
    finally
    {
        // Close the Registry
        if (Regkey != null)
            Regkey.Close();
    }
}

您可能会发现messagebox.show仅供测试使用。

键如下所示:

  • 11001 (0x2AF9) - Internet Explorer 11。页面以IE11边缘模式显示,不考虑!DOCTYPE指令。

  • 11000 (0x2AF8) - Internet Explorer 11。包含基于标准的!DOCTYPE指令的网页以IE11边缘模式显示。IE11的默认值。

  • 10001 (0x2711)- Internet Explorer 10。不考虑!DOCTYPE指令,页面以IE10标准模式显示。

  • 10000 (0x2710)- Internet Explorer 10。包含基于标准的!DOCTYPE指令的网页以IE10标准模式显示。Internet Explorer 10的默认值。

  • 9999 (0x270F) - Internet Explorer 9。不考虑!DOCTYPE指令,页面以IE9标准模式显示。

  • 9000 (0x2328) - Internet Explorer 9。包含基于标准的!DOCTYPE指令的网页以IE9模式显示。

  • 8888 (0x22B8) - 网页以IE8标准模式显示,不考虑!DOCTYPE指令。

  • 8000 (0x1F40) - 包含基于标准的!DOCTYPE指令的网页以IE8模式显示。

  • 7000 (0x1B58) - 包含基于标准的!DOCTYPE指令的网页以IE7标准模式显示。

参考资料: MSDN:网页功能控件

我看到像Skype这样的应用程序使用10001,但我不知道为什么。

注意

安装程序将更改注册表。您可能需要在清单文件中添加一行以避免由于更改注册表权限而导致的错误:

<requestedExecutionLevel level="highestAvailable" uiAccess="false" />

更新 1

这是一个类,将获取 Windows 上的最新版本 IE,并进行应有的更改;

public class WebBrowserHelper
{


    public static int GetEmbVersion()
    {
        int ieVer = GetBrowserVersion();

        if (ieVer > 9)
            return ieVer * 1000 + 1;

        if (ieVer > 7)
            return ieVer * 1111;

        return 7000;
    } // End Function GetEmbVersion

    public static void FixBrowserVersion()
    {
        string appName = System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetExecutingAssembly().Location);
        FixBrowserVersion(appName);
    }

    public static void FixBrowserVersion(string appName)
    {
        FixBrowserVersion(appName, GetEmbVersion());
    } // End Sub FixBrowserVersion

    // FixBrowserVersion("<YourAppName>", 9000);
    public static void FixBrowserVersion(string appName, int ieVer)
    {
        FixBrowserVersion_Internal("HKEY_LOCAL_MACHINE", appName + ".exe", ieVer);
        FixBrowserVersion_Internal("HKEY_CURRENT_USER", appName + ".exe", ieVer);
        FixBrowserVersion_Internal("HKEY_LOCAL_MACHINE", appName + ".vshost.exe", ieVer);
        FixBrowserVersion_Internal("HKEY_CURRENT_USER", appName + ".vshost.exe", ieVer);
    } // End Sub FixBrowserVersion 

    private static void FixBrowserVersion_Internal(string root, string appName, int ieVer)
    {
        try
        {
            //For 64 bit Machine 
            if (Environment.Is64BitOperatingSystem)
                Microsoft.Win32.Registry.SetValue(root + @"\Software\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", appName, ieVer);
            else  //For 32 bit Machine 
                Microsoft.Win32.Registry.SetValue(root + @"\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", appName, ieVer);


        }
        catch (Exception)
        {
            // some config will hit access rights exceptions
            // this is why we try with both LOCAL_MACHINE and CURRENT_USER
        }
    } // End Sub FixBrowserVersion_Internal 

    public static int GetBrowserVersion()
    {
        // string strKeyPath = @"HKLM\SOFTWARE\Microsoft\Internet Explorer";
        string strKeyPath = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer";
        string[] ls = new string[] { "svcVersion", "svcUpdateVersion", "Version", "W2kVersion" };

        int maxVer = 0;
        for (int i = 0; i < ls.Length; ++i)
        {
            object objVal = Microsoft.Win32.Registry.GetValue(strKeyPath, ls[i], "0");
            string strVal = System.Convert.ToString(objVal);
            if (strVal != null)
            {
                int iPos = strVal.IndexOf('.');
                if (iPos > 0)
                    strVal = strVal.Substring(0, iPos);

                int res = 0;
                if (int.TryParse(strVal, out res))
                    maxVer = Math.Max(maxVer, res);
            } // End if (strVal != null)

        } // Next i

        return maxVer;
    } // End Function GetBrowserVersion 


}

使用类如下。
WebBrowserHelper.FixBrowserVersion();
WebBrowserHelper.FixBrowserVersion("SomeAppName");
WebBrowserHelper.FixBrowserVersion("SomeAppName",intIeVer);

您可能会遇到Windows 10不兼容的问题,这可能是由于您的网站本身导致的。您可能需要添加此元标记。

<meta http-equiv="X-UA-Compatible" content="IE=11" >

享受 :)


2
注册表重定向器通过在WOW64上提供某些部分的注册表的单独逻辑视图来隔离32位和64位应用程序。注册表重定向器拦截32位和64位注册表调用到它们各自的逻辑注册表视图,并将它们映射到相应的物理注册表位置。重定向过程对应用程序是透明的。因此,即使数据存储在64位Windows上的不同位置,32位应用程序也可以像在32位Windows上运行一样访问注册表数据。 - Luca Manzo
3
你也可以使用 HKEY_CURRENT_USER,无需管理员权限。 - Michael Chourdakis
6
建议更改 Environment.Is64BitOperatingSystemEnvironment.Is64BitProcess - CC Inc
1
@JobaDiniz,请查看更新1,它会帮助你的 :) - Mhmd
4
我知道这篇文章有点过时了,但是对于未来的读者:您的应用程序不需要检查它是否在64位系统中运行,甚至不需要检查其是否在64位进程中运行。64位版本的Windows实现了注册表重定向器,它会自动将在64位系统上运行的32位应用程序重定向到Wow6432Node子键。您的应用程序不需要做任何额外的工作来适应这个“新”的键。 - Visual Vincent
显示剩余4条评论

62

使用来自MSDN的数值:

  int BrowserVer, RegVal;

  // get the installed IE version
  using (WebBrowser Wb = new WebBrowser())
    BrowserVer = Wb.Version.Major;

  // set the appropriate IE version
  if (BrowserVer >= 11)
    RegVal = 11001;
  else if (BrowserVer == 10)
    RegVal = 10001;
  else if (BrowserVer == 9)
    RegVal = 9999;
  else if (BrowserVer == 8)
    RegVal = 8888;
  else
    RegVal = 7000;

  // set the actual key
  using (RegistryKey Key = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", RegistryKeyPermissionCheck.ReadWriteSubTree))
    if (Key.GetValue(System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe") == null)
      Key.SetValue(System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe", RegVal, RegistryValueKind.DWord);

1
老兄,这是一个更简单的获取版本的方法......谢谢,这对我很有用! - sfaust
谢谢,代码很好,只是应该使用CreateSubKey而不是OpenSubKey,因为如果键不存在,OpenSubKey将返回null。 - eug
太好了!我编辑了答案,使用了CreateSubKey并仅在未设置值时设置该值。 - RooiWillie
太棒了!非常感谢。这应该是最好的答案了。尝试了上面的庞然大物解决方案,但没有任何改变。这种方法解决了问题。再次感谢! - Matt
1
@MarkNS 好的,在这种情况下,您可以在写入之前进行空值检查和版本检查。这背后的逻辑很简单,就是避免不断地写入注册表,但如果您可以接受这一点,那么可以直接删除空值检查。 - RooiWillie
显示剩余2条评论

22
var appName = System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe";

using (var Key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", true))
    Key.SetValue(appName, 99999, RegistryValueKind.DWord);
根据我在这里阅读的内容 (控制WebBrowser控件兼容性):

如果我将FEATURE_BROWSER_EMULATION文档模式值设置为客户端IE版本更高会发生什么?

显然,浏览器控件只能支持小于或等于客户端安装的IE版本的文档模式。使用FEATURE_BROWSER_EMULATION键最适合企业线上业务应用程序,其中浏览器已部署并得到支持。 如果您将该值设置为一个高于客户端安装的浏览器版本的浏览器模式,则浏览器控件将选择可用的最高文档模式。

最简单的方法是输入非常大的十进制数...


1
注意:如果您在Win64上运行32位应用程序,则需要编辑的关键是在SOFTWARE\WOW6432Node\Microsoft...下。它在代码中自动重定向,但如果您打开了regedit,则可能会让您感到惊讶。 - toster-cx
1
对我来说,在Win2012服务器上以管理员身份运行,Registry.LocalMachine.OpenSubKey("..是有效的。 - bendecko
1
@bendecko,你的应用程序需要管理员权限。 - dovid
不要使用此解决方案,因为如果您使用navigate(到本地文件)并且您的HTML内容位于Intranet区域中(例如:使用MOTW到localhost),它将回退到IE7。使用99999与使用11000具有相同的行为。而要解决我上面提到的问题,您需要使用11001。 - Lenor

15

我不需要更改RegKey,我可以在HTML的头部插入一行代码:

<html>
    <head>
        <!-- Use lastest version of Internet Explorer -->
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />

        <!-- Insert other header tags here -->
    </head>
    ...
</html>

请查看Web浏览器控件和指定IE版本


1
虽然这种技术可行,但它不能提供相同的用户代理。使用“FEATURE_BROWSER_EMULATION”技术,我得到了“Mozilla/5.0(Windows NT 6.2;Win64;x64; ...”。而使用“X-UA-Compatible”技术,我得到了“Mozilla/4.0(compatible; MSIE 7.0; Windows NT 6.2; ...”,Google Analytics将其识别为移动设备。 - Benoit Blanchon
1
谢谢!当您只需要托管本地页面时(因此用户代理字符串完全无关紧要),它可以完美运行。 - realMarkusSchmidt

13
您可以尝试这个链接
try
{
    var IEVAlue =  9000; // can be: 9999 , 9000, 8888, 8000, 7000
    var targetApplication = Processes.getCurrentProcessName() + ".exe"; 
    var localMachine = Registry.LocalMachine;
    var parentKeyLocation = @"SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl";
    var keyName = "FEATURE_BROWSER_EMULATION";
    "opening up Key: {0} at {1}".info(keyName, parentKeyLocation);
    var subKey = localMachine.getOrCreateSubKey(parentKeyLocation,keyName,true);
    subKey.SetValue(targetApplication, IEVAlue,RegistryValueKind.DWord);
    return "all done, now try it on a new process".info();
}
catch(Exception ex)
{
    ex.log();
    "NOTE: you need to run this under no UAC".info();
}

string ver = (new WebBrowser()).Version.ToString();字符串 ver = (新的 WebBrowser()).Version.ToString(); - Veer
好的,我只是想在注册表中检查HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer,但这种方法更简单。谢谢。 - Moslem7026
5
Processes.getCurrentProcessName() 是什么?可能是 Process.GetCurrentProcess().ProcessName 吗? - SerG
1
localMachine.getOrCreateSubKey是什么?不存在吗? - TEK
2
你可以使用HKEY_CURRENT_USER,无需管理员权限。 - Michael Chourdakis
显示剩余2条评论

4

我能够实现Luca的解决方案,但是我需要做一些修改才能让它正常工作。我的目标是将D3.js与Windows Forms应用程序的Web浏览器控件结合使用(针对.NET 2.0)。现在它对我来说可以工作了。希望这能对其他人有所帮助。

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using Microsoft.Win32;
using System.Diagnostics;

namespace ClientUI
{
    static class Program
    {
        static Mutex mutex = new System.Threading.Mutex(false, "jMutex");

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            if (!mutex.WaitOne(TimeSpan.FromSeconds(2), false))
            {
                // Another application instance is running
                return;
            }
            try
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                var targetApplication = Process.GetCurrentProcess().ProcessName + ".exe";
                int ie_emulation = 11999;
                try
                {
                    string tmp = Properties.Settings.Default.ie_emulation;
                    ie_emulation = int.Parse(tmp);
                }
                catch { }
                SetIEVersioneKeyforWebBrowserControl(targetApplication, ie_emulation);

                Application.Run(new MainForm());
            }
            finally
            {
                mutex.ReleaseMutex();
            }
        }

        private static void SetIEVersioneKeyforWebBrowserControl(string appName, int ieval)
        {
            RegistryKey Regkey = null;
            try
            {
                Regkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", true);

                // If the path is not correct or
                // if user doesn't have privileges to access the registry
                if (Regkey == null)
                {
                    MessageBox.Show("Application FEATURE_BROWSER_EMULATION Failed - Registry key Not found");
                    return;
                }

                string FindAppkey = Convert.ToString(Regkey.GetValue(appName));

                // Check if key is already present
                if (FindAppkey == ieval.ToString())
                {
                    MessageBox.Show("Application FEATURE_BROWSER_EMULATION already set to " + ieval);
                    Regkey.Close();
                    return;
                }

                // If key is not present or different from desired, add/modify the key , key value
                Regkey.SetValue(appName, unchecked((int)ieval), RegistryValueKind.DWord);

                // Check for the key after adding
                FindAppkey = Convert.ToString(Regkey.GetValue(appName));

                if (FindAppkey == ieval.ToString())
                {
                    MessageBox.Show("Application FEATURE_BROWSER_EMULATION changed to " + ieval + "; changes will be visible at application restart");
                }
                else
                {
                    MessageBox.Show("Application FEATURE_BROWSER_EMULATION setting failed; current value is  " + ieval);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Application FEATURE_BROWSER_EMULATION setting failed; " + ex.Message);
            }
            finally
            {
                //Close the Registry
                if (Regkey != null) Regkey.Close();
            }
        }
    }
}

此外,我在项目设置中添加了一个字符串(ie_emulation),其值为11999。这个值似乎可以用于IE11(11.0.15)。

接下来,我需要更改应用程序的权限以允许访问注册表。这可以通过向您的项目添加新项(使用VS2012)来完成。在常规项目下,选择应用程序清单文件。将级别从asInvoker更改为requireAdministrator(如下所示)。

<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

如果您正在尝试使用webbrowser控件与D3.js一起使用,您可能需要修改JSON数据并将其存储在HTML页面内的变量中,因为D3.json使用XmlHttpRequest(更容易与web服务器一起使用)。经过这些更改和上述更改后,我的Windows表单能够加载调用D3的本地HTML文件。


4

这里是我通常使用的方法,适用于32位和64位应用程序;ie_emulation可以是任何在此处记录的文档:Internet Feature Controls (B..C), Browser Emulation

    [STAThread]
    static void Main()
    {
        if (!mutex.WaitOne(TimeSpan.FromSeconds(2), false))
        {
            // Another application instance is running
            return;
        }
        try
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            var targetApplication = Process.GetCurrentProcess().ProcessName  + ".exe";
            int ie_emulation = 10000;
            try
            {
                string tmp = Properties.Settings.Default.ie_emulation;
                ie_emulation = int.Parse(tmp);
            }
            catch { }
            SetIEVersioneKeyforWebBrowserControl(targetApplication, ie_emulation);

            m_webLoader = new FormMain();

            Application.Run(m_webLoader);
        }
        finally
        {
            mutex.ReleaseMutex();
        }
    }

    private static void SetIEVersioneKeyforWebBrowserControl(string appName, int ieval)
    {
        RegistryKey Regkey = null;
        try
        {
            Regkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION", true);

            // If the path is not correct or
            // if user haven't privileges to access the registry
            if (Regkey == null)
            {
                YukLoggerObj.logWarnMsg("Application FEATURE_BROWSER_EMULATION Failed - Registry key Not found");
                return;
            }

            string FindAppkey = Convert.ToString(Regkey.GetValue(appName));

            // Check if key is already present
            if (FindAppkey == "" + ieval)
            {
                YukLoggerObj.logInfoMsg("Application FEATURE_BROWSER_EMULATION already set to " + ieval);
                Regkey.Close();
                return;
            }

            // If a key is not present or different from desired, add/modify the key, key value
            Regkey.SetValue(appName, unchecked((int)ieval), RegistryValueKind.DWord);

            // Check for the key after adding
            FindAppkey = Convert.ToString(Regkey.GetValue(appName));

            if (FindAppkey == "" + ieval)
                YukLoggerObj.logInfoMsg("Application FEATURE_BROWSER_EMULATION changed to " + ieval + "; changes will be visible at application restart");
            else
                YukLoggerObj.logWarnMsg("Application FEATURE_BROWSER_EMULATION setting failed; current value is  " + ieval);
        }
        catch (Exception ex)
        {
            YukLoggerObj.logWarnMsg("Application FEATURE_BROWSER_EMULATION setting failed; " + ex.Message);

        }
        finally
        {
            // Close the Registry
            if (Regkey != null)
                Regkey.Close();
        }
    }

2

结合RooiWillie和MohD的答案,记得以管理员权限运行您的应用程序。

var appName = System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe";

RegistryKey Regkey = null;
try
{
    int BrowserVer, RegVal;

    // get the installed IE version
    using (WebBrowser Wb = new WebBrowser())
        BrowserVer = Wb.Version.Major;

    // set the appropriate IE version
    if (BrowserVer >= 11)
        RegVal = 11001;
    else if (BrowserVer == 10)
        RegVal = 10001;
    else if (BrowserVer == 9)
        RegVal = 9999;
    else if (BrowserVer == 8)
        RegVal = 8888;
    else
        RegVal = 7000;

    //For 64 bit Machine 
    if (Environment.Is64BitOperatingSystem)
        Regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"SOFTWARE\\Wow6432Node\\Microsoft\\Internet Explorer\\MAIN\\FeatureControl\\FEATURE_BROWSER_EMULATION", true);
    else  //For 32 bit Machine 
        Regkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", true);

    //If the path is not correct or 
    //If user't have priviledges to access registry 
    if (Regkey == null)
    {
        MessageBox.Show("Registry Key for setting IE WebBrowser Rendering Address Not found. Try run the program with administrator's right.");
        return;
    }

    string FindAppkey = Convert.ToString(Regkey.GetValue(appName));

    //Check if key is already present 
    if (FindAppkey == RegVal.ToString())
    {
        Regkey.Close();
        return;
    }

    Regkey.SetValue(appName, RegVal, RegistryValueKind.DWord);
}
catch (Exception ex)
{
    MessageBox.Show("Registry Key for setting IE WebBrowser Rendering failed to setup");
    MessageBox.Show(ex.Message);
}
finally
{
    //Close the Registry 
    if (Regkey != null)
        Regkey.Close();
}

1
正如之前所指出的,使用localmachine密钥注册会限制管理员安装应用程序,而当前用户密钥则允许普通用户安装应用程序。后者更加灵活。 - gg89

1
将以下内容添加到您的HTML中即可完成操作,无需进行注册表设置。
<meta http-equiv="X-UA-Compatible" content="IE=11" >

如何在 WebBrowser 中添加头部 meta 标签?我无法添加注册表,因为我的应用程序将作为独立的应用程序 Web 浏览器运行在用户帐户下。 - Luiey

1
一个便宜而简单的解决方法是,在FEATURE_BROWSER_EMULATION键中放置一个比11001大的值。然后它会使用系统中可用的最新IE版本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接