WatiN和.net winforms WebBrowser控件 - DialogWatcher可能吗?

时间:2010-12-15 22:27:41

标签: webbrowser-control watin browser-automation

我们的目标是:嵌入在.net winform中的支持Watin的浏览器测试。

目前,我们正在使用.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控件(而不是使用自己的WatiN生成的IE窗口)时,如何处理弹出窗口? a)Watin的DialogWatcher仍然可以使用吗?如果是这样......怎么样? b)如果没有,那么也许我们可以编写自己的DialogWatcher - 但我们需要一个hWnd或processID来添加它。在Waitin没有自己的窗口或进程的情况下,我们在哪里获得正确的hWnd或processId?

提前感谢任何想法...欢迎达到相同目标的替代方法!

2 个答案:

答案 0 :(得分:4)

我刚刚升级到最新版本的WatiN(头版本 - 1166 - 在trunk: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的{​​{1}}属性时,您必须修改此类以避免跨线程操作。

答案 1 :(得分:3)

哦,伙计,这个问题出现了这么多次,我总是写一些类似的东西:但是通过一些黑客攻击你可以根据原始的DialogWatcher类创建自己的(来自:{{3因此,我在我的源代码中挖出来找到它,我将展示我是如何做到的。也许它并不完美,但它有效,我没有遇到任何问题。

  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;
    
  5. 这就是全部!要启动它,只需创建它:new FormDialogWatcher(Handle)其中Handle只是Form的属性。您可以在示例代码中创建IE对象之后创建它(LOL,我刚刚想通了,我的昵称有问题:)) - Form_Load或类似的东西。它将立即启动(参见构造函数),并且在窗口停止存在后主循环将中断。

    编辑:请注意,如果您设置此类(或WatiN设置)以关闭未处理的对话框,那么即使您的MessageBox.Show也将关闭:)

    编辑2(重要!):上面的整个解释与从WatiN SVN主干修订版1056 中取得的原始DialogWatcher类有关。直接链接到此修订版和文件:How to use watin with WebBrowser control?