2010-12-15 102 views
3

Notre objectif est: test de navigateur compatible Watin intégré dans un winform .net.WatiN et .net winforms Contrôle WebBrowser - DialogWatcher est-il possible?

Actuellement, nous utilisons un contrôle .net WebBrowser pour intégrer le comportement du navigateur dans un winform. Nous joignons Watin au contrôle de WebBroswer sur le formulaire avec le code comme celui-ci (merci prostynick):

var thread = new Thread(() => 
{ 
    Settings.AutoStartDialogWatcher = false; 
    var ie = new IE(webBrowser1.ActiveXInstance); 
    ie.GoTo("http://www.google.com"); 
}); 
thread.SetApartmentState(ApartmentState.STA); 
thread.Start(); 

Le problème est - le « navigateur WinForm » doit gérer popups durant les essais/automatisation. Question: Comment les popups peuvent-ils être gérés lorsque Watin est attaché à un contrôle webBrowser winforms (et n'utilise pas sa propre fenêtre IE générée par WatiN)?
a) Le DialogWatcher de Watin peut-il encore être utilisé? Si c'est le cas, comment?
b) Sinon, nous pourrions peut-être écrire notre propre DialogWatcher - mais nous aurions besoin d'un hWnd ou d'un processID pour l'ajouter. Où obtiendrions-nous hWnd ou processId correct dans ce scénario où Waitin n'a pas sa propre fenêtre ou processus? Merci d'avance pour toutes idées ... les approches alternatives qui atteignent la même cible sont les bienvenues!

Répondre

3

homme Oh, cette question vient tant de fois et j'ai toujours écrit quelque chose comme: Mais avec un peu de piratage, vous pouvez créer votre propre base de la classe de DialogWatcher originale (à partir de: How to use watin with WebBrowser control?), donc je creusais dans mon code source pour le trouver et je vais juste montrer comment je l'ai fait. Peut-être que ce n'est pas parfait, mais ça marche et je n'ai eu aucun problème avec ça.

  1. Créer FormDialogWatcher classe en copiant le nom de classe DialogWatcher, le changement d'origine, espace de noms, etc.
  2. J'ai supprimé suivant les champs et les méthodes de la classe d'origine. Ce n'est probablement pas nécessaire, mais vous n'utiliserez probablement qu'une seule instance du contrôleur WebBrowser, donc vous n'avez pas vraiment besoin de ce code et je ne suis pas sûr qu'il fonctionnera correctement après les modifications sans le supprimer.Pour supprimer:

    • private static IList<DialogWatcher> dialogWatchers
    • public static DialogWatcher GetDialogWatcher(IntPtr mainWindowHwnd)
    • public static DialogWatcher GetDialogWatcherFromCache(IntPtr mainWindowHwnd)
    • public static void CleanupDialogWatcherCache()
    • public void IncreaseReferenceCount()
    • public void DecreaseReferenceCount()
    • public int ReferenceCount { get; private set; }
    • private bool IsWindowOfIexploreProcess(Window window)
  3. Dans la méthode Start() remplacer:

    if (new Window(MainWindowHwnd).Exists()) 
    { 
        var winEnumerator = new WindowsEnumerator(); 
        var windows = winEnumerator.GetWindows(win => true); 
    

    avec ceci:

    var mainWindow = new Window(MainWindowHwnd); 
    if (mainWindow.Exists()) 
    { 
        var winEnumerator = new WindowsEnumerator(); 
        var windows = winEnumerator.GetWindows(window => window.ProcessID == mainWindow.ProcessID); 
    

    (la seule différence réelle est à l'intérieur GetWindows appel)

  4. En HandleWindow(Window window) supprimer ce ligne:

    if (!IsWindowOfIexploreProcess(window)) return; 
    

C'est tout! Pour le démarrer, il suffit de le créer: new FormDialogWatcher(Handle)Handle est juste une propriété de Form. Vous pouvez probablement le créer après avoir créé IE objet dans votre exemple de code (LOL, je viens de comprendre, qu'il ya mon pseudo en question :)) - ou quelque chose comme ça. Il commencera immédiatement (voir constructeur) et la boucle principale se cassera après que la fenêtre cessera d'exister.

EDIT: Sachez que si vous définissez cette classe (ou paramètres Watin) pour fermer les boîtes de dialogue non gérée, alors même votre MessageBox.Show sera fermé :)

EDIT 2 (important!): explication entière ci-dessus est liée à l'origine DialogWatcher classe prise à partir du tronc SVN WatiN révision 1056. Lien direct vers cette révision et un fichier: http://watin.svn.sourceforge.net/viewvc/watin/trunk/src/Core/DialogHandlers/DialogWatcher.cs?revision=1056&content-type=text/plain&pathrev=1056

+0

incroyablement utile, prostynick. Beau travail. – user526186

4

Je viens de mettre à jour vers la dernière version de WatiN (révision de la tête - 1166 - dans le coffre: https://watin.svn.sourceforge.net/svnroot/watin/trunk/src/). Comme il y avait un changement dans la classe DialogWatcher originale, il est maintenant possible d'utiliser DialogWatcher avec moins de code.

Créer une classe:

public class WebBrowserIE : IE 
{ 
    private IntPtr hwnd; 

    public WebBrowserIE(WebBrowser webBrowserControl) 
     : base(webBrowserControl.ActiveXInstance, false) 
    { 
     hwnd = webBrowserControl.FindForm().Handle; 
     StartDialogWatcher(); 
    } 

    public override IntPtr hWnd 
    { 
     get 
     { 
      return hwnd; 
     } 
    } 

    protected override void Dispose(bool disposing) 
    { 
     hwnd = IntPtr.Zero; 
     base.Dispose(disposing); 
    } 
} 

utiliser au lieu de classe d'origine IE et voir javascript disparaître dialogue d'alerte:

var ie = new WebBrowserIE(webBrowser1); 
var thread = new Thread(() => 
{ 
    ie.GoTo("http://www.plus2net.com/javascript_tutorial/window-alert.php"); 
    ie.Button(Find.ByValue("Click here to display alert message")).Click(); 
}); 
thread.SetApartmentState(ApartmentState.STA); 
thread.Start(); 

Avertissement: Créer WebBrowserIE instance en dehors du fil. Sinon, vous devrez modifier cette classe pour éviter les opérations croisées lors de la lecture de la propriété Handle de Form.

+0

Excellent! Nous utilisons le code ci-dessus avec un bon succès, sauf pour le téléchargement de fichiers. La fenêtre de téléchargement de fichier s'ouvrira mais n'ira pas plus loin (remplissez le nom de fichier et fermez) quand nous employons ce code comme ceci: ie.FileUpload (Find.ByName ("myInputTagName")). Set ("c: \\ myUploadFileName.txt "). Des pensées? – user526186

+0

Hmm ... ça marche pour moi. Vista, IE8, WatiN du tronc SVN. – prostynick

+0

Puisque vous utilisez la variable locale 'ie' dans une méthode (je suppose) et que vous passez cette variable au thread, cela signifie que GC sera informé pour disposer le' ie' quand le thread se termine. vous ne pouvez pas le forcer à se débarrasser – Odys