Изменение пользовательского агента элемента управления WebBrowser

Я пытаюсь изменить UserAgent элемента управления WebBrowser в приложении Winforms.

Я успешно добился этого, используя следующий код:

[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 () во второй раз, он не работает. Он остается установленным на первое измененное значение. Это очень раздражает, я все перепробовал, но больше одного раза это не изменится.

Кто-нибудь знает другой, более гибкий подход?

Спасибо


person Proximo    schedule 02.06.2009    source источник
comment
Я пробовал описанный выше метод, но он не работал для WPF (System.Windows.Controls.WebBrowser)   -  person Jader Dias    schedule 05.04.2010


Ответы (4)


Я не уверен, следует ли мне просто скопировать / вставить из 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, похоже, кэширует эту строку пользовательского агента, поэтому он не изменит пользовательский агент без перезапуска процесса.

person Jean Azzopardi    schedule 02.06.2009
comment
Есть ли способ перезапустить процесс, возможно, с помощью потоковой передачи? У меня ограниченный опыт работы с winforms. - person Proximo; 02.06.2009
comment
Я не уверен, я бы попробовал сам, но думаю, что подход, который я дал в своем ответе, должен сработать. Хотя это менее элегантно. Мне также интересно, можно ли удалить элемент управления и создать новый во время выполнения, но я думаю, что это может быть немного дороже. - person Jean Azzopardi; 02.06.2009
comment
Я действительно добавил этот класс в свой проект, и он вообще не работал. Итак, теперь я думаю, мне нужно попробовать перезапустить процессный подход. - person Proximo; 02.06.2009
comment
ссылка сейчас недействительна. Так что да, почти два года спустя копирование и вставка оказались правильным решением :) - person Courtney Christensen; 29.03.2011
comment
@zourtney, хех, в конце концов, это окупилось! - person Jean Azzopardi; 29.03.2011
comment
Я делаю это (код отличается от вашего) в течение многих лет, нет необходимости перезагружать, нет необходимости использовать msinet.ocx (Ms Internet Controls) ... если вам все еще нужен код, дайте мне знать, и я могу показать вам как это сделать. на самом деле я могу заставить его работать даже с Visual Studio 6.0 :). - person Erx_VB.NExT.Coder; 25.01.2012
comment
Есть еще способ сделать это? По-видимому, WPF-вариант WebBrowser запечатан и не может использоваться таким образом. - person Andreas; 31.12.2013
comment
BeforeNavigate2 не срабатывает, если элемент управления размещен в приложении .net support.microsoft.com/kb/325079 - person grzegorz_p; 11.11.2014
comment
Что это SHDocVw.WebBrowser xBrowser = (SHDocVw.WebBrowser)ActiveXInstance ?? - person developerwjk; 11.04.2017
comment
@Andreas, ты можешь using System.Windows.Forms; вместо using System.Windows.Controls; - person vinsa; 08.07.2018

Самый простой способ:

webBrowser.Navigate("http://localhost/run.php", null, null,
                    "User-Agent: Here Put The User Agent");
person Constantin    schedule 23.09.2011
comment
вы должны завершить настраиваемый заголовок с помощью \r\n - person Smith; 10.07.2012
comment
Если элемент управления веб-обозревателя уходит от этого URI (при нажатии на ссылку или перемещении назад / вперед), пользовательский агент сбрасывается. В идеале это решение должно работать для всех запросов, которые выполняет элемент управления. - person monzonj; 02.08.2013
comment
Он работает только для исходного запроса, переданного в Navigate - все вызовы AJAX на веб-сайте по-прежнему будут использовать UA по умолчанию для элемента управления. - person grzegorz_p; 11.11.2014
comment
@Constantin Веб-браузер автоматически откроет мой браузер по умолчанию с URL-адресом, когда я использую этот код в своем проекте. Я просто хочу, чтобы веб-страница загружалась в веб-браузер, но открыла дополнительный браузер. Я что-то пропустил в своем коде? browser.Navigate(url, "User-Agent:Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Mobile Safari/537.36"); - person 劉鎮瑲; 22.05.2019

Кроме того, в функции есть опция обновления (согласно 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);
}
person natenho    schedule 06.08.2013
comment
почему вы не используете переменную userAgent? - person Sebastian; 08.01.2014
comment
Он был извлечен из моего собственного кода, его там быть не должно. Спасибо, что указали на это. - person natenho; 09.01.2014
comment
Принятый ответ не будет работать, если вы, например, входите в Facebook и вам нужно получить разрешение от пользователя (повторная навигация вызывает проблемы). Итак, создайте встроенный браузер и используйте URLMON_OPTION_USERAGENT_REFRESH, затем URLMON_OPTION_USERAGENT, чтобы установить свой пользовательский UA. Как указано выше, повторяйте по мере необходимости или только установите URLMON_OPTION_USERAGENT_REFRESH, чтобы вернуться к IE UA по умолчанию. - person ; 23.04.2014
comment
Оглядываясь назад, я должен сказать, что мне понравился этот ответ, жаль, что уже на 4 года позже :) - person Proximo; 23.03.2015
comment
Так легко. Спасибо! :) - person Jack; 23.07.2015
comment
просто примечание, если вы используете формы, запускайте перед InitializeComponent (); - person toster-cx; 23.01.2016
comment
Он отлично работает в Windows 7 и 10 даже с проверенной учетной записью гостя. Сначала вызовите ChangeUserAgent () в своем приложении, и тогда вы будете готовы использовать новый UA. Повторяйте каждый раз во время выполнения. Будьте осторожны - библиотеки, такие как jquery, не могут работать должным образом, потому что они используют разные методы для браузеров IE. - person vinsa; 10.07.2018

Я хотел бы добавить к ответу @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 имели правильный пользовательский агент.

person harsimranb    schedule 21.10.2014