2009-06-02 9 views
40

Je tente de modifier l'UserAgent du contrôle WebBrowser dans une application Winforms.Modification de l'agent utilisateur du contrôle WebBrowser

J'ai réalisé avec succès ce 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 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 défini sur la première valeur modifiée. C'est assez énervant et j'ai tout essayé mais ça ne changera pas plus d'une fois.

Est-ce que quelqu'un connaît une approche différente, plus flexible?

Merci

+1

J'ai essayé la méthode ci-dessus, mais cela n'a pas fonctionné pour WPF (System.Windows.Controls.WebBrowser) –

Répondre

32

Je ne sais pas si je devrais copier/coller d'un website, 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, de sorte qu'il ne changera pas l'agent utilisateur sans redémarrer le processus.

+0

Y at-il un moyen de redémarrer le processus, peut-être en utilisant le thread? J'ai une expérience limitée avec winforms. – Proximo

+0

Je ne suis pas si sûr, je l'essayerais moi-même, mais je pense que l'approche que j'ai donnée dans ma réponse devrait fonctionner. C'est moins élégant, cependant. Je me demande aussi si vous pouvez supprimer le contrôle et en créer un nouveau à l'exécution, mais je suppose que cela pourrait être un peu cher. –

+0

J'ai ajouté cette classe à mon projet et cela n'a pas fonctionné du tout. Donc maintenant je suppose que je dois essayer de redémarrer l'approche de processus. – Proximo

58

La meilleure façon:

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

vous devez terminer l'en-tête personnalisé avec '\ r \ n' – Smith

+8

Si le contrôle webbrowser s'éloigne de cet URI (en cliquant sur un lien ou en reculant/en avant), l'agent utilisateur est réinitialisé. Idéalement, la solution devrait fonctionner pour toutes les demandes que le contrôle fait. – monzonj

+5

Cela ne fonctionne que pour la demande d'origine passée à Naviguer - tous les appels AJAX dans le site Web utiliseront toujours l'UA par défaut du contrôle –

13

En outre, il y a une option de rafraîchissement dans la fonction (selon MSDN). Cela a bien fonctionné pour moi (vous devriez le régler avant tout changement d'agent utilisateur). Alors le code de question pourrait être changé 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); 
} 
+1

pourquoi n'utilisez-vous pas la variable 'userAgent'? – Sebastian

+0

Il a été extrait de mon propre code, ne devrait pas être là. Tks pour le signaler. – natenho

+1

La réponse acceptée ne fonctionnera pas si vous êtes, par exemple, connecté à Facebook et que vous avez besoin d'obtenir l'autorisation de l'utilisateur ("renavigate" provoque des problèmes). Alors créez votre navigateur intégré et utilisez URLMON_OPTION_USERAGENT_REFRESH puis URLMON_OPTION_USERAGENT pour définir votre UA personnalisé. Comme indiqué ci-dessus, répétez au besoin ou définissez uniquement URLMON_OPTION_USERAGENT_REFRESH pour revenir à l'UA UA par défaut. –

2

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. Utiliser le renavigating a causé d'autres problèmes étranges pour moi, comme le contenu du navigateur disparaissant soudainement, et parfois toujours le navigateur Unsupported. Avec cette technique, toutes les demandes dans Fiddler avaient le bon User Agent.

Questions connexes