如何将Selenium WebDriver嵌入为WPF控件?

Jak*_*kša 1 wpf selenium-webdriver

WebDriver与WPF的WebBrowser控件类似,有没有办法将驱动程序嵌入WPF窗口?

(可选)是否可以在WebBrowser控件本身上使用Selenium ?


到目前为止,只能创建一个WebDriver与应用程序中任何其他WPF窗口分开的新窗口。

ear*_*loc 5

这是一个小把戏;)

由于Selenium大多数时候都使用外部应用程序(浏览器),因此没有像将Browser-UI集成到应用程序中那样的“本机”解决方案。

但是,有Windows特定的API可以使用WinForms完全实现。

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);
}
Run Code Online (Sandbox Code Playgroud)

基本上,该想法是将外部浏览器“包装”在应用程序的用户控件内。

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);
        };
    }
Run Code Online (Sandbox Code Playgroud)

最后,扩展用于通过WMI枚举子进程:

ProcessExtensions.cs

public static IEnumerable<Process> GetChildren(this Process parent) {
    var query = new ManagementObjectSearcher($@"
        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);
}
Run Code Online (Sandbox Code Playgroud)

并调用如下方法:

var host = new SeleniumHost();
var service = InternetExplorerDriverService.CreateDefaultService();
var driver = new InternetExplorerDriver(service);
host.AttachDriverService(service);
Run Code Online (Sandbox Code Playgroud)

完成后,这解决了WinForms-Part。要将其集成到WPF中,您需要利用WindowsFormsHost来显示WinForms-Control。

在GitHub上查看我最新发布的仓库,以获取更多参考或直接利用NuGet-Package

请耐心等待,因为这些都是非常热门的内容-因此将来肯定会有bug和进一步的改进(例如从浏览器中删除chrome / border)。希望您能得到这个想法和/或在GitHub上做出贡献。