使用Selenium 3启动特定的Firefox配置文件

8
我正在尝试从Selenium 2升级到Selenium 3,但旧的处理方式不再有效(似乎文档也不存在)。目前的程序是打开一个Firefox驱动器并使用配置文件:SELENIUM。不幸的是,它无法正常运行,总是出现错误:“System.InvalidOperationException”类型的未处理异常在WebDriver.dll中发生。附加信息:压缩流已损坏。以下是目前的程序:
public Program()
{
    FirefoxOptions _options = new FirefoxOptions();
    FirefoxProfileManager _profileIni = new FirefoxProfileManager();
    FirefoxDriverService _service = FirefoxDriverService.CreateDefaultService(@"C:\Programme\IMaT\Output\Release\Bin");
    _service.FirefoxBinaryPath = @"C:\Program Files (x86)\Mozilla Firefox\firefox.exe";
    try
    {
        if ((_options.Profile = _profileIni.GetProfile("SELENIUM")) == null)
        {
            Console.WriteLine("SELENIUM PROFILE NOT FOUND");
            _profile.SetPreference("network.proxy.type", 0); // disable proxy
            _profile = new FirefoxProfile();
        }
    }
    catch
    {
        throw new Exception("Firefox needs a Profile with \"SELENIUM\"");
    }
    IWebDriver driver = new FirefoxDriver(_service,_options,new System.TimeSpan(0,0,30));        
    driver.Navigate().GoToUrl("ld-hybrid.fronius.com");
    Console.Write("rtest");
}

static void Main(string[] args)
{
    new Program();
}

如果不加载配置文件,仅使用new FirefoxDriver(_service),则可以正常运行,但是配置文件是必需的。

在Selenium 2中,我用以下代码处理它:

FirefoxProfileManager _profileIni = new FirefoxProfileManager();
// use custom temporary profile
try { 
    if ((_profile = _profileIni.GetProfile("SELENIUM")) == null)
    {
        Console.WriteLine("SELENIUM PROFILE NOT FOUND");
        _profile.SetPreference("network.proxy.type", 0); // disable proxy
        _profile = new FirefoxProfile();
    }
}
catch
{
    throw new Exception("Firefox needs a Profile with \"SELENIUM\"");
}

_profile.SetPreference("intl.accept_languages", _languageConfig);
_driver = new FirefoxDriver(_profile);

快速简单,但是由于驱动程序不支持带有服务和配置文件的构造函数,我真的不知道如何使它工作,任何帮助将不胜感激。

1个回答

5

这个异常是由于.Net库中的一个错误导致的。生成配置文件的Zip代码未能提供正确的Zip。

克服此问题的一种方法是重载FirefoxOptions并使用来自.Net框架(System.IO.Compression.ZipArchive)的归档程序,而不是有缺陷的ZipStorer

var options = new FirefoxOptionsEx();
options.Profile = @"C:\Users\...\AppData\Roaming\Mozilla\Firefox\Profiles\ez3krw80.Selenium";
options.SetPreference("network.proxy.type", 0);

var service = FirefoxDriverService.CreateDefaultService(@"C:\downloads", "geckodriver.exe");

var driver = new FirefoxDriver(service, options, TimeSpan.FromMinutes(1));

class FirefoxOptionsEx : FirefoxOptions {

    public new string Profile { get; set; }

    public override ICapabilities ToCapabilities() {

        var capabilities = (DesiredCapabilities)base.ToCapabilities();
        var options = (IDictionary)capabilities.GetCapability("moz:firefoxOptions");
        var mstream = new MemoryStream();

        using (var archive = new ZipArchive(mstream, ZipArchiveMode.Create, true)) {
            foreach (string file in Directory.EnumerateFiles(Profile, "*", SearchOption.AllDirectories)) {
                string name = file.Substring(Profile.Length + 1).Replace('\\', '/');
                if (name != "parent.lock") {
                    using (Stream src = File.OpenRead(file), dest = archive.CreateEntry(name).Open())
                        src.CopyTo(dest);
                }
            }
        }

        options["profile"] = Convert.ToBase64String(mstream.GetBuffer(), 0, (int)mstream.Length);

        return capabilities;
    }

}

通过名称获取配置文件的目录:

var manager = new FirefoxProfileManager();
var profiles = (Dictionary<string, string>)manager.GetType()
    .GetField("profiles", BindingFlags.Instance | BindingFlags.NonPublic)
    .GetValue(manager);

string directory;
if (profiles.TryGetValue("Selenium", out directory))
    options.Profile = directory;

谢谢,我真的已经放弃使用Selenium 3了...这样一个 - 我会说,低级基础 - 不起作用真的很痛苦...而且在任何地方都找不到解决这个问题的方法更加令人沮丧。对于重载版本,现在我需要知道SELENIUM配置文件的路径,但这对我来说并不真正有效,因为我们有多台不同的测试计算机,但配置文件位于其他位置等等。(new FirefoxProfileManager())。GetProfile(“SELENIUM”)。ProfileDirectory当我尝试这样做时,ProfileDirectory总是为空,它只存储在非公共变量中。 - Dominik Lemberger
在我的情况下,这会是什么样子? FirefoxProfile profile = new FirefoxProfileManager().GetProfile("SELENIUM"); var profiles = (Dictionary<string, string>)profile.GetType().GetField("ProfileDirectory", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(profile); options.Profile =看起来好像无法正常工作(附注:我以前从未使用过反射)。 - Dominik Lemberger
谢谢,它的效果非常好 - 即使我基本上不理解发生了什么 :) 我打算接下来几个小时试着去读懂它哈哈 - Dominik Lemberger
@FlorentB。在实施相同的代码后,我仍然遇到“无法加载您的Firefox配置文件”错误。只有在我手动点击“确定”后,它才会打开,并在测试完成后收到“Firefox已停止工作”的警告。您能否花几分钟时间查看一下这个问题? - Praveen Tiwari
@FlorentB。这是我的代码链接(无法在评论中编写代码)。它看起来与您的代码相同。如果我漏掉了什么,请给予建议。https://drive.google.com/file/d/0B3tWPIS9ivWkRG1uR0tjMUlfUEk/view - Praveen Tiwari
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接