简体   繁体   English

LinqPad 中的 CefSharp.offscreen

[英]CefSharp.offscreen in LinqPad

LinqPad is my goto REPL and there isn't much I throw at it that it cant handle. LinqPad是我的首选REPL,没有太多我无法处理的内容。

However I cannot for the life of me get CefSharp (specifically OffScreen) to run.但是,我一生都无法让CefSharp (特别是 OffScreen)运行。

I'm constantly met with either of the below errors我经常遇到以下错误之一

Could not load file or assembly 'CefSharp.Core.Runtime, Version=95.7.141.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138' or one of its dependencies.无法加载文件或程序集“CefSharp.Core.Runtime,Version=95.7.141.0,Culture=neutral,PublicKeyToken=40c4b6fc221f4138”或其依赖项之一。 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'. BadImageFormatException:无法加载文件或程序集“CefSharp.Core.Runtime,版本=95.7.141.0,Culture=neutral,PublicKeyToken=40c4b6fc221f4138”。 An attempt was made to load a program with an incorrect format.试图加载格式不正确的程序。

I have tried我试过了

  • LP5/6 32 and 64 bit LP5/6 32 和 64 位
  • Adding Cefsharp via nuget通过 nuget 添加 Cefsharp
  • Referencing .dll's manually from the file system从文件系统手动引用 .dll
  • Referencing x86 or x64 .dll's引用 x86 或 x64 .dll
  • Copying .dll's into assembly search paths将 .dll 复制到程序集搜索路径中
  • Adding nuget paths to Environment path将 nuget 路径添加到环境路径

And what seems like every combination of the above.以及上面的每一个组合。

I don't understand the assembly resolution process that Visual Studio uses with the nuget package, but whatever it does I would like to at least simulate in Linqpad so I can avoid the VS ceremony when testing something simple.我不明白 Visual Studio 与 nuget 包一起使用的程序集解析过程,但无论它做什么,我都希望至少在 Linqpad 中进行模拟,这样我就可以在测试简单的东西时避免 VS 仪式。

I assume that manually referencing the correct .dll's and maybe setting a path somewhere should be sufficient, but I'm ideas=>EOF.我认为手动引用正确的 .dll 并可能在某处设置路径就足够了,但我的想法=> EOF。

Can CefSharp be run outside of VS / MSBuild ? CefSharp 可以在 VS/MSBuild 之外运行吗?

It doesn't work because of the shadow-copying that LinqPad is using.由于 LinqPad 使用的阴影复制,它不起作用。 Here is a hack to make your problem go away (spoiler alert: not really, read on):这是一个让您的问题消失的技巧(剧透警报:不是真的,请继续阅读):

  1. Write your code in the LinqPad query.在 LinqPad 查询中编写代码。
  2. Reference CefSharp libraries, so you get an exception from your question参考CefSharp库,以便您从问题中获得例外
  3. Find a LinqPad working directory (usually something like C:\\Users\\<user>\\AppData\\Local\\Temp\\LINQPad5\\_yyigmhzg ).找到 LinqPad 工作目录(通常类似于C:\\Users\\<user>\\AppData\\Local\\Temp\\LINQPad5\\_yyigmhzg )。
  4. Copy all CefSharp libraries to this folder (don't forget cef.redist ).将所有CefSharp库复制到此文件夹(不要忘记cef.redist )。
  5. In LinqPad, click Ctrl + Shift + F5 ;在 LinqPad 中,单击Ctrl + Shift + F5 this will reset the query state.这将重置查询状态。
  6. Rerun the query.重新运行查询。

Now all the referenced libraries should load.现在应该加载所有引用的库。 But you will likely face more problems after that.但在那之后你可能会面临更多的问题。

I couldn't make CefSharp.MinimalExample work.我无法让CefSharp.MinimalExample工作。 LinqPad kept crashing for me with the cryptic message Query ended because an uncatchable exception was thrown and a crashdump. LinqPad 一直在为我崩溃,并显示神秘的消息Query ended because an uncatchable exception was thrown了一个Query ended because an uncatchable exception was thrown和一个崩溃转储。

Although I am not sure if you will make CefSharp work as intended under LinqPad, maybe this can get you a bit further.虽然我不确定您是否会让 CefSharp 在 LinqPad 下按预期工作,但也许这可以让您走得更远。

Found the answer with motivation from @Sasha's post and @amaitland's note about BadImageFormatException 's being more than just incorrect architectures.从@Sasha 的帖子和@amaitland 关于BadImageFormatException不仅仅是不正确的架构的注释中找到了答案。

The below is all in reference to LP6 and CefSharp.Offscreen.NetCore .以下是所有参考LP6CefSharp.Offscreen.NetCore I have not pushed the efforts into LP5 but the process should be similar.我没有将努力推向LP5,但过程应该是相似的。

After some trial and error I narrowed down all of the necessary dependencies and worked out why CefSharp would not run in LinqPad .经过一些反复试验,我缩小了所有必要的依赖关系,并找出了为什么CefSharp不能在LinqPad 中运行的原因

Here are the steps to make it run -以下是使其运行的步骤 -

  1. Add CefSharp.Offscreen.NetCore package as normal to query正常添加CefSharp.Offscreen.NetCore包进行查询
  2. Enable Copy all NuGet assemblies into a single local folder (F4->Advanced)启用将所有 NuGet 程序集复制到单个本地文件夹(F4->高级)
  3. Add the OnInit() and queryPath code as below to the queryOnInit()queryPath代码如下添加到查询中
  4. Ensure the BrowserSubprocessPath is set before Initializing Cef确保在初始化 Cef 之前设置了BrowserSubprocessPath

Here is the code.这是代码。

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);
    }
}

The why for those interested -为什么感兴趣的人 -

CefSharp needs every dependency to be in the same directory so they can be resolved at runtime, but Linqpad only copies a few key dll's from the NuGet package. CefSharp 需要每个依赖项都在同一目录中,以便它们可以在运行时解析,但 Linqpad 只从 NuGet 包中复制了几个关键的 dll。 None of the cef.redist files, ijwhost.dll or BrowserSubprocess.exe et al. cef.redist文件、 ijwhost.dllBrowserSubprocess.exe cef.redist没有。 come across.遇到。 Dependencies are scattered between NuGet packages and trying to resolve them directly from the .nuget cache just does not work.依赖项分散在 NuGet 包之间,尝试直接从 .nuget 缓存中解析它们是行不通的。 So all these need to be brought in manually to the running query shadow path.所以所有这些都需要手动引入到正在运行的查询影子路径中。

I did initially copy all files into the Assembly.GetExecutingAssembly().Location path, but this approach requires adding the assembly directory to the "path" environment variable.我最初确实将所有文件复制到Assembly.GetExecutingAssembly().Location路径中,但这种方法需要将程序集目录添加到“路径”环境变量中。 Internally Linqpad seems to have the shadow path set, so copying the dependencies to the shadow folder skips the need to set the environment variable. Linqpad 似乎在内部设置了影子路径,因此将依赖项复制到影子文件夹无需设置环境变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM