1

I need to host an online payment gateway in a Browser control in Framework 4.5 and have come across the problem where the CSS is not applied correctly or indeed at all.

I have been through all of the options here with no luck and have tried to use the Navigate override detailed here and shown below where the page renders properly but is popped in a new browser window.

browser.Navigate(url, "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">");

What I'm looking to do is make some webservice calls dependent on what control the user clicks in so I have tapped into the MouseDown event.

I've also tried a WPF app with no luck to see if the Browser control is different.

I'm waiting to see if the payment gateway guys can supply me with the CSS so I can apply it manually but in the meantime does anyone have any other suggestions ?

**** UPDATE ****

Have tried the suggestions below with no luck.

I have also tried this Internet Explorer Local Machine Zone Lockdown to see if it made any differences and it didn't.

***** Further Update ***** I'm getting the following error about the certificate at this site :

Certificate Error

And also a JavaScript errors advising me that AddEvent is not supported. I'm wondering if this is the failed browser emulation ?

Another update

In realtion to the above I followed Noseratio's excellent advice and added the following:

SetBrowserFeatureControlKey("FEATURE_WARN_ON_SEC_CERT_REV_FAILED", fileName, 0); 

This feature is not supported for applications hosting the WebBrowser Control.

Community
  • 1
  • 1
SteveB
  • 1,474
  • 1
  • 13
  • 21

1 Answers1

3

Usually, implementing FEATURE_BROWSER_EMULATION resolves issues like this, but you mentioned you already did that. I could share a test app if you like to try it with your own HTML+CSS.

using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WbTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            SetBrowserFeatureControl();
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            DoNavigationAsync().ContinueWith(_ =>
            {
                MessageBox.Show("Navigation complete!");
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }

        private async Task DoNavigationAsync()
        {
            TaskCompletionSource<bool> documentCompleteTcs = null;

            WebBrowserDocumentCompletedEventHandler handler = delegate 
            {
                if (documentCompleteTcs.Task.IsCompleted)
                    return;
                documentCompleteTcs.SetResult(true);
            };

            documentCompleteTcs = new TaskCompletionSource<bool>();
            this.wb.DocumentCompleted += handler;

            // could do this.wb.Navigate(url) here 
            this.wb.DocumentText = "<!DOCTYPE html><head><meta http-equiv='X-UA-Compatible' content='IE=edge'/></head>"+
                "<body><input size=50 type='text' placeholder='HTML5 if this placeholder is visible'/></body>";

            await documentCompleteTcs.Task;
            this.wb.DocumentCompleted -= handler;

            dynamic document = this.wb.Document.DomDocument;
            dynamic navigator = document.parentWindow.navigator;
            var info =
                "\n navigator.userAgent: " + navigator.userAgent +
                "\n navigator.appName: " + navigator.appName +
                "\n document.documentMode: " + document.documentMode +
                "\n document.compatMode: " + document.compatMode;

            MessageBox.Show(info);
        }

        private static void SetBrowserFeatureControl()
        {
            // http://msdn.microsoft.com/en-us/library/ee330720(v=vs.85).aspx

            // WebBrowser Feature Control settings are per-process
            var fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);

            // make the control is not running inside Visual Studio Designer
            if (String.Compare(fileName, "devenv.exe", true) == 0 || String.Compare(fileName, "XDesProc.exe", true) == 0)
                return;

            SetBrowserFeatureControlKey("FEATURE_BROWSER_EMULATION", fileName, GetBrowserEmulationMode()); 
        }

        private static void SetBrowserFeatureControlKey(string feature, string appName, uint value)
        {
            using (var key = Registry.CurrentUser.CreateSubKey(
                String.Concat(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\", feature),
                RegistryKeyPermissionCheck.ReadWriteSubTree))
            {
                key.SetValue(appName, (UInt32)value, RegistryValueKind.DWord);
            }
        }

        private static UInt32 GetBrowserEmulationMode()
        {
            int browserVersion = 7;
            using (var ieKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Internet Explorer",
                RegistryKeyPermissionCheck.ReadSubTree,
                System.Security.AccessControl.RegistryRights.QueryValues))
            {
                var version = ieKey.GetValue("svcVersion");
                if (null == version)
                {
                    version = ieKey.GetValue("Version");
                    if (null == version)
                        throw new ApplicationException("Microsoft Internet Explorer is required!");
                }
                int.TryParse(version.ToString().Split('.')[0], out browserVersion);
            }

            // Internet Explorer 10. Webpages containing standards-based !DOCTYPE directives are displayed in IE10 Standards mode. Default value for Internet Explorer 10.
            UInt32 mode = 10000; 

            switch (browserVersion)
            {
                case 7:
                    // Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode. Default value for applications hosting the WebBrowser Control.
                    mode = 7000;                     
                    break;
                case 8:
                    // Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode. Default value for Internet Explorer 8
                    mode = 8000; 
                    break;
                case 9:
                    // Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode. Default value for Internet Explorer 9.
                    mode = 9000; 
                    break;
                default:
                    // use IE10 mode by default
                    break;
            }

            return mode;
        }
    }
}

First, try it as is, you should see something like this:

enter image description here

Note documentMode and compatMode values, these correspond to HTML5 standard mode. Then try it with your HTML, see if they stay the same.

noseratio
  • 59,932
  • 34
  • 208
  • 486
  • Thanks Noseratio. I tried your suggestion still with no luck. My code is slightly different to yours in that I don't do an asynchronous call. I do, however, get the same values as in your message box. I need to trap the mouse events in the browser window so don't want it displayed in a new window completely. What is the reason it checks to see if it is running in visual studio ? Does it make a difference if I'm going to an SSL address ? Also - the machines are locked down here and IE is also locked down - would that make a difference ? – SteveB Sep 03 '13 at 08:54
  • I've added a comment to my original post to make sure all of the things tried are captured in the same place. – SteveB Sep 03 '13 at 09:19
  • Is your HTML content served locally via `file://` protocol? – noseratio Sep 03 '13 at 09:23
  • I check for VS processes to avoid putting their names in the registry for WB feature control (e.g., VS designer can be a separate process which still runs your C# code). There should be no difference for `HTTPS://` (but `FILE://` is not OK by default). Try other [fetures](http://stackoverflow.com/questions/18333459/c-sharp-webbrowser-ajax-call/18333982#18333982), maybe you'll find the combination which works for you. Basically, the rule is, set [each feature](http://msdn.microsoft.com/en-us/library/ee330720%28v=vs.85%29.aspx) to the same value it has for full IE browser by default. – noseratio Sep 03 '13 at 10:07
  • No - the HTML is served remotely from an online payment system via `HTTPS://`. I copied your code from the link above and JS error is gone - I'll look through the list and see if any of the restrictions relate to `CSS`. I can add `CSS` style elements to the `HEADER` and they render correctly. – SteveB Sep 03 '13 at 10:25
  • There's more features [documented on MSDN](http://msdn.microsoft.com/en-us/library/ee330720%28v=vs.85%29.aspx) than used in my linked sample. Try them all and set them to the IE default values as per docs. IIRC, there's one to control certificates too. – noseratio Sep 03 '13 at 10:30
  • This is really strange now. After adding a value of 0 for `SetBrowserFeatureControlKey("FEATURE_WARN_ON_SEC_CERT_REV_FAILED", fileName, 0);` I am still getting the same error. The key is there in the registry but seems to be ignored ? – SteveB Sep 03 '13 at 11:00
  • You could try [CoInternetSetFeatureEnabled](http://www.pinvoke.net/default.aspx/urlmon.cointernetsetfeatureenabled) instead of the registry (I haven't tried it yet). – noseratio Sep 03 '13 at 11:10
  • LOL. I have no idea how I would use this. – SteveB Sep 03 '13 at 11:34
  • I'll come up with some code and update the answer, as time allows. – noseratio Sep 03 '13 at 11:39
  • Thanks - really appreciate your effort here. I've just checked with Awesomium (terrible name but great component) and the page loaded first time. If the client can stretch to $2900 I'll post an update. I suspect not. – SteveB Sep 03 '13 at 12:29
  • No worries. You don't have to stick with Awesonium, CEF may also be a [viable choice](http://stackoverflow.com/questions/18119125/options-for-embedding-chromium-instead-of-ie-webbrowser-control-with-wpf-c). – noseratio Sep 03 '13 at 12:32
  • Awesomium was in pole position. It rendered the page perfectly but then simply does not trap the mouse events. No events would fire at all. I'm beginning to think this project is cursed – SteveB Sep 03 '13 at 17:05
  • 1
    this was a great help – Ryan Loggerythm Dec 17 '14 at 19:58