web-dev-qa-db-fra.com

Modification de l'agent utilisateur du contrôle WebBrowser

J'essaye de changer le UserAgent du contrôle WebBrowser dans une application Winforms.

J'ai réussi cela en utilisant le code suivant:

[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);
}

Le seul problème est que cela ne fonctionne qu'une seule fois. Lorsque j'essaie d'exécuter la méthode ChangeUserAgent () pour la deuxième fois, cela ne fonctionne pas. Il reste réglé sur la première valeur modifiée. C'est assez ennuyeux et j'ai tout essayé mais ça ne changera pas plus d'une fois.

Quelqu'un connaît-il une approche différente et plus flexible?

Merci

44
Proximo

Je ne sais pas si je devrais simplement copier/coller à partir d'un site Web , mais je préfère laisser la réponse ici, au lieu d'un lien. Si quelqu'un peut clarifier dans les commentaires, je serai très obligé.

Fondamentalement, vous devez étendre la classe 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;
            }
        }
    }
}

Remarque: pour utiliser la méthode ci-dessus, vous devez ajouter une référence COM à "Microsoft Internet Controls".

Il mentionne également votre approche et indique que le contrôle WebBrowser semble mettre en cache cette chaîne d'agent utilisateur, il ne modifiera donc pas l'agent utilisateur sans redémarrer le processus.

35
Jean Azzopardi

La façon la plus simple:

webBrowser.Navigate("http://localhost/run.php", null, null,
                    "User-Agent: Here Put The User Agent");
62
Constantin

En outre, il existe une option de rafraîchissement dans la fonction (selon MSDN ). Cela a bien fonctionné pour moi (vous devez le définir avant tout changement d'agent utilisateur). Ensuite, le code de question pourrait être modifié comme ceci:

[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);
}
19
natenho

Je voudrais ajouter à la réponse de @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);
}

Cette solution a fonctionné le mieux pour moi. L'utilisation de la renavigation a causé d'autres problèmes étranges pour moi, comme la disparition soudaine du contenu du navigateur et, parfois, l'obtention d'un navigateur non pris en charge. Avec cette technique, toutes les demandes dans Fiddler avaient l'agent utilisateur correct.

4
harsimranb