2017-05-08 8 views
0

Gibt es eine Möglichkeit, einen WebDriver-Treiber in ein WPF-Fenster einzubetten, ähnlich wie beim WPF WebBrowser?Wie bette ich einen Selenium WebDriver als WPF-Steuerelement ein?

Optional gibt es eine Möglichkeit, Selenium auf der WebBrowser Steuerung selbst zu verwenden?


Bisher ist es nur möglich, ein neues WebDriver Fenster, getrennt von jedem anderen WPF-Fenster in der Anwendung zu erstellen.

Antwort

2

Dies war eine leicht austricksen;)

Als Selen externe Anwendungen verwendet (die Browser) die meiste Zeit gibt es keine „native“ Lösung wie nur in einer App den Browser-UI zu integrieren.

Es gibt jedoch Windows-spezifische APIs, um genau das mit WinForms zu erreichen.

UnsafeNativeMethods.cs

private static class UnsafeNativeMethods { 
     [DllImport("user32")] 
     public static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent); 

     [DllImport("user32.dll", SetLastError = true)] 
     public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); 
} 

Grundsätzlich ist die Idee zu "wickeln", um den externen Browser innerhalb eines Usercontrol in Ihrer Anwendung.

SeleniumHost.cs

public void AttachDriverService(DriverService service) { 
     //get the process started by selenium 
     var driverProcess = Process.GetProcessById(service.ProcessId); 

     //find the first child-process (should be the browser) 
     var browserProcess = driverProcess.GetChildren() 
           .Where(p => p.ProcessName != "conhost") 
           .First(); 

     _BrowserHandle = browserProcess.MainWindowHandle; 

     //set the parent window utilizing Win32-API 
     UnsafeNativeMethods.SetParent(_BrowserHandle.Value, this.Handle); 
     //handle moving/resizing of your appo to be reflected on browser 
     UnsafeNativeMethods.MoveWindow(_BrowserHandle.Value, 0, 0, Width, Height, true); 

     this.Resize += (sender, e) => { 
      UnsafeNativeMethods.MoveWindow(_BrowserHandle.Value, 0, 0, Width, Height, true); 
     }; 
    } 

Endlich die Erweiterung verwendet Kind-Prozesse über WMI aufzuzählen:

ProcessExtensions.cs

public static IEnumerable<Process> GetChildren(this Process parent) { 
    var query = new ManagementObjectSearcher([email protected]" 
     SELECT * 
     FROM Win32_Process 
     WHERE ParentProcessId={parent.Id}"); 

    return from item in query.Get().OfType<ManagementBaseObject>() 
      let childProcessId = (int)(UInt32)item["ProcessId"] 
      select Process.GetProcessById(childProcessId); 
} 

und rufen Sie die Methode wie:

var host = new SeleniumHost(); 
var service = InternetExplorerDriverService.CreateDefaultService(); 
var driver = new InternetExplorerDriver(service); 
host.AttachDriverService(service); 

Wenn Sie fertig sind, löst dies die WinForms-Teil. Um dies in WPF zu integrieren, müssen Sie WindowsFormsHost nutzen, um WinForms-Control anzuzeigen.

Überprüfen Sie meine frische veröffentlichte repo on GitHub für weitere Referenz oder nutzen Sie direkt die NuGet-Package.

Bitte ertragen Sie mit mir, da diese sehr heiße Bits sind - so wird es sicher Bugs und weitere Verbesserungen in der Zukunft (wie Entfernen der Chrom/Grenze aus dem Browser) sein. Hoffentlich könnt ihr die Idee bekommen und/oder vielleicht einen Beitrag zu GitHub leisten.