WatiN и.net winforms Элемент управления WebBrowser - возможен ли DialogWatcher?
Наша цель: тестирование браузеров с поддержкой 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 ответа
Я только что обновил до последней версии 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
,
О, чувак, этот вопрос возникает так много раз, и я всегда пишу что-то вроде: Но с небольшим количеством взлома вы можете создать свой собственный, основываясь на оригинальном классе DialogWatcher (из: Как использовать watin с контролем WebBrowser?), Поэтому я выкопал в моем исходном коде, чтобы найти его, и я просто покажу, как я это сделал. Может быть, это не идеально, но это работает, и у меня не было никаких проблем с этим.
- Создайте
FormDialogWatcher
класс путем копирования оригиналаDialogWatcher
, изменение имени класса, пространства имен и т. д. Я удалил следующие поля и методы из оригинального класса. Это, вероятно, не нужно, но вы, вероятно, будете использовать только один экземпляр
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)
В
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
вызов)В
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