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

发布于 2024-10-08 00:19:34 字数 763 浏览 0 评论 0原文

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

目前,我们正在使用 .net WebBrowser 控件将浏览器行为嵌入到 winform 中。 我们使用如下代码将 WatiN 附加到表单上的 WebBroswer 控件(感谢 protynick ):

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?

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

Our target is: Watin-enabled browser testing embedded in a .net winform.

Currently, we are using a .net WebBrowser control to embed browser behavior in a winform.
We are attaching WatiN to the WebBroswer control on the form with code like this ( thanks 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();

The problem is this - the "winform browser" needs to handle popups during testing/automation.

Question: How can popups be handled when Watin is attached to a winforms webBrowser control ( and not using its own WatiN-generated IE window )?
a) Can Watin's DialogWatcher still be used? If so ...how?
b) If not, then perhaps we can write our own DialogWatcher -- but we would need an hWnd or processID to add it. Where would we get correct hWnd or processId in this scenario where Waitin does not have its own window or process?

Thanks in advance for any ideas ...alternate approaches that reach the same target are welcome!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

雨的味道风的声音 2024-10-15 00:19:34

我刚刚升级到 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 实例。否则,在读取 FormHandle 属性时,您将必须修改此类以避免跨线程操作。

I have just upgraded to newest version of WatiN (head revision - 1166 - in trunk: https://watin.svn.sourceforge.net/svnroot/watin/trunk/src/). Since there was a change in original DialogWatcher class it is now possible to use existing DialogWatcher with fewer code.

Create class:

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

Use it instead of original IE class and see disappearing javascript alert dialog:

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

Warning: Create WebBrowserIE instance outside the thread. Otherwise you will have to modify this class to avoid cross-thread operation when reading Handle property of Form.

彩扇题诗 2024-10-15 00:19:34

天哪,这个问题出现了很多次,我总是写这样的东西:但是通过一点点黑客攻击,你可以根据原始的 DialogWatcher 类创建自己的(来自:如何将 watin 与 WebBrowser 控件一起使用?),所以我挖掘我的源代码来找到它,我将展示我是如何做到的。也许它并不完美,但它有效,而且我没有遇到任何问题。

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

    • 私有静态IList对话观察者
    • 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 bool IsWindowOfIexploreProcess(窗口窗口)
  3. Start() 方法中替换此:

    if (新窗口(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 对象后创建它(哈哈,我刚刚发现,有问题的是我的昵称:)) - Form_Load或类似的东西。它将立即启动(请参阅构造函数),并且主循环将在窗口不再存在后中断。

编辑:请注意,如果您设置此类(或 WatiN 设置)来关闭未处理的对话框,那么甚至您的 MessageBox.Show 也会被关闭:)

编辑 2 (重要!):上面的整个解释与取自 WatiN SVN trunk revision 1056 的原始 DialogWatcher 类相关。直接链接到此修订版和文件: http://watin.svn.sourceforge.net/viewvc/watin/trunk/src/Core/DialogHandlers/DialogWatcher.cs?revision=1056&content-type=文本/纯文本&pathrev=1056

Oh man, this question comes up so many times and I always writing something like: But with a little bit of hacking you can create your own based on original DialogWatcher class (from: How to use watin with WebBrowser control?), so I dug in my source code to find it and I will just show how I did it. Maybe it's not perfect, but it works and I didn't have any problems with it.

  1. Create FormDialogWatcher class by copying original DialogWatcher, changing class name, namespace etc.
  2. I have deleted following fields and methods from original class. This is probably not needed, but you will probably use only one instance of WebBrowser controll, so you don't really need this code and I am not sure if it will work properly after the changes without deleting this. To delete:

    • 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. In Start() method replace this:

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

    with this:

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

    (the only real difference is inside GetWindows call)

  4. In HandleWindow(Window window) remove this line:

    if (!IsWindowOfIexploreProcess(window)) return;
    

That's all! To start it, just create it: new FormDialogWatcher(Handle) where Handle is just a property of Form. You can probably create it after creating IE object in your example code (LOL, I've just figured out, that there is my nick name in question :)) - Form_Load or something like that. It will start immediately (see constructor) and the main loop will break after the window cease to exist.

EDIT: Be aware that if you set this class (or WatiN settings) to close unhandled dialogs, then even your MessageBox.Show will be closed :)

EDIT 2 (important!): Whole explanation above is related to original DialogWatcher class taken from WatiN SVN trunk revision 1056. Direct link to this revision and file: http://watin.svn.sourceforge.net/viewvc/watin/trunk/src/Core/DialogHandlers/DialogWatcher.cs?revision=1056&content-type=text/plain&pathrev=1056

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文