3

我们的目标是:在 .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?

提前感谢您的任何想法...欢迎使用其他方法达到相同的目标!

4

2 回答 2

4

我刚刚升级到最新版本的 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

于 2010-12-16T12:40:24.247 回答
3

哦,伙计,这个问题出现了很多次,我总是写类似的东西:但是通过一些黑客攻击,您可以根据原始 DialogWatcher 类创建自己的(来自:如何使用 watin 和 WebBrowser 控件?),所以我挖了在我的源代码中找到它,我将展示我是如何做到的。也许它并不完美,但它有效,我没有任何问题。

  1. FormDialogWatcher通过复制原始DialogWatcher类、更改类名、命名空间等来创建类。
  2. 我从原始类中删除了以下字段和方法。这可能不是必需的,但您可能只会使用一个WebBrowsercontroll 实例,因此您实际上并不需要此代码,而且我不确定在更改后它是否会在不删除它的情况下正常工作。删除:

    • 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)whereHandle只是Form. 您可以IE在示例代码中创建对象后创建它(大声笑,我刚刚发现,我的昵称有问题:)) -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

于 2010-12-16T00:42:06.317 回答