WatiN and .net winforms WebBrowser control - is DialogWatcher possible?

后端 未结 2 2072
面向向阳花
面向向阳花 2020-12-16 08:11

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

相关标签:
2条回答
  • 2020-12-16 08:19

    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

    0 讨论(0)
  • 2020-12-16 08:25

    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.

    0 讨论(0)
提交回复
热议问题