WebBrowser脚本错误的原因及Web Browser Control & Specifying the IE Version

最近想用 WebBrowser控件写个程序访问中国南方电网,以便查询各个网点停电计划停电信息,但发现报脚本错误,导致无法正常访问,而IE访问却无此问题。一开始抱着头疼医头,脚疼医脚的心态,想着怎么解决脚本错误的问题,无法解决之后想,IE无问题,那就是WebBrowser本身的问题了,想到之前也曾看过,说WebBrowser的工作模式并不是本机安装的IE正常模式,而是工作在保护模式,要想工作在本机IE模式,需要修改注册表。  报脚本错误,无论点击“是”或“否”,都无法访问相关功能,例如“停电查询”。图片 32位系统运行32位程序或64位系统运行64位程序,在这里修改: 图片 图片 图片 64位系统下的32位程序,在HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION 添加自己应用程序DWORD键,值改为2AF9。 图片现在可以正常访问中国南方电网了,但还有点奇怪的就是,点[登录]按钮出来的界面是空白的,无法登录,点[立即登录]就可以登录。 图片 以下为转的文章: Web Browser Control & Specifying the IE Version

updated Aug 26th, 2016 - the original was published in May 2011

I use the Internet Explorer Web Browser Control in a lot of my desktop applications to display document content. For example Markdown MonsterHelp Builder and WebSurge rely heavily on the Web Browser Control to render their document centric or even rich interactive UI (in the case of Markdown Monster which hosts an HTML editor). Whether you're just rendering document content, or you're interacting with rich interactive content, HTML happens to be one of the most common document formats to display or interact with and it makes a wonderful addition to conventional forms based UI. Even in desktop applications, is often way easier than using labels or edit boxes or even some of the WPF text containers. HTML is easy to generate, generally re-usable, and easily extensible and distributable. The Web Browser Control allows for an effective way to display HTML in your applications in a way that blends in and becomes part of your application.

But there's a snag: The Web Browser Control is - by default - perpetually stuck in IE 7 rendering mode. Even though we're now up to IE 11 and a reasonably HTML5 compatible browser, the Web Browser Control always uses the IE 7 rendering engine by default. This is because the original versions of the ActiveX control used this mode and for backwards compatibility the Control continues this outdated and very HTML5 unfriendly default.

This applies whether you’re using the Web Browser control in a WPF application, a WinForms app, or FoxPro application using the ActiveX control. Behind the scenes all these UI platforms use the same COM interfaces and so you’re stuck with those same rules.

The good news is there are a couple of ways to override the default rendering behavior:

  • Using the IE X-UA-Compatible Meta header
  • Using Application specific FEATURE_BROWSER_EMULATION Registry Keys

But first lets see the problem more graphically.

Rendering Challenged

To see what I’m talking about, here are two screen shots rendering an HTML5 page that includes some CSS3 functionality – rounded corners and border shadows - from an earlier post. One uses Internet Explorer as a standalone browser, and one uses a simple WPF form that includes the Web Browser control.

Full IE Browser:                                                                     Web Browser Control in a WPF form: 图片         图片

The the full Internet Explorer the page displays the HTML correctly – you see the rounded corners and shadow displayed. Obviously the latter rendering using the Web Browser control in a WPF application is a bit lacking. Not only are the new CSS features missing but the page also renders in Internet Explorer’s quirks mode so all the margins, padding etc. behave differently by default, even though there’s a CSS reset applied on this page. But the default IE 7 mode doesn't recognize many of these settings resulting in a terrible render mode.

If you’re building an application that intends to use the Web Browser control for a live preview of some HTML this is clearly undesirable.

Using the X-UA-Compatible HTML Meta Tag

If you control the content in your Web Browser control by rendering the HTML pages you display yourself, the easiest way to provide later versions of the IE rendering engine is by using the IE Edge mode header. By adding a meta tag to the head of the HTML document rendered in the Web Browser Control you can effectively override the IE Rendering engine and specify which version of IE (or the latest version) to use.

The tag to use in the header looks like  this:

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

Inside of a full document it looks like this:

<!DOCTYPE html> <html>   <head>     <meta http-equiv="X-UA-Compatible" content="IE=edge" />     ... other headers  </head>  <body>    ... content  </body></html>

Note the header should be the first header so that the engine is applied before any other headers are processed.

In this case IE=edge uses the current version of IE that is installed on the machine. So if you have IE 11 installed that's used, if IE 10 is installed that's used.

You can also specify a specific version of IE:

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

For info on all the modes available see this StackOverflow answer.

Alternately you can also serve X_UA_Compatible: IE=edge as a raw HTTP header from a Web server, which has the same behavior as the http-equiv meta header.

Caveats with the Edge Mode Header

There are a few things you need in order to use the meta tag and make it work properly:

  • You have to control the Page In order to add the <meta> tag you have to control the page so that you can add the <meta> tag into your HTML. If you're rendering arbitrary HTML that doesn't include the tag, then this approach won't work obviously. Typically the header approach works great if you generate your own content.

  • Browser Version Reporting is incorrect The <meta>tag changes the rendering engine behavior that IE uses, but it doesn't change the way that IE reports its version. If you access pages that do IE version checking you'll find that it still points at IE 7 (or sometime some custom browser version) that doesn't reflect the current rendering mode. If you're running script code that may rely on browser sniffing this can become a problem. I ran into this recently with Ace Editor, which has a couple of odd places where it uses browser sniffing for dealing with the clipboard, and that code wouldn't work. This is likely an edge (ha ha) case, but be aware that this can become a problem.

Feature Delegation via Registry Hacks

Another and perhaps more robust way to affect the Web Browser Control version is by using FEATURE_BROWSER_EMULATION. Starting with IE 8 Microsoft introduced registry entries that control browser behavior when a Web Browser Control is embedded into other applications. These registry values are used by many application on your system.

Essentially you can specify a registry with the name of your Executable and specify the version of IE that you would like to load. The numbers are specified as 11000, 10000, 9000, 8000 and 7000. The keys can be specified either for the current user (HKCU) or globally for all users (HKLM).

Here's what I have in my HKCU key: 图片

Notice some big applications like Visual Studio and Outlook use these overrides and at the HKLM keys you will also find apps like Skype SnagIt, Fiddler, SourceTree, 1Password and the Windows Help Viewer to name a few. So this feature is actually used by a wide range of popular software.

Registry Key Location for FEATURE_BROWSER EMULATION

You can specify these keys in the registry at:

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION

The HKCU key is the best place to set these values because there's a single key and it can be set without admin rights, but you can also set these keys at the machine level at HKLM:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION

or for a 32 bit application on a 64 bit machine:

HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION

Key Name

The keyname is the EXE name of your application like:

  • outlook.exe
  • MarkdownMonster.exe

Values

The value specifies the IE version as follows:

The value to set this key to is (taken from MSDN here) as decimal values:

11001 (0x2AF9) Internet Explorer 11. Webpages are displayed in IE11 Standards mode, regardless of the !DOCTYPE directive.

11000 (0x2AF8) Internet Explorer 11. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode.

10001 (0x2AF7) Internet Explorer 10. Webpages are displayed in IE10 Standards mode, regardless of the !DOCTYPE directive.

10000 (0x2710) Internet Explorer 10. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode.

9999 (0x270F) Internet Explorer 9. Webpages are displayed in IE9 Standards mode, regardless of the !DOCTYPE directive.

9000 (0x2328) Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode.

8888 (0x22B8) Webpages are displayed in IE8 Standards mode, regardless of the !DOCTYPE directive.

8000 (0x1F40) Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode.

7000 (0x1B58) Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode. This mode is kind of pointless since it's the default.

Setting these keys enables your applications to use the latest Internet Explorer versions on your machine easily. Unfortunately there doesn't seem to be a key that says use the latest version that's installed - you have to be specific regarding the version unfortunately. Given that Windows 7 and later can run IE 11, I'm requiring users to have IE 11 if I want to use HTML5 and more advanced CSS features like Flexbox, but if your content is simpler you can probably get away with using IE 10 or even IE 9.

Don’t forget to add Keys for Host Environments

As mentioned above you have to specify the name of the EXE you're running as the key in the registry.

If you're using a development environment like Visual Studio or Visual FoxPro to debug your applications, keep in mind that your main EXE you are running while debugging may not be the final EXE that you are building. So after you've set up your registry keys, your debugging experience may still not see the enhanced rendering features in the Web Browser control because you're not actually running the final EXE.

The problem is that when you debug in these environments, you are running a debugging host and in order for it to render properly you may have to the host to the FEATURE_BROWSER_EMULATION keys as well.

For Visual Studio this will be yourapp.vshost.exe, which is the debugging host. For Visual FoxPro you'll want vfp9.exe. Simply add these keys to the registry alongside those you use for your actual, live application.

Registry Key Installation for your Application

It’s important to remember that the registry settings from above are made per application, so most likely this is something you want to set up with your installer. I let my installers write the values into the registry during the install process which also removes the keys on uninstall.

Personally I always prefer setting this value per user using using the HKCU key.

If you set the keys globally on HKLM for all users, remember that 32 and 64 bit settings require separate settings in the registry. So if you’re creating your installer you most likely will want to set both keys in the registry preemptively for your application.

I use Tarma Installer for all of my application installs and in Tarma I configure registry keys for both and set a flag to only install the latter key group in the 64 bit version: 图片

Summary

It would be nice if the Web Browser Control would just use the native Internet Explorer engine as is, but as you see in this article, that's unfortunately not the case and you have to coerce the browser. If you have control over your documents that you render in the Web Browser Control you may be able to use X_UA_Compatible header in your pages. Otherwise you have to resort to the registry hack using FEATURE_BROWSER_EMULATION.

Personally I've used the registry hack for all of my apps that use the Web Browser Control because my applications tend to render HTML from all sorts of different sources - local generated content, as well as Web loaded pages for previews and sometimes even dynamically injected content. It's better to force the latest IE version for all content than forget the fact you need custom headers for other non-application content you might display (update notices, registration forms, notifications etc.)

These days most machines will be running either IE 10 or 11, so there's much less of a problem with differening browser behavior than there used to be.

Other Posts you might also like            

猜你喜欢

转载自my.oschina.net/u/2477950/blog/1606760