CefSharp.offscreen 在 LinqPad 中

CefSharp.offscreen in LinqPad

LinqPad 是我的 goto REPL,没有太多我无法处理的东西。

但是我一辈子都做不到 CefSharp(特别是 OffScreen)到 运行。

我经常遇到以下任一错误

Could not load file or assembly 'CefSharp.Core.Runtime, Version=95.7.141.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138' or one of its dependencies. The system cannot find the file specified.

BadImageFormatException: Could not load file or assembly 'CefSharp.Core.Runtime, Version=95.7.141.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138'. An attempt was made to load a program with an incorrect format.

我试过了

上面的每一个组合看起来都是什么。

我不明白 Visual Studio 与 nuget 包一起使用的程序集解析过程,但无论它做什么,我都想至少在 Linqpad 中进行模拟,这样我就可以在测试一些简单的东西时避免 VS 仪式.

我认为手动引用正确的 .dll 并可能在某处设置路径应该就足够了,但我的想法=>EOF。

CefSharp 可以 运行 在 VS / MSBuild 之外吗?

由于 LinqPad 使用的卷影复制,它不起作用。这是一个让你的问题消失的技巧(剧透警报:不是真的,请继续阅读):

对于 LinqPad v5

  1. 将所有 CefSharp 个库复制到一个单独的文件夹(不要忘记 cef.redist)。
  2. 在 LinqPad 首选项对话框 (Advanced/Execution) 中,将 Do not shadow assembly references 设置为 True,重新启动 LinqPad。
  3. 在 LinqPad 查询中编写代码。
  4. 从您在步骤 1 中设置的文件夹中引用 CefSharp 个库。
  5. 运行查询。

对于以前的 LinqPad(早于 v5)

  1. 在 LinqPad 查询中编写代码。
  2. 参考 CefSharp 个库,所以你的问题得到了例外
  3. 找到一个 LinqPad 工作目录(通常类似于 C:\Users\<user>\AppData\Local\Temp\LINQPad5\_yyigmhzg)。
  4. 将所有 CefSharp 个库复制到此文件夹(不要忘记 cef.redist)。
  5. 在LinqPad中,点击Ctrl + Shift + F5;这将重置查询状态。
  6. 重新运行查询。

现在应该加载所有引用的库。但是之后你可能会遇到更多的问题。

我无法让 CefSharp.MinimalExample 工作。 LinqPad 不断为我崩溃并显示神秘消息 Query ended because an uncatchable exception was thrown 和故障转储。

虽然我不确定您是否会让 CefSharp 在 LinqPad 下按预期工作,也许这可以让您更进一步。

从@Sasha 的post 和@amaitland 的note 中找到关于 BadImageFormatException 不仅仅是错误架构的答案。

以下均参考LP6 and CefSharp.Offscreen.NetCore. I have not pushed the efforts into LP5,但过程应该类似。

经过反复试验,我缩小了所有必要的依赖项范围,并找出了 CefSharp would not run in LinqPad.

的原因

以下是制作步骤运行 -

  1. 正常添加CefSharp.Offscreen.NetCore包查询
  2. 启用将所有 NuGet 程序集复制到一个本地文件夹中(F4->高级)
  3. 将下面的 OnInit()queryPath 代码添加到查询中
  4. 确保在初始化 Cef
  5. 之前设置 BrowserSubprocessPath

这是代码。

async Task Main()
{
    var are = new AutoResetEvent(false);//my technique for waiting for the browser
    var sett = new CefSettings();
    sett.BrowserSubprocessPath = this.queryPath + @"\CefSharp.BrowserSubprocess.exe";   //CefSharp will complain it cant find it
    if (!Cef.IsInitialized) 
        Cef.Initialize(sett);
    var browser = new ChromiumWebBrowser("http://www.google.com");
    browser.LoadingStateChanged += (sender, args) => { if (!args.IsLoading) are.Set(); };
    are.WaitOne();
    await browser.WaitForInitialLoadAsync();
    var html = await browser.GetBrowser().MainFrame.GetSourceAsync();
    html.Dump("winner winner chicken dinner");
}

//this is the location of the queries shaddow folder
string queryPath = Path.GetDirectoryName(typeof(CefSettings).Assembly.Location);

void OnInit() // Executes when the query process first loads
{
    if (!Directory.Exists(queryPath + @"\locales")) //subdirectory of cef.redist
    {
        var nugetPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
        var sources = new[] {
            /*paths here are hardcoded version dependant. Can get cefsharp.common.netcore version 
            from Util.CurrentQuery.NuGetReferences, but cef.redist not available via that method. */
            @"cef.redist.x64.7.14\CEF", //contans all the Cef dependencies needed
            @"cefsharp.common.netcore.7.141\runtimes\win-x64\lib\netcoreapp3.1", //mainly for ijwhost.dll
            @"cefsharp.common.netcore.7.141\runtimes\win-x64\native"}; //contains BrowserSubprocess & friends
        var dst = new DirectoryInfo(queryPath);
        foreach (var path in sources)
        {
            var src = new DirectoryInfo($@"{nugetPath}\.nuget\packages\{path}");
            CopyFilesRecursively(src, dst);
        }
    }
}

//curtesy of  with slight mod
public static void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
{
    foreach (DirectoryInfo dir in source.GetDirectories())
        CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
    foreach (FileInfo file in source.GetFiles())
    {
        var dst = Path.Combine(target.FullName, file.Name);
        if (!File.Exists(dst))
            file.CopyTo(dst);
    }
}

感兴趣的人的原因 -

CefSharp 需要每个依赖项都在同一目录中,以便它们可以在 运行 时解析,但 Linqpad 仅从 NuGet 包中复制几个关键的 dll。 cef.redist 文件中的 None,ijwhost.dllBrowserSubprocess.exe 等。遇到。依赖项分散在 NuGet 包之间,尝试直接从 .nuget 缓存中解析它们是行不通的。所以这些都需要手动引入到运行ning query shadow path中。

我最初确实将所有文件复制到 Assembly.GetExecutingAssembly().Location 路径中,但这种方法需要将程序集目录添加到“路径”环境变量中。 Linqpad 内部似乎设置了 shadow 路径,所以将依赖项复制到 shadow 文件夹就可以跳过设置环境变量的需要。