WinformsアプリケーションでWebBrowserコントロールのUserAgentを変更しようとしています。
次のコードを使用して、これを正常に達成しました。
[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()
{
List<string> userAgent = new List<string>();
string ua = "Googlebot/2.1 (+http://www.google.com/bot.html)";
UrlMkSetSessionOption(URLMON_OPTION_USERAGENT, ua, ua.Length, 0);
}
唯一の問題は、これが一度しか機能しないことです。 ChangeUserAgent()メソッドを2回目に実行しようとしても機能しません。最初に変更された値に設定されたままになります。これは非常に迷惑であり、私はすべてを試してみましたが、それは一度だけ変更されません。
誰もが別のより柔軟なアプローチを知っていますか?
ありがとう
website からコピー/貼り付けするだけかどうかはわかりませんが、リンクではなく答えをここに残したいです。誰もがコメントで明確にすることができれば、私は多くの義務を負います。
基本的に、WebBrowserクラスを拡張する必要があります。
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;
}
}
}
}
注:上記の方法を使用するには、COM参照を「Microsoft Internet Controls」に追加する必要があります。
彼はあなたのアプローチにも言及し、WebBrowserコントロールはこのユーザーエージェント文字列をキャッシュするように見えるため、プロセスを再起動しない限りユーザーエージェントを変更しないと述べています。
最も簡単な方法:
webBrowser.Navigate("http://localhost/run.php", null, null,
"User-Agent: Here Put The User Agent");
また、関数には更新オプションがあります( [〜#〜] msdn [〜#〜] に準拠)。私にとってはうまくいきました(ユーザーエージェントを変更する前に設定する必要があります)。その後、質問コードは次のように変更できます。
[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;
const int URLMON_OPTION_USERAGENT_REFRESH = 0x10000002;
public void ChangeUserAgent()
{
string ua = "Googlebot/2.1 (+http://www.google.com/bot.html)";
UrlMkSetSessionOption(URLMON_OPTION_USERAGENT_REFRESH, null, 0, 0);
UrlMkSetSessionOption(URLMON_OPTION_USERAGENT, ua, ua.Length, 0);
}
@Jean Azzopardiの回答に追加したいと思います。
void BeforeNavigate(object pDisp, ref object url, ref object flags, ref object targetFrameName,
ref object postData, ref object headers, ref bool cancel)
{
// This alone is sufficient, because headers is a "Ref" parameters, and the browser seems to pick this back up.
headers += string.Format("User-Agent: {0}\r\n", UserAgent);
}
このソリューションは私に最適です。再ナビゲートを使用すると、ブラウザのコンテンツが突然消えたり、サポートされていないブラウザが表示されたりするなど、他の奇妙な問題が発生しました。この手法では、Fiddlerのすべてのリクエストに正しいユーザーエージェントが含まれていました。