Tuesday, December 1, 2009

Changing the User Agent in IE (.NET WebBrowser Control) Via C#

I’ve read a lot about this topic over the last couple hours, and all information I found seemed to be going about it the wrong way. Many people suggest changing the registry, but from what I tried it seemed to only allow you to change certain parts of the user agent, instead of the whole string. If you’re interested in this, you’ll want to change:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\User Agent

Changing part of the User Agent wasn’t the goal though. The next idea I came across was that the WebBrowser.Navigate method took a headers string option that let you inject your own user agent into it. This would be useful if I was using the Navigate method instead of allowing users to click links and submit forms on pages. Luckily I ran into a COM method that lets you intercept all navigations, by form submits, link clicks, or anything else. Using this method, we can cancel the current navigation before it happens, edit the headers, and start the navigation again. I have extended the WebBrowser class so it allows simply setting of the UserAgent property to allow this.

public class ExtendedWebBrowser : WebBrowser

{

bool renavigating = false;



public string UserAgent { get; set; }



public ExtendedWebBrowser()

{

DocumentCompleted += SetupBrowser;



//this will cause SetupBrowser to run (we need a document object)

Navigate("about:blank");

}



void SetupBrowser(object sender, WebBrowserDocumentCompletedEventArgs e)

{

DocumentCompleted -= SetupBrowser;

SHDocVw.WebBrowser xBrowser = (SHDocVw.WebBrowser)ActiveXInstance;

xBrowser.BeforeNavigate2 += BeforeNavigate;

DocumentCompleted += PageLoaded;

}



void PageLoaded(object sender, WebBrowserDocumentCompletedEventArgs e)

{



}



void BeforeNavigate(object pDisp, ref object url, ref object flags, ref object targetFrameName,

ref object postData, ref object headers, ref bool cancel)

{

if (!string.IsNullOrEmpty(UserAgent))

{

if (!renavigating)

{

headers += string.Format("User-Agent: {0}\r\n", UserAgent);

renavigating = true;

cancel = true;

Navigate((string)url, (string)targetFrameName, (byte[])postData, (string)headers);

}

else

{

renavigating = false;

}

}

}

}

Note: To use the method above you’ll need to add a COM reference to “Microsoft Internet Controls”.

I also stumbled across a PInvoke method that had a simpler solution. The following code shows how to change the user agent for the WebBrowser control to GoogleBot’s user agent.

[DllImport("urlmon.dll", CharSet = CharSet.Ansi)]

private static extern int UrlMkSetSessionOption(int dwOption, string pBuffer, int dwBufferLength, int dwReserved);



const int URLMON_OPTION_USERAGENT = 0x10000001;



public void ChangeUserAgent()

{

string ua = "Googlebot/2.1 (+http://www.google.com/bot.html)";

UrlMkSetSessionOption(URLMON_OPTION_USERAGENT, ua, ua.Length, 0);

}

After calling that method, you can just use your WebBrowser as normal. All pages it navigates to will use the user agent you specified. For more information, you can check out the documentation on UrlMkSetSessionOption . The only problem with this method is that the WebBrowser control seems to cache this user agent string, so it will not change the user agent without restarting the process.

1 comment:

arleyschrock@gmail.com said...

When using UrlMkSetSessionOption, you need to call it twice, once with URLMON_OPTION_USERAGENT and once with URLMON_OPTION_USERAGENT_REFRESH