WatiN и .net winforms Элемент управления WebBrowser - возможен ли DialogWatcher? - PullRequest
3 голосов
/ 16 декабря 2010

Наша цель: тестирование браузеров с поддержкой Watin, встроенное в .net winform.

В настоящее время мы используем элемент управления .net WebBrowser для встраивания поведения браузера в winform. Мы присоединяем WatiN к элементу управления WebBroswer в форме с помощью кода, подобного этому (спасибо 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();

Проблема в том, что «браузер winform» должен обрабатывать всплывающие окна во время тестирования / автоматизации.

Вопрос: Как можно обрабатывать всплывающие окна, когда Watin подключен к элементу управления winforms webBrowser (и не использует собственное окно IE, сгенерированное WatiN)?
а) Можно ли использовать DialogWatcher от Watin? Если так ... как?
б) Если нет, то, возможно, мы можем написать наш собственный DialogWatcher - но нам понадобится hWnd или processID, чтобы добавить его. Где бы мы получили правильный hWnd или processId в этом сценарии, где у Waitin нет собственного окна или процесса?

Заранее спасибо за любые идеи ... приветствуются альтернативные подходы, которые достигают той же цели!

Ответы [ 2 ]

4 голосов
/ 16 декабря 2010

Я только что обновился до последней версии WatiN (основная редакция - 1166 - в багажнике: https://watin.svn.sourceforge.net/svnroot/watin/trunk/src/). Поскольку в первоначальном классе DialogWatcher произошли изменения, теперь можно использовать существующий DialogWatcher с меньшим количеством код.

Создать класс:

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

Используйте его вместо исходного IE класса и увидите диалоговое окно предупреждения об исчезновении JavaScript:

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();

Предупреждение : Создать WebBrowserIE экземпляр вне потока. В противном случае вам придется изменить этот класс, чтобы избежать операции с несколькими потоками при чтении Handle свойства Form.

3 голосов
/ 16 декабря 2010

О, боже, этот вопрос возникает так много раз, и я всегда пишу что-то вроде: Но, немного взломав, вы можете создать свой собственный, основываясь на оригинальном классе DialogWatcher (от: Как использовать watin с контролем WebBrowser? ), поэтому я покопался в исходном коде, чтобы найти его, и я просто покажу, как я это сделал. Может быть, он не идеален, но работает, и у меня не было с этим проблем.

  1. Создание FormDialogWatcher класса путем копирования оригинала DialogWatcher, изменения имени класса, пространства имен и т. Д.
  2. Я удалил следующие поля и методы из исходного класса. Это, вероятно, не нужно, но вы, вероятно, будете использовать только один экземпляр WebBrowser controll, поэтому вам не нужен этот код, и я не уверен, будет ли он работать должным образом после изменений, не удаляя его. Удалить:

    • 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. В Start() метод замените это:

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

    с этим:

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

    (единственная реальная разница внутри GetWindows звонок)

  4. В HandleWindow(Window window) удалить эту строку:

    if (!IsWindowOfIexploreProcess(window)) return;
    

Вот и все! Чтобы запустить его, просто создайте его: new FormDialogWatcher(Handle), где Handle - это просто свойство Form. Вы, вероятно, можете создать его после создания объекта IE в своем примере кода (LOL, я только что выяснил, что речь идет о моем псевдониме :)) - Form_Load или что-то подобное. Он начнется немедленно (см. Конструктор) и основной цикл прекратится после того, как окно перестанет существовать.

РЕДАКТИРОВАТЬ : Имейте в виду, что если вы установите этот класс (или настройки WatiN) для закрытия необработанных диалогов, то даже ваш MessageBox.Show будет закрыт:)

РЕДАКТИРОВАТЬ 2 (важно!) : Все вышеприведенное объяснение связано с оригинальным DialogWatcher классом, взятым из магистрали WatiN SVN ревизия 1056 . Прямая ссылка на эту редакцию и файл: http://watin.svn.sourceforge.net/viewvc/watin/trunk/src/Core/DialogHandlers/DialogWatcher.cs?revision=1056&content-type=text/plain&pathrev=1056

...