Introduction
A software system I was involved with a while ago had a WinForms 2.0 client that was designed to facilitate a user's navigation path through pages of target web sites, and therefore hosted a WebBrowser
control in the application. While most of the requirements of the system proved relatively easy to implement, several of them involved solutions that required some 'out of the square' techniques.
This article discusses one such problem area - suppressing various dialogs (including 'Security Alert' and 'Connect To ...' dialogs) - and demonstrates one possible approach to solving it.
As the article is marked 'Advanced' and the accompanying code is fairly extensively commented and reasonably self explanatory, I will not go into too much detail in the article here other than to outline the various techniques utilised in the solution.
Background
Occasionally, it is desirable to navigate a hosted WebBrowser
control to an SSL secured website which may serve, what the control determines, an invalid SSL certificate, for example, a company intranet site with a self-signed certificate. When the hosted WebBrowser
control (or more accurately, a lower level Win32 DLL) determines that an SSL certificate is invalid, it will display a Security alert dialog (i.e., a dialog with the text "Security Alert" in the caption), regardless of whether your application deems the website trusted or not. Obviously, it is not always desirable, or alternatively, there is simply no need, for the user to see this dialog, so we require a method by which to suppress the dialog from ever showing.
Along similar lines, you might have a target web page which requires user logon. Again, the normal (and fully reasonable) response by the WebBrowser
control is to display the user a dialog with which to enter their credentials (i.e., a dialog with the text "Connect To .." in the caption). But again, perhaps it is desirable to automate the logon process in your application and never bother the user with the dialog.
The solution to these problems lies in the use of 'Windows Hooks', some low-level functionality that is provided in the User32 DLL. Windows Hooks have been around for a long time, and importantly for this solution, what they provide for us is the ability to monitor Windows messages at a low level. Window Hooks are described in detail elsewhere (here and here, for example - also, simply Google it if you want more), so they will not be described further here.
Although .NET hides the gory details from us in layers of abstraction, the simple fact remains that when a dialog is about to be created/displayed, its message pump is sent a WM_INITDIALOG
Windows message. Upon receiving this message, a dialog generally prepares itself to be displayed/used, a process which includes setting up any child controls etc. etc.
Using the WH_CALLWNDPROCRET
style of Windows Hook, we can receive notification after a dialog message pump has processed the WM_INITDIALOG
message and discover various properties of the dialog (such as its caption text, text, or class of contained child controls etc.). Once the required information is acquired, we can perform different actions such as simulating user-clicks on buttons and disallowing further processing of the message - the combination of which prevents the dialog from ever being displayed.
In order to access information such as the text of a dialog's caption or that of one of its child controls or the like, we make use of the following exported functions in the User32 DLL - EnumChildWindows()
, GetWindowTextLength()
, GetWindowText()
, SetWindowText()
, GetClassName()
, GetDlgCtrlID()
, and SendMessage()
via the standard .NET Interop technology (i.e., DllImport). The signatures/descriptions of all of these functions are described in MSDN documentation, and most, if not all, have DllImport declarations at the pinvoke Web site.
Using the code
The VS2008 project (C#.NET 2.0) - downloadable using the link above - contains all of the required (and extensively commented) code, and can be tested by building and running the project. However, you must first fill in some values to test with before it will work:
- the URL of a site with an 'invalid' SSL certificate (e.g., https://mysite.mydomain.com) (see the
btnTestNoSecurityAlertDialog_Click()
event handler). - the URL of a site which requires Credentials for which you may want to perform auto logon (see the
btnTestNoCredentialsDialog_Click()
event handler). - a Username and Password (see the
WindowsInterop_ConnectToDialogWillBeShown()
event handler) (only if wanting to test/use #2).
Points of interest
Using Windows Hooks to post-process dialog initialization Windows messages.
History
- 23.11.2008 - Original article submission.