3

I am using .NET 4 and trying to use the desktop authentication for the StackApps site via the web-browser control (WPF and/or WinForms) to develop a NNTP Bridge for accessing StackOverflow (https://stackapps.com/questions/4215/stackapp-nntp-bridge-for-accessing-stackexchange-forums-like-stackoverflow).

It seems that the login cannot be done, because the web browser hangs up, after the page from "StackExchange Login" is displayed. I use the following URL: https://stackexchange.com/oauth/dialog?client_id=1736&scope=no_expiry&redirect_uri=https://stackexchange.com/oauth/login_success

It works in the normal IE browser, but not in a WinForms or WPF window... Does anyone know what the problem is?

It is simple to repoduce:

  1. Create a WinForms-Project
  2. Add the "WebBrowser" control to the dialog
  3. Double-Click on the Form1
  4. Add the following code

    private void Form1_Load(object sender, EventArgs e)
    {
      webBrowser1.Navigate("https://stackexchange.com/oauth/dialog?client_id=1736&scope=no_expiry&redirect_uri=https://stackexchange.com/oauth/login_success");
    }
    
  5. Start the application

  6. Login by pressing the "login with Stack Exchange" account symbol
  7. A new page gets loaded; it is displayed correctly, but you cannot enter your login name; the window hangs...

The same happens, if I use WPF-App and the WPF-WebBrowser-Control... it seems that it is stuck in an endless-loop in JavaScript...

Any hint on how to solve ths problem?

Or is it possible to debug the JavaScript in the WebBrowser-Control???

Community
  • 1
  • 1
Jochen Kalmbach
  • 3,549
  • 17
  • 18
  • Is anyone able t reproduce this issue? – Jochen Kalmbach Jul 28 '13 at 16:54
  • You can try this -> set property 'ScriptErrorsSuppressed' of your 'WebBrowser' control to 'True'. And if this is not helping, try updating your Internet Explorer to a newer version. After that, 'WebBrowser' control will use the newer version of IE and maybe it will be better. Just first two ideas:) I hope i helped. EDIT: this [link](http://stackoverflow.com/questions/14713596/how-to-add-the-firefox-and-chrome-to-c-sharp-browser-control) and this [link](http://stackoverflow.com/questions/2141668/use-chrome-as-browser-in-c) can help too. – Steven Jul 29 '13 at 09:56
  • I also tried setting the scriptErrorsSuppressed property; it does not change anything... also I have the latest version of IE on Win7... – Jochen Kalmbach Jul 29 '13 at 10:29
  • And what about links leading to IE WebBrowser control alternatives (Firefox core, Chrome core)? If you insist on using the IE then my apologize. I do not know how to help further. EDIT: For example gecko for Firefox WebBrowser core in your app: https://code.google.com/p/geckofx/ – Steven Jul 29 '13 at 13:32
  • I will try alternatives... But mostly they are not very easy to deploy... i will take a look and check it out.... but it would be also good, if the page would solve the javascript endless loop ;) – Jochen Kalmbach Jul 29 '13 at 15:12
  • It's already a year and a half since this was asked. I don't know if it's solved for .NET, but in Delphi I've still got the same issue using a TWebBrowser. I'm aware that there is a [duplicate of this question on StackApps](http://stackapps.com/questions/4244/desktop-login-url-webbrowser-hangs-net-javascript-endless-loop), but since I don't have enough rep there, I'll start a bounty here. – GolezTrol Dec 20 '14 at 19:20
  • If you are using WPF you can try using Awesomium - it is a browser control with lots of cool features based on Chrome. Also you never said what version of IE you are using, because that could have a great impact. Have you tried doing the same thing in Internet Explorer and seeing if you have problems there? – Phoenix Dec 20 '14 at 22:21
  • @Phoenix Thanks, I have, I put my findings (and a work-around) in [my answer below](http://stackoverflow.com/a/27585156/511529). – GolezTrol Dec 21 '14 at 17:07
  • @GolezTrol do you see any error windows when form is loaded ? – Mairaj Ahmad Dec 23 '14 at 09:10
  • Duplicate of: http://stackoverflow.com/questions/6717055/how-do-i-turn-off-compatibility-view-on-the-ie-webbrowsercontrol-in-a-winforms-a – kjbartel Dec 24 '14 at 00:51
  • @kjbartel That answer might be a work-around for this question, but the question is not a duplicate at all and there might be other solutions as well to really solve it. – GolezTrol Dec 25 '14 at 07:12
  • @GolezTrol No they are exactly the same. You are asking how to use a website which requires a newer IE engine to work in the native IE [webbrowser control](http://msdn.microsoft.com/en-us/library/aa752040(v=vs.85).aspx) which defaults to compatibility view. .Net has wrappers for the control and I assume Delphi also, but it's still the same underlying control. How does changing the website make this a different question? All the answers will be exactly the same. – kjbartel Dec 25 '14 at 23:53
  • First of all *I* didn't ask this at all, although I captured this question a bit, because I had the same issue. The question here is *"Why does the StackExchange login hang in a WebBrowser control and not in a real web browser and how can I solve it."* There is no mention of a website that needs a newer IE, because that fact was apparently unknown. Actually, I found that out and described that in my answer (which is indeed mine), but because the answer is similar, doesn't mean that the question is too. `Sqrt(25)` is not the same question as `2+3`. – GolezTrol Dec 26 '14 at 07:48

3 Answers3

2

Fixing WebBrowser Control

I also had the issue of the WebBrowser control handing when trying to login.

Although requesting a token in IE (11) works, I found that IE itself also hangs when I put it in IE 7 emulation mode. This suggested to me that my previous attempt to make the WebBrowser control use a newer version had failed.

I found this article, Web Browser Control Specifying the IE Version, which suggests that for 32 bit applications in 64 bit mode, you need to set a different registry value.

So now, I've added two values in the registry:

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

and

HKEY_CURRENT_USER\Software\Wow6432Node\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION

In both of them, I added a DWORD value named 'MyExecutable.exe' (where MyExecutable is the actual name of my executable). The value for each of them is 9000 which will work for IE9 and above. Watch out when using RegEdit to test this, it will default to hexadecimal instead of decimal. Also, make sure it is a DWORD value, not any other type.

This seems to do the trick. I can now run the application, go through the login process, and eventually I am redirected to the url specified by me, which I can then capture using the OnNavigate event of the webbrowser control.

Remaining issue

It doesn't really work perfectly. The first time I was redirected to some OpenID page as well, but at least the form didn't hang. With subsequent attempts, apparently the login (which succeeded before) is remembered and I get the message "Navigation to the webpage was cancelled" with a link to refresh the page. When I click that link, I am immediately redirected to the redirect_url I specified when requesting the login form. At least that part works, and I get an actual access_token and an expiry time, so for now I'm happy.

Update: After some testing, it turned out that the previous login was remembered. That causes the request uri to direct to the redirect_uri immediately. I used the OnBeforeNavigate event to detect this, but it isn't fired in this case. I now linked the NavigateComplete2 event, and that one is triggered in this scenario.

Fix for .NET?

I think for .NET the solution should be the same: add the executable (and MyExecutabl.vshost.exe as well, for debugging purposes in Visual Studio) to the first key. If it's a 32 bit executable running on 62 bit Windows, you might also need to add it to the second key, although I'm sure if that rule applies to .NET as well. I don't do C# on a daily basis, and I'm trying to get it to work in Delphi first, but if I find time to test this in C# I will post the update here.

In the end, it would be nice if the actual issue would be solved, and the JavaScript would work in IE7 mode as well, but at least this seems to be a proper work-around.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
1

Unfortunately, I'm not a JavaScript developer, so I only could try to explain you how to debug a JavaScript that executes in the WebBrowser control.

This approach is for the Microsoft Visual Studio, I don't know if Delphi can provide similar functionality.

  1. Enable Script Debugging (both Internet Explorer and Other) in Internet Explorer settings.
  2. Disable Friendly HTTP messages in Internet Explorer settings.
  3. Enable Display a notification about every script error in Internet Explorer settings.
  4. From Visual Studio, start your WebBrowser hosting application without debugging (i. e., Ctrl + F5).
  5. In Visual Studio, go to Debug → Attach to Process… and select your application in the list.
  6. Hit the Select… button to the right of Attach to: field and choose Script code.
  7. Hit the Attach button. Visual Studio starts the script debugger.
  8. In your application, navigate to the deadlocking page by pressing the Login with Stack Exchange account symbol.
  9. Go to Visual Studio and press the Pause button on the debugging toolbar.

Now you can look into your script code and investigate the code itself, the call stack, the variable values and so on. You can set breakpoints too. Perhaps you can then find the place where the script hangs. As I said before, I'm not a web developer and cannot help you with this…

Update:

I guess I can propose you a working solution. My investigation shows that the WebBrowser hangs when it renders the content in the IE7 mode (what is the default mode even if you have IE10 in your system). You should force it to switch into IE9 mode. In IE9 mode, the page renders well and does not cause the script to stuck in an endless loop.

You can switch your WebBrowser to the IE9 mode using one of the following methods:

  1. Define the global browser emulation mode for your application in Windows registry.

For 32 bit OS, go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION.

For 64 bit OS, use HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION.

In this node, create a new DWORD parameter called YourApplicationExeName.exe with a value 9000 (0x2710). You can create another entries for your *.vshost.exe executables, if you want this to work in Visual Studio debug mode.

  1. Manipulate the source for the WebBrowser to switch it in the IE9 mode.

This will be more complicated. You need to alter the <head> tag of the html document adding a new <meta> tag preferably as a first element: <meta http-equiv="X-UA-Compatible" content="IE=9"/>. This will cause the WebBrowser to switch its mode on document rendering. Since you can't change the compatibility mode after the document is rendered, you could use a proxy as a source for your WebBrowser, so this proxy will add the header.

I`ve successfully tested this with the 1st approach, and the second one should work too. Hope that helps!

shaedrich
  • 5,457
  • 3
  • 26
  • 42
dymanoid
  • 14,771
  • 4
  • 36
  • 64
  • Thanks, I may try this, but even if I found a bug, I wouldn't know how to solve this, since this script is part of the StackApp/StackExchange login form. – GolezTrol Dec 20 '14 at 20:17
  • Maybe you then know what you could change in your browser settings etc. so the script doesn't stuck in the endless loop. – dymanoid Dec 20 '14 at 20:20
  • Just updated the answer with a proposed solution, which I've successfully tested on my machine. – dymanoid Dec 21 '14 at 16:42
  • Thanks, I found out about option 1 myself and put it in an answer. I don't really know how to test option 2, but it seems a cumbersome approach relative to 1. Thanks for all your effort! – GolezTrol Dec 21 '14 at 17:05
0

Project + Properties, Debug tab, tick the "Enable native code debugging" option. Ensure that you've got the Microsoft Symbol server enabled (Tools + Options, Debugging, Symbols), I know you do :)

You can now use Debug + Break All and see what's going on inside the browser. Do so repeatedly to get the lay of the land. You'll see that Javascript is executing (jscript8.dll) and constantly forcing the layout engine to recalculate layout, never getting the job done.

Browsers in general are vulnerable to Javascript that's stuck in an endless loop. A regular browser tends to put up a dialog after several dozen seconds to allow the user to abort the JS, but WebBrowser doesn't have that feature. Nor does it have the dev tools so debugging the JS isn't going to be a great joy either. This is going to be difficult to get fixed.

You might consider using the OAuth 2.0 api instead. Notes on usage are on this web page. Exactly how to integrate that with WebBrowser is a bit murky to me, I don't have a key to test this. Find help for this at the Stackapps site. You are probably not the first SE api user that ran into this problem.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I already asked in the stackapps site: http://stackapps.com/questions/4244/desktop-login-webbrowser-hangs-net but they redirecte me to C# ;) so I will try again to ask there for help... it seems so that desktop-authentication is not used very often... and maybe not under Windows.... I also tried IE compatibility-ode, but maybe I used the worng values.... – Jochen Kalmbach Jul 27 '13 at 17:25
  • I have no idea how to use OAuth directly... also I do not know if this is even supported... as far as I see is the login done in the server, and therefor always an url needed... It would be great if you have any links... – Jochen Kalmbach Jul 27 '13 at 18:18