【问题标题】:CefSharp.offscreen in LinqPadLinqPad 中的 CefSharp.offscreen
【发布时间】:2021-11-11 04:36:18
【问题描述】:

LinqPad 是我的 goto REPL,没有什么我无法处理的。

但是我一辈子都无法让CefSharp(特别是OffScreen)运行。

我经常遇到以下任一错误

无法加载文件或程序集“CefSharp.Core.Runtime, Version=95.7.141.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138”或其依赖项之一。系统找不到指定的文件。

BadImageFormatException:无法加载文件或程序集“CefSharp.Core.Runtime,版本=95.7.141.0,文化=中性,PublicKeyToken=40c4b6fc221f4138”。试图加载格式不正确的程序。

我试过了

  • LP5/6 32 和 64 位
  • 通过 nuget 添加 Cefsharp
  • 从文件系统手动引用 .dll
  • 引用 x86 或 x64 .dll 的
  • 将 .dll 复制到程序集搜索路径中
  • 将 nuget 路径添加到环境路径

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

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

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

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

【问题讨论】:

  • 这似乎使用了各种技巧和不安全的代码,并且可能无法在 VS 之外使用它。如果你真的想这样做,你可以试试这个。 1)下载项目的源代码并在本地构建。然后使用VS,构建一个最小的例子,但使用你的dll(即不是nuget)。最后创建一个引用本地 dll 的 LinqPad 项目并将第一行设置为 System.Diagnostics.Debugger.Launch(); 这应该允许您调试启动 VS 并调试脚本并可能找到问题。这是很多工作,您需要决定是否值得尝试。

标签: c# nuget linqpad assembly-resolution cefsharp.offscreen


【解决方案1】:

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

对于 LinqPad v5

  1. 将所有CefSharp 库复制到一个单独的文件夹(不要忘记cef.redist)。
  2. 在 LinqPad 首选项对话框(高级/执行)中,将 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 和 crashdump。

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

【讨论】:

  • 请注意,在 LinqPad 5 中,首选项中有一个“不要隐藏程序集引用”选项。
  • 哦,谢谢!没找到
  • @sgmoore,再次感谢,更新了步骤。虽然仍然崩溃:\
【解决方案2】:

从@Sasha 的帖子和@amaitland 的note 关于BadImageFormatException 不仅仅是不正确的架构中找到了答案。

以下内容均参考LP6CefSharp.Offscreen.NetCore。我还没有将努力推送到LP5,但过程应该类似。

经过反复试验,我缩小了所有必要的依赖项,并找出了为什么 CefSharp 不能在 LinqPad 中运行。

下面是让它运行的步骤-

  1. 照常添加CefSharp.Offscreen.NetCore包进行查询
  2. 启用将所有 NuGet 程序集复制到单个本地文件夹中(F4->高级)
  3. OnInit()queryPath 代码如下添加到查询中
  4. 确保在初始化 Cef 之前设置了 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\95.7.14\CEF", //contans all the Cef dependencies needed
            @"cefsharp.common.netcore\95.7.141\runtimes\win-x64\lib\netcoreapp3.1", //mainly for ijwhost.dll
            @"cefsharp.common.netcore\95.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 https://stackoverflow.com/a/58779/2738249 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 文件、ijwhost.dllBrowserSubprocess.exe 等。遇到。依赖项分散在 NuGet 包之间,尝试直接从 .nuget 缓存中解析它们是行不通的。所以所有这些都需要手动引入到正在运行的查询影子路径中。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2016-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多