Cefsharp: Feature Request - Add .Net Core 3.1 Support

Created on 31 May 2019  Β·  52Comments  Β·  Source: cefsharp/CefSharp

With .Net Core 3.0 adding support for WPF and WinForms I'm seeing more and more queries about running CefSharp using .Net Core 3.0. This issue will track the official progress, there is no timeframe yet, please don't ask when this will be implemented, .Net Core isn't even officially out yet. As per https://github.com/dotnet/core/blob/master/roadmap.md#upcoming-ship-dates the release is still some months away.

Microsoft has started implementing C++/CLI as part of .Net Core you can track the issue https://github.com/dotnet/coreclr/issues/18013 They are only adding support for Windows initially. See also https://github.com/dotnet/coreclr/issues/659

.Net Core will support mixed mode assemblies on Windows Only.

https://devblogs.microsoft.com/dotnet/net-core-3-and-support-for-windows-desktop-applications/

The sync JavaScript Binding implementation will not work as Microsoft is not supporting WCF in .Net Core 3.0.

  • [x] Refactor BrowserSubProcess #2891
  • [x] Compile project targeting .Net Core (#3181)
  • [ ] Release Net Core/Net 5.0 packages
feature-request

Most helpful comment

In .NET Core 3.1 preview 2, C++/CLI support has been added.
I think it's time to port CefSharp to .NET Core.

See https://devblogs.microsoft.com/cppblog/an-update-on-cpp-cli-and-dotnet-core/ and https://devblogs.microsoft.com/dotnet/announcing-net-core-3-1-preview-2/

All 52 comments

With https://github.com/cefsharp/CefSharp/pull/2767 it may be possible to load the next CefSharp release (75 at time of writing) with .Net Core 3.0 referencing the current .Net 4.5.2 framework assemblies. I have no personally tested this personally yet. You will have to avoid using the sync JavaScript Binding as it relies on WCF.

Any news on this one?

Hi,
first, many thanks for this great project!

I was able to successfully use CefSharp.WinForms 75.0.110-CI3174 on a .NET Core 3.0 (Preview 5) WinForms application (form title in the screenshot contains process filename and RuntimeInformation.FrameworkDescription when running with dotnet.exe):
cefsharp-windows

I also tested that the IDownloadHandler was working successfully.

However, directly adding the NuGet package to the .NET Core project did not work as it didn't resolve the dependencies (probably because they are only declared for .NET Framework 4.5.2).

Instead, I first added it to a .NET Framework project and built it (so all the necessary files would be copied into the bin folder), and then in the .NET Core 3.0 project I manually added references to the CefSharp.dll, CefSharp.Core.dll and CefSharp.WinForms.dll assemblies. Additionally, I copied all other files from the bin folder of the .NET Framework app to the bin folder of the .NET Core app.

Another thing to consider is the browser subprocess (CefSharp.BrowserSubprocess.exe) which is built for .NET Framework 4.5.2, meaning that you still would need to have .NET Framework 4.5.2 or higher installed to run the .NET Core 3.0 app.

In order to avoid a dependency on .NET Framework and only use .NET Core, I think you will probably have to provide your own browser subprocess, implemented as a .NET Core app (using the same .NET Core version as your main app so that it can share runtime files when publishing a self-contained app).
(I haven't tested this yet.)

Thank you!

You can try setting <PackageTargetFallback>net452</PackageTargetFallback> in your project file which might restore the nuget package correctly.
https://docs.microsoft.com/en-us/nuget/reference/msbuild-targets#packagetargetfallback

Hi @campersau,

You can try setting <PackageTargetFallback>net452</PackageTargetFallback> in your project file which might restore the nuget package correctly.

Thanks for your suggestion! Unfortunately, it did not seem to have an effect when I added that setting to the project file - it still only added CefSharp.WinForms.dll but none of the dependencies. I guess the NuGet packages would need to have an additional .NET Core 3.0 target for this to work.


I also had a look at the browser subprocess, and I was also able to successfully provide the subprocess as .NET Core 3.0 app, to avoid a dependency on the .NET Framework 4.5.2.
However, actually using a different project for the subprocess might be a bit cumbersome with .NET Core because the build results (binaries) might different for a normal (framework-dependent) app (e.g. when debugging in Visual Studio) compared to a published (self-contained) app etc., and you would need to copy the correct subprocess binaries near your app binaries each time.

I think the easiest way to use CEFSharp including the browser subprocess in .NET Core 3.0 might be to use the same executable for both your regular WinForms app and the browser subprocess.

To test this, I added a reference to CefSharp.BrowserSubprocess.Core.dll to my .NET Core 3.0 WinForms project, set CefSettings.BrowserSubprocessPath = Process.GetCurrentProcess().MainModule.FileName, and then used a Main() method like this (as I noticed the subprocess will be called with a --type=.... argument):
c# [STAThread] static int Main(string[] args) { if (args.Length > 0 && args[0].StartsWith( CefSharpArguments.SubProcessTypeArgument + "=", StringComparison.Ordinal)) { // Run the CEFSharp browser subprocess. return RunBrowserSubprocess(args); } else { // Run the regular application. RunGui(); return 0; } }

Here, RunBrowserSubprocess() would contain the code from the Main() method of CefSharp.BrowserSubprocess, and RunGui() would do the regular Application.Run(new Form1()).
(The code of RunBrowserSubprocess() could also be implemented as utiltiy method in the .NET Core 3.0 package of CefSharp.)

This means you won't have to bother with building and copying the correct subprocess executable before running your main application.
(A minor disadvantage of this is that you cannot implement the command line argument --type= for your own use.)

What do you think?
Thanks!

Regarding the subprocess handling for .NET Core, my idea was the following:

  • Switch project CefSharp.BrowserSubprocess to the .NET Core SDK and multi-target for net452 and netcoreapp3.0, so that for net452 the result is a EXE (like today) and for netcoreapp3.0 the result is a DLL, e.g.:
  <PropertyGroup>
    <TargetFrameworks>net452;netcoreapp3.0</TargetFrameworks>
    ...
  </PropertyGroup>

  <PropertyGroup Condition="'$(TargetFramework)'!='netcoreapp3.0'">
    <OutputType>WinExe</OutputType>
    <ApplicationManifest>app.manifest</ApplicationManifest>
    <Prefer32Bit>false</Prefer32Bit>
  </PropertyGroup>
  • Make the Program.Main method internal and add a public method like the following that is only compiled for .NET Core:
    ```c#

    if NETCOREAPP

    public static class CefSharpBrowserSubprocess
    {
    public static void HandleSubprocess()
    {
    // Check if the first argument starts with "--type=", in which case
    // we run the subprocess logic. Otherwise, we simply return and allow
    // the app run its own logic.
    var args = Environment.GetCommandLineArgs().Skip(1);
    if (args.HasArgument(CefSharpArguments.SubProcessTypeArgument + "="))
    {
    // Run the subprocess.
    int exitCode = Program.Main(args.ToArray());

            // Exit directly so that the remaining application logic is not run.
            Environment.Exit(exitCode);
        }
    }
    

    }

    endif

* Adjust the NuGet files so that for projects targeting .NET Core, a reference to `CefSharp.BrowserSubprocess.dll` is added.
* In `CefSharp.Core`, adjust `CefSettings.BrowserSubprocessPath` to specify `"CefSharp.BrowserSubprocess.exe"` when running on .NET Framework, and specify the current executable path when running on .NET Core (this can be done with a runtime check, e.g. using [`RuntimeInformation.FrameworkDescription`](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.runtimeinformation.frameworkdescription?view=netcore-3.0); but that would require compiling for .NET Framework 4.7.1 or higher).

That way, a user could modify the `Main` method in a WinForms project like this when adding CefSharp:

```diff
         [STAThread]
         static void Main()
         {
             Application.SetHighDpiMode(HighDpiMode.SystemAware);
+            
+            // Handle the CefSharp browser subprocess logic on start-up.
+            CefSharpBrowserSubprocess.HandleSubprocess();
+            
             Application.EnableVisualStyles();
             Application.SetCompatibleTextRenderingDefault(false);
             Application.Run(new Form1());
         }

In this case, the application executable would also run the browser subprocess logic, and a separate EXE is no longer needed.

With that change, I think the only other thing needed is to adjust the NuGet spec files to declare dependencies to .NETCoreApp3.0 so the dependencies will resolve when compiling for .NET Core.
(Note: The logic that currently allows to compile .NET Framework projects for AnyCPU might no longer work on .NET Core, but that shouldn't be a big issue because you will probably publish a self-contained application which is platform-specific.)


On a related note, I think using the same executable for the app and the browser subprocess will also solve a rendering issue that we experienced with a WPF app using CefSharp.WinForms: When moving the window between monitors with different DPI settings, the browser control starts to display some contents in an incorrect size when moving the mouse, like this:
grafik

This seems to occur because the subprocess executable (CefSharp.BrowserSubprocess.exe) declares <dpiAware>true/PM</dpiAware> (per-monitor DPI aware V1), whereas in our case the application only supports <dpiAware>true</dpiAware> (System DPI aware).

Whereas when using the same executable, both processes will use the same DPI settings, so this issue will no longer occur there.

What do you think?

Thanks!

@kpreisser Thanks for the very detailed summaries, some very useful insights πŸ‘

  • Switch project CefSharp.BrowserSubprocess to the .NET Core SDK and multi-target for net452 and netcoreapp3.0, so that for net452 the result is a EXE (like today) and for netcoreapp3.0 the result is a DLL, e.g.:

For simplicity we'll just rewrite the Main method in VC++ and move the code into CefSharp.BrowserSubprocess.Core

  • Make the Program.Main method internal and add a public method like the following that is only compiled for .NET Core:

Will keep the changes to CefSharp.BrowserSubprocess at a minimum, replace the Main body with a simple call to a method in CefSharp.BrowserSubprocess.Core that codes the actual work, this can be reused. Will need some fairly descriptive comments.

  • Adjust the NuGet files so that for projects targeting .NET Core, a reference to CefSharp.BrowserSubprocess.dll is added.

My initial plan is to create a new CefSharp.DotNetCore Nuget package, it'll depend on CefSharp.Common and add the required include for CefSharp.BrowserSubprocess.Core.dll, only minor changes will need to be made to the Nuget packages to support this.

  • In CefSharp.Core, adjust CefSettings.BrowserSubprocessPath to specify "CefSharp.BrowserSubprocess.exe" when running on .NET Framework, and specify the current executable path when running on .NET Core (this can be done with a runtime check, e.g. using RuntimeInformation.FrameworkDescription; but that would require compiling for .NET Framework 4.7.1 or higher).

Some sort of runtime check would be idea, will have to investigate alternatives as .Net 4.5.2 is our current target (I still get people asking to target .Net 4.0). Alternatively we'll provide some sort of helper class in the new DotNetCore specific Nuget package.

With that change, I think the only other thing needed is to adjust the NuGet spec files to declare dependencies to .NETCoreApp3.0 so the dependencies will resolve when compiling for .NET Core.

What does declare dependencies to .NETCoreApp3.0 actually get us? As it stands I don't see any great benefit in compiling an actual .Net Core specific set of dlls as the current ones appear to load correctly. If we can work out a runtime check then we'll add that to any calls that would require WCF so that users get an exception.

This seems to occur because the subprocess executable (CefSharp.BrowserSubprocess.exe) declares <dpiAware>true/PM</dpiAware> (per-monitor DPI aware V1), whereas in our case the application only supports <dpiAware>true</dpiAware> (System DPI aware).

It's hard to please everyone, the general idea is to provide a sensible set of defaults and let you customise as required. I rewrote the entire CefSharp.BrowserSubprocess.exe quite some time ago so it's just a single file, makes it easy to implement your own when the need arises.

Hi @amaitland,

thanks for your reply!

For simplicity we'll just rewrite the Main method in VC++ and move the code into CefSharp.BrowserSubprocess.Core

Will keep the changes to CefSharp.BrowserSubprocess at a minimum, replace the Main body with a simple call to a method in CefSharp.BrowserSubprocess.Core that codes the actual work, this can be reused. Will need some fairly descriptive comments.

Agreed, that way no change to the project file for CefSharp.BrowserSubprocess is needed - the .NET Core project can then reference CefSharp.BrowserSubprocess.Core.dll to call that method.

What does declare dependencies to .NETCoreApp3.0 actually get us? As it stands I don't see any great benefit in compiling an actual .Net Core specific set of dlls as the current ones appear to load correctly. If we can work out a runtime check then we'll add that to any calls that would require WCF so that users get an exception.

Sorry, actually here I only meant that the .nuspec file probably needs a <group targetFramework=".NETCoreApp3.0"> element in addition to <group targetFramework=".NETFramework4.5.2">, so that the transitive dependencies to the other NuGet packages will be resolved correctly for .NET Core projects. The projects itself (CefSharp.WinForms etc.) don't need to be changed, because like you said the binaries for .NET Framework 4.5.2 already work on .NET Core 3.0.

For example, right now if I create a new .NET Core 3.0 project and add <PackageReference Include="CefSharp.WinForms" Version="75.1.141" />, then the project will have a reference to CefSharp.WinForms, but is missing references to CefSharp.Common, CefSharp etc. and the redist files. Instead I currently have to manually add packages for all references:

  <PackageReference Include="CefSharp.WinForms" Version="75.1.141" />
  <PackageReference Include="CefSharp.Common" Version="75.1.141" />
  <PackageReference Include="cef.redist.x64" Version="75.1.14" />
  <PackageReference Include="cef.redist.x86" Version="75.1.14" />

However, this also does not yet work in the .NET Core 3.0 project because at runtime it will not find CefSharp.WinForms.dll even though the file exists. I think this is because the reference is declared private in CefSharp.WinForms.props:

      <ItemGroup>
        <Reference Include="CefSharp.WinForms">
          <HintPath>$(MSBuildThisFileDirectory)..\CefSharp\x64\CefSharp.WinForms.dll</HintPath>
          <Private>False</Private>
        </Reference>
      </ItemGroup>

This seems to have the effect that the dependency is not specified in the .deps.json file when building the project, so that the .NET Core CLR doesn't load the assembly. It should work when using <Private>True</Private> (but I guess this change would mean that the support for AnyCPU would no longer work; but as said I think we can ignore that for .NET Core projects).


To summarize, CefSharp.WinForms already works today on a .NET Core 3.0 WinForms project (created with dotnet new winforms) when using a project file like the following, and setting the <Platform> explicitely to x64 or x86 depending on the used .NET Core runtime – provided that .NET Framework 4.5.2 or higher is installed on the machine as that is currently used by CefSharp.BrowserSubprocess.exe:

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <RootNamespace>MyNetCoreApp</RootNamespace>
    <UseWindowsForms>true</UseWindowsForms>
    <Platforms>x86;x64</Platforms>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="CefSharp.WinForms" Version="75.1.141" />
    <PackageReference Include="CefSharp.Common" Version="75.1.141" />
    <PackageReference Include="cef.redist.x64" Version="75.1.14" />
    <PackageReference Include="cef.redist.x86" Version="75.1.14" />
  </ItemGroup>

  <ItemGroup>
    <Reference Update="CefSharp">
      <Private>true</Private>
    </Reference>
    <Reference Update="CefSharp.Core">
      <Private>true</Private>
    </Reference>
    <Reference Update="CefSharp.WinForms">
      <Private>true</Private>
    </Reference>
  </ItemGroup>
</Project>

Thanks!

Additionally, I found that the condition in CefSharp.WinForms.targets currently checks for the Platform Variable like this:

<When Condition="'$(Platform)' == 'x64'">

Maybe this needs to be changed to use PlatformTarget instead of Platform, because e.g. when you publish a self-contained .NET Core app with dotnet publish -f netcoreapp3.0 -r win-x64, the PlatformTarget will be x64, but Platform will still be AnyCPU; thus the check will currently fail.

Thanks!

For example, right now if I create a new .NET Core 3.0 project and add <PackageReference Include="CefSharp.WinForms" Version="75.1.141" />, then the project will have a reference to CefSharp.WinForms, but is missing references to CefSharp.Common, CefSharp etc. and the redist files. Instead I currently have to manually add packages for all references:

It was my understanding (and that's a limited understanding at this point) that transitive dependencies meant that only top level references were included?

This seems to have the effect that the dependency is not specified in the .deps.json file when building the project, so that the .NET Core CLR doesn't load the assembly. It should work when using <Private>True</Private> (but I guess this change would mean that the support for AnyCPU would no longer work; but as said I think we can ignore that for .NET Core projects).

The files should be copied via the .targets file. What you are seeing may actually be the same as #2642

Additionally, I found that the condition in CefSharp.WinForms.targets currently checks for the Platform Variable like this:

The current packages require that you set the solution target, this is a current limitation.

Maybe this needs to be changed to use PlatformTarget instead of Platform, because e.g. when you publish a self-contained .NET Core app with dotnet publish -f netcoreapp3.0 -r win-x64, the PlatformTarget will be x64, but Platform will still be AnyCPU; thus the check will currently fail.

Last I checked this isn't possible, PlatformTarget is defined after the .props files are included, so it's not actually set early enough to be useful.

If you have the time to contribute a .Net Core example to https://github.com/cefsharp/CefSharp.MinimalExample that would make debugging/testing much easier.

Hi @amaitland,

For example, right now if I create a new .NET Core 3.0 project and add <PackageReference Include="CefSharp.WinForms" Version="75.1.141" />, then the project will have a reference to CefSharp.WinForms, but is missing references to CefSharp.Common, CefSharp etc. and the redist files. Instead I currently have to manually add packages for all references:

It was my understanding (and that's a limited understanding at this point) that transitive dependencies meant that only top level references were included?

Sorry, I'm not sure if I fully understood what you say here. With 'transitive reference', I meant that if project MyWinFormsApp references CefSharp.WinForms, and CefSharp.WinForms references CefSharp.Common, then MyWinFormsApp will also get a (transitive) reference to CefSharp.Common.

I don't have detailed knowledge about how NuGet packages work, but I think that when the .nuspec file of CefSharp.WinForms would be changed to contain the following:

    <dependencies>
      <group targetFramework=".NETFramework4.5.2">
        <dependency id="CefSharp.Common" version="[75.1.141]" />
      </group>
      <group targetFramework=".NETCoreApp3.0">
        <dependency id="CefSharp.Common" version="[75.1.141]" />
      </group>
    </dependencies>

then CefSharp.Common should be correctly included when the project only contains <PackageReference Include="CefSharp.WinForms" Version="75.1.141" />. VS will then display the package references as follows:
grafik

Currently, when using a .NET Core 3.0 project I also have to add <PackageReference Include="CefSharp.Common" Version="75.1.141" />, and the VS will display the packages like this:
grafik

The files should be copied via the .targets file. What you are seeing may actually be the same as #2642

Actually, the files are copied correctly into the output directory, but because the <Reference> element contains <Private>false</Private>, the references to these DLLs will not be specified in the <exe>.deps.json file when compiling the project, which means the CoreCLR will not load them (as AFAIK it will only load libraries that are specified in that JSON file).

Last I checked this isn't possible, PlatformTarget is defined after the .props files are included, so it's not actually set early enough to be useful.

OK, thanks. It might be worth to check if this is also the case with SDK-style (.NET Core) projects.

If you have the time to contribute a .Net Core example to https://github.com/cefsharp/CefSharp.MinimalExample that would make debugging/testing much easier.

OK, I will submit a PR with a minimal .NET Core example.

Thank you!

Was testing @kpreisser's method of adding all packages individually and adding the private true in a WPF project and got the following error:

Unable to find an entry point named 'CopyMemory' in DLL 'kernel32.dll'.'

Looking around i found [https://github.com/dotnet/coreclr/issues/24008]https://github.com/dotnet/coreclr/issues/24008 where @vatsan-madhavan points out that:

In .NET Framework there was a special case for a few function names and CopyMemory happened to be one of them. The special case was removed in .NET Core. In order to address this in your code, please update the attribute to include the following: [DllImport EntryPoint="RtlMoveMemory"]. If the EntryPoint property is set as above, the P/Invoke will work in both .NET Framework and .NET Core

Its not just CopyMemory, as you can see in [https://github.com/AArnott/pinvoke/issues/431]https://github.com/AArnott/pinvoke/issues/431, other memory related functions are also affected - MoveMemory, CopyMemory, FillMemory and ZeroMemory at least

@537mfb Thanks! I created #2885 to fix the CopyMemory declaration.

I also updated https://github.com/cefsharp/CefSharp.MinimalExample/pull/57 to include a minimal WPF example using .NET Core 3.0 which should work once the CopyMemory declaration is fixed.

@537mfb Thanks for the links πŸ‘
@kpreisser Thanks for the PR and updated WPF example πŸ‘

I am planning on releasing 75.1.142 in the next couple of days, I've committed https://github.com/cefsharp/CefSharp/commit/c11157fa8e77991baab83f417dfb78ba22f1e34b into the cefsharp/75 branch (copy and paste fail I've linked the incorrect issue, oh well) which contains the bare minimum required to get WPF working.

@kpreisser Thanks for the quick PR
@amaitland Thanks for the update

Started the refactor of the BrowserProcess see #2891 there is a little bit to go before it's done.

Sorry, actually here I only meant that the .nuspec file probably needs a <group targetFramework=".NETCoreApp3.0"> element in addition to <group targetFramework=".NETFramework4.5.2">, so that the transitive dependencies to the other NuGet packages will be resolved correctly for .NET Core projects.

@kpreisser Have you tested that adding .NETCoreApp3.0 to the group resolves the dependency issue? If so are you able to create a PR?

@kpreisser Have you tested that adding .NETCoreApp3.0 to the group resolves the dependency issue? If so are you able to create a PR?

Yes, I tested it with the minimal .NET Core examples and the transitive references were successfully resolved. I created PR #2894 to add these.
Thanks!

I've committed c11157f into the cefsharp/75 branch (copy and paste fail I've linked the incorrect issue, oh well) which contains the bare minimum required to get WPF working.

Appears RtlCopyMemory only works in x64, reverted to using RtlMoveMemory in https://github.com/cefsharp/CefSharp/commit/050d354b82e054be122f1c2ca70bc64c8ec4900f

Suggestion that EntryPoint = "CopyMemory" actually mapped to RtlMoveMemory anyway. Will look at updating to RtlCopyMemory in the master branch.

My initial plan is to create a new CefSharp.DotNetCore Nuget package, it'll depend on CefSharp.Common and add the required include for CefSharp.BrowserSubprocess.Core.dll, only minor changes will need to be made to the Nuget packages to support this.

Thanks to @kpreisser #2895 eliminates the requirements for a separate package, we'll go with this option instead.

Do you already know when you will release the .NET Core Support?

Do you already know when you will release the .NET Core Support?

Note that it's already possible use the current NuGet packages (75.1.142) within .NET Core 3.0 projects (with some limitations).

The CefSharp.MinimalExample repo contains example .NET Core 3.0 projects for WinForms, WPF and OffScreen (in solution CefSharp.MinimalExample.netcore.sln).
See also ".NET Core support" in README.md.

If you want to completely avoid a dependency on .NET Framework 4.5.2 (which is currently still required by the CefSharp.BrowserSubprocess.exe), you can implement the code of the CefSharp.BrowserSubprocess.Program.Main() method in your own Main() method, so that it is run if the first argument starts with --type=, and otherwise the regular GUI application is run.

(Edit: But for that you would need to manually add a reference to CefSharp.BrowserSubprocess.Core.dll until #2895 is merged.)

In that case you would also need to set CefSettings.BrowserSubprocessPath = Process.GetCurrentProcess().MainModule.FileName (but that currently doesn't seem to work when you want to publish the application as single EXE with -p:PublishSingleFile=true).

There is a PR #2891 to refactor the subprocess handling for better .NET Core support.

Really looking forward to this!

Will it be possible to create cross-platform application with .net core, so it can work on Windows and MacOS? Minimal example is referencing "Microsoft.WindowsDesktop.App.WindowsForms" wich will not work on MacOS. Are you considering Cefsharp with Avalonia, so it will be cross-platform?

I mean something like this https://github.com/VitalElement/CefGlue.Core where .net core introduces Windows, MacOs and Linux

Will it be possible to create cross-platform application with .net core, so it can work on Windows and MacOS?

@dmitrya1979 Unfortunately no. Microsoft have stated they have no current plans to port C++/CLI to MacOS/Linux, see https://devblogs.microsoft.com/cppblog/the-future-of-cpp-cli-and-dotnet-core-3/ for a very recent confirmation of this.

Microsoft has started implementing C++/CLI as part of .Net Core you can track the issue dotnet/coreclr#18013 They are only adding support for Windows initially. See also dotnet/coreclr#659

See also my comments in https://github.com/cefsharp/CefSharp/issues/2796#issue-450564341

You can subscribe to dotnet/coreclr#659 if you are interested in the subject.

In .NET Core 3.1 preview 2, C++/CLI support has been added.
I think it's time to port CefSharp to .NET Core.

See https://devblogs.microsoft.com/cppblog/an-update-on-cpp-cli-and-dotnet-core/ and https://devblogs.microsoft.com/dotnet/announcing-net-core-3-1-preview-2/

I think it's time to port CefSharp to .NET Core.

@hez2010 For what reason exactly? What problems are you seeing loading the existing dlls?

@amaitland Sorry, what I actually mean is to add .NET Core 3.0 nuget package support :)

However .NET Core provides higher performance and richer BCLs, I think it valuable to add a .NET Core version of CefSharp.

I was actually thinking a version of CefSharp that runs on Mac via NetCore3. Should that be possible with this announcement?

Should that be possible with this announcement?

@jahmai Nope. Currently there's no cross-platform C++/CLI and Microsoft has no plan for it yet. It also needs some works from gcc and clang to support compiling to MSIL.

I thought .Net core 3 was already supported. I am actually using it currently in a .net core 3 project.

@jahmai Nope. Currently there's no cross-platform C++/CLI and Microsoft has no plan for it yet. It also needs some works from gcc and clang to support compiling to MSIL.

Excitement rescinded.

Sorry, what I actually mean is to add .NET Core 3.0 nuget package support :)

@hez2010 It's already possible to use the current packages with .Net Core 3.0. All the details are listed above. Credit goes to @kpreisser

This issue only remains open as there are still some improvements to make integration easier.

I thought .Net core 3 was already supported

@Telavian Correct, it is.


A more modern set of Nuget packages will be created to better support PackageReference style projects, these will be the preferred packages for .Net Core 3.x. See #2795 (When this issue is resolved then this one will likely be closed).

The next major release of CefSharp will include #2891 which will make it easier to use your own exe for the Browser SubProcess.

Hi All,
Any ideas when the PackageReference packages will be available? I'm really looking forward to testing this out.

Also - RE .NET Core -
Does the Sync and Async Javascript library use WCF or just the sync?

You can use the current packages as is with a few limitations, see https://github.com/cefsharp/CefSharp.MinimalExample#net-core-support for an example.

Only the sync JavaScript Binding requires WCF, the Async version uses the IPC provided by CEF.

Under .Net Core when VC++ is not installed the error message is different, the FAQ should be updated. The error message is misleading, unfortunately we have no control over that.

https://github.com/cefsharp/CefSharp/issues/3024 has stack trace

The MinimalExample has been updated to demo self hosting the BrowserSubProcess. The changes were made in commit https://github.com/cefsharp/CefSharp.MinimalExample/commit/898eb755c6bb7f504f9b5bdc889ff9142e105848 The OffScreen example is crashing on exit so it has been updated, the line that specifies the BrowserSubProcessPath has been commented out until this has been fixed.

This eliminates the requirement to have .Net 4.5.2 or greater installed.

IMPORTANT:

You need to manually include CefSharp.BrowserSubprocess.Core in your proj file. The following example will work for x86/x64/Win32. Once #2795 is complete this step won't be required.

<!-- Include CefSharp.BrowserSubprocess.Core so we can selfhost the BrowserSubProcess using our exe -->
<Choose>
<When Condition="'$(PlatformTarget)' == 'x64'">
  <ItemGroup>
    <Reference Include="CefSharp.BrowserSubprocess.Core">
      <HintPath>$(CefSharpBrowserProcessCore64)</HintPath>
      <Private>true</Private>
    </Reference>
  </ItemGroup>
</When>
<!-- x86, Win32 and AnyCPU -->
<Otherwise>
  <ItemGroup>
    <Reference Include="CefSharp.BrowserSubprocess.Core">
      <HintPath>$(CefSharpBrowserProcessCore32)</HintPath>
      <Private>true</Private>
    </Reference>
  </ItemGroup>
</Otherwise>
</Choose>

Example application entry point for WPF/WinForms. CEF/Chromium uses the --type command line arg for launching the subproceses, you should see --type=gpu-process, --type=renderer, --type=utility, --type=crashpad-handler, etc.

```c#
public static class Program
{
///


/// Application Entry Point.
///

[STAThread]
public static int Main(string[] args)
{
//For Windows 7 and above, app.manifest entries will take precedences of this call
Cef.EnableHighDPISupport();

    //We are using our current exe as the BrowserSubProcess
    //Multiple instances will be spawned to handle all the 
    //Chromium proceses, render, gpu, network, plugin, etc.
    var subProcessExe = new CefSharp.BrowserSubprocess.BrowserSubprocessExecutable();
    var result = subProcessExe.Main(args);
    if (result > 0)
    {
        return result;
    }

    //We use our current exe as the BrowserSubProcess
    var exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;

    var settings = new CefSettings()
    {
        //By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
        CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache"),
        BrowserSubprocessPath = exePath
    };

    //Example of setting a command line argument
    //Enables WebRTC
    settings.CefCommandLineArgs.Add("enable-media-stream");

    //Perform dependency check to make sure all relevant resources are in our output directory.
    Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);

    //Example for WPF
    var app = new App();
    app.InitializeComponent();
    return app.Run();

    //Example for WinForms
    var browser = new BrowserForm();
            Application.Run(browser);

    return 0;
}

}
```

Run the WPF example in Winows7 sp1 machine, it is also crashed on exit. Could you please tell me how to resolve this?

Run the WPF example in Winows7 sp1 machine, it is also crashed on exit

@dora912 Just saying it doesn't work on Win7 using WPF Example is too vague.

Please provide a detailed report including:

Anyone who is up for testing the more modern set of Nuget packages see
https://github.com/cefsharp/CefSharp/issues/2795#issuecomment-587991081 for details. Looking for a few people to provide feedback before they'll be released for general consumption.

Is there a official sample of the .net core wpf ? I can't find any of the BrowserSubprocessExecutable class in current nuget package

I'm a bit confusing about why CefSharp.BrowerSubProcess.Core is not a .exe file on windows, base on my test, if a winexe project PackageReferece a exe project for .net core 3.1 is also copy the .exe file (the loader) to the buildouput too , if we need to just run the exe , why not just include all the asset of PublishTrimmed + selft-contained to the nuget? (include the loader and the app dll )

Is there a official sample of the .net core wpf

Commit https://github.com/cefsharp/CefSharp.MinimalExample/commit/898eb755c6bb7f504f9b5bdc889ff9142e105848 adds support for self hosting the BrowserSubProcess as detailed in https://github.com/cefsharp/CefSharp/issues/2796#issuecomment-583932675 (which also includes this link).

I'm a bit confusing about why CefSharp.BrowerSubProcess.Core is not a .exe file on windows

CefSharp.BrowerSubProcess.Core.dll exists as a library for the purpose of self hosting the BrowserSubProcess, this is desirable in many cases. The Core in the dll name is in no way a reference to .Net Core, it's a CLI/C++ library that targets .Net 4.5.2 currently.

if we need to just run the exe , why not just include all the asset of PublishTrimmed + selft-contained to the nuget? (include the loader and the app dll )

You are welcome to submit a PR with some proposed changes, you can discuss them there. Including a .exe as a library reference is not standard practice and is something we're unlikely to go with. For self contained self hosting the BrowserSubProcess is the current recommended option.

It's unlikely we'll be able to support all of the uses cases out of the box (unless we can convince Microsoft to make some improvements).

I'm trying use ChromiumWebBrowser in an NET Core 3.1 Class Library.
I have modified the .csproj according to the netcore .csproj here: https://github.com/cefsharp/CefSharp.MinimalExample/tree/master/CefSharp.MinimalExample.Wpf

But the BrowserSubProcess and other initialization has to be done from a Main method (Program.netcore.cs in the example)

A a Class Library has no Program.cs, how to start the BrowserSubProcess and do the initialization?
Also, I want to target AnyCPU but therefore is also an App or a Program class required which I don't have in a Class Library. AnyCPU examples: #1714

Or do I have to do the initialization in my WinExe project and can the Class Library use the BrowserSubProcess from the WinExe project?

An example of how the two .csrpoj files need to look + initiliazation code would be helpful.

A a Class Library has no Program.cs, how to start the BrowserSubProcess and do the initialization?

To self host the BrowserSubProcess then the code must be in the applications main entry point. The application will be spawned multiple times to support the Chromium Multi-process Architecture. Your class library can easily expose a helper method to wrap the required code.

Overall there are plenty of options available for providing a BrowserSubProcess

  • Self host using your application as the BrowserSubProcess, the .Net Core example as part of the CefSharp.MinimalExample has been upgraded to demo this.
  • You can still use the current CefSharp.BrowserSubprocess.exe if your target machines have .Net 4.5.2 or greater installed.
  • You can create your own .Net Core exe specifically to host the BrowserSubProcess, this is fairly trivial.
  • In the near future there will be a CefSharp.BrowserSubProcess.NetCore set of packages that will provide a .Net Core option, this is not ready yet.

I want to target AnyCPU

There are no .Net Core AnyCPU examples as it's not clear that it's possible to support. There are many limitations currently with .Net Core

  • There is no AnyCPU exe, when you publish you must target a specific platform https://github.com/dotnet/sdk/issues/1906
  • There is no probing privatePath option in .Net Core, support for loading from a sub directory is very limited currently see https://github.com/dotnet/sdk/issues/10366
  • .Net Core will only load files that are included in .deps.json (as described in https://github.com/cefsharp/CefSharp/issues/2796#issuecomment-524820012). This makes dynamically loading files are runtime near impossible.

For your scenario of having an AnyCPU Class Library you'll have to do your own research to see what is possible. Personally I'd suggest keeping things simple by having an x86 and x64 target.

@Sybren- I'd also suggest you all the comments in this issue as there is a lot of relevant background information here already.

  • .Net Core will only load files that are included in .deps.json (as described in #2796 (comment)). This makes dynamically loading files are runtime near impossible.

@kpreisser I think I'm following what is being described in the comment, but I'm not 100% sure. if you can create a simple barebones project that illustrates the problem you are encountering, I can try to troubleshoot and see if we can come up with a solutions (or craft a viable workaround).

For your scenario of having an AnyCPU Class Library you'll have to do your own research to see what is possible. Personally I'd suggest keeping things simple by having an x86 and x64 target.

Have you had a chance to look at the cross platform targeting documentation yet?

If you don't have architecture specific code, then why not just build a netstandard2.1 targeted library?

If you truly have architecture specific code, then you'll probably need a code, build that generates reference-assemblies, RID-specific runtime assemblies and separately and also have a packaging architecture that uses the _bait & switch_ technique_ (which is not very well documented). I wouldn't recommend going down this path if you can help it. Adding _some_ complexity to make your library conform to nestandard2.1 would be worth it ultimately. But if you must, even this can be done with a little effort.
Microsoft.NetCore.App is a good example of a package that illustrates how this technique is used. You might find it in your NuGet cache already, or else you can download it from NuGet.org and peek into it using NuGetPackageExplorer. If you look into _runtime.json_ in the package, you'll see how the base package 'links' to RID-specific packages. A project only needs to PackageReference a package such as this - the RID-specific packages would be automatically selected and restored by NuGet intelligently on a need basis. (Microsoft.NetCore.App itself is not intended to be used in PackageReference scenarios - I'm just calling attention to it to illustrate the _bait & switch_ technique).

There is no probing privatePath option in .Net Core, support for loading from a sub directory is very limited currently see dotnet/sdk#10366

This can be worked around in an inline MSBuild task. Take a look at _AssemblyResolverForSystemReflectionMetadataLoadContext task here. There are several things that can trip you, but it can be done reliably if you are in reasonable control of some of the parameters involved.

@vatsan-madhavan Thanks for taking the time to comment πŸ‘ Any insights you could give would be greatly appreciated. Even just a pointer to the appropriate place to ask some additional questions would be helpful.

I think I'm following what is being described in the comment, but I'm not 100% sure. if you can create a simple barebones project that illustrates the problem you are encountering, I can try to troubleshoot and see if we can come up with a solutions (or craft a viable workaround).

For the current set of Nuget packages (CefSharp.WinForms, CefSharp.Wpf, CefSharp.OffScreen) the project will compile, the dlls are included in the bin directory, they are however not included in .deps.json, which I believe is described in https://github.com/dotnet/sdk/issues/2162#issuecomment-382852510

  • The unmanaged dlls are included with <Private>false</Private>
  • They are copied with None entries in a .targets file.

The current Nuget packages allow for an old school __bait and switch__ for AnyCPU support and an optional $(CefSharpTargetDir) property in MSBuild used to customise the file copy location. It's fairly common complain that CefSharp pollutes the bin folder with too many dlls.

I was hoping to create a new set of Nuget packages that utilise runtimes/{rid}/native for the unmanaged dlls and resources.

The folder structure used by the Chromium Embedded Framework(CEF) looks like the following screenshot
folderstructure

  • My first attempt included the Locales and Swiftshader folders in the native folder. Unfortunately the folder structure is not maintained as per https://github.com/NuGet/Home/issues/7698

    • The Swiftshader folder must be relative to libcef.dll as Chromium decides at runtime which set of dlls are used to render WebGL (either hardware or software rendering).

  • Second attempt was to use contentFiles to copy the two folders into the native folder, this appeared to work initially, unfortunately it only works when the package is directly referenced, when it's included as a transitive reference then they folders aren't copied to the native folder.

If you have any suggestions or potential workarounds for this I'd be interested in testing them out, I can provide an example without too much effort.

Ignore the missing files for now (copying them manually to be precise) the Mixed Mode CLI/C++ assembly (CefSharp.Core.dll) is unable to automatically load libcef.dll when it's located in the runtimes/{rid}/native folder. If I manually call NativeLibrary to load the assembly then I can successfully load CefSharp.Core.dll. I know VC++ is fairly new to .Net Core so I'm wondering if the scenario is supported yet? I can provide an example, if required.

There are some other issues that I've run into along the way:

  • PackageReference doesn't copy pdb files see https://github.com/dotnet/sdk/issues/1458#issuecomment-577286780
  • Folder with only Visible="False" items still appears in Solution Explorer https://github.com/dotnet/project-system/issues/5859

Have you had a chance to look at the cross platform targeting documentation yet?

I haven't yet no, I'll check it out thanks.

If you don't have architecture specific code, then why not just build a netstandard2.1 targeted library?

The situation as it stands

  • We target .Net 4.5.2
  • The Mixed Mode CLI/C++ dlls are built with VC++ 2015(v140)
  • Visual Studio 2013 can install/use the current set of Nuget packages.

Adding _some_ complexity to make your library conform to nestandard2.1 would be worth it ultimately

  • As per https://docs.microsoft.com/en-us/dotnet/core/porting/cpp-cli#ccli-net-core-limitations

    • C++/CLI projects can't target .NET Standard, only .NET Core (or .NET Framework)., unless this has changed or I'm interpriting this incorrectly targeting .Net Standard isn't an option.

    • C++/CLI projects can't multitarget multiple .NET platforms. If you need to build a C++/CLI project for both .NET Framework and .NET Core, use separate project files., this isn't a show stopper, it's just a extra work to maintain two project files.

  • The project uses WCF currently, we'd have to conditionally compile all references

There are quite a few other build environment complexities that I won't get into now.

Microsoft.NetCore.App is a good example of a package that illustrates how this technique is used. You might find it in your NuGet cache already, or else you can download it from NuGet.org and peek into it using NuGetPackageExplorer. If you look into _runtime.json_ in the package, you'll see how the base package 'links' to RID-specific packages. A project only needs to PackageReference a package such as this - the RID-specific packages would be automatically selected and restored by NuGet intelligently on a need basis. (Microsoft.NetCore.App itself is not intended to be used in PackageReference scenarios - I'm just calling attention to it to illustrate the _bait & switch_ technique).

I downloaded microsoft.netcore.app.2.2.8.nupkg a few months ago as I started doing research into using a runtime.json file as I'd seen references suggesting it might be the solution, unfortunately I couldn't find any official documentation. Any chance there is some documentation somewhere that I missed?

I got stuck on the earlier issues and reverted to a more traditional .targets approach in the short term.

This can be worked around in an inline MSBuild task. Take a look at _AssemblyResolverForSystemReflectionMetadataLoadContext task here. There are several things that can trip you, but it can be done reliably if you are in reasonable control of some of the parameters involved.

Thanks for the reference, hopefully others will find this helpful πŸ‘

I was hoping to create a new set of Nuget packages that utilise runtimes/{rid}/native for the unmanaged dlls and resources.

I took a look at CefSharp.Winforms, and I think you have already tried the one thing I would have suggested - which is to attempt <Reference Include="..." /> directly.

Attempting to build a normalized structure within NuGet package based on folder-conventions would be the next thing to try, which you've already figured out I think.

re: the swiftshader problem...

unfortunately it only works when the package is directly referenced, when it's included as a transitive reference then they folders aren't copied to the native folder.

Have you tried changing PrivateAssets (in the PackageReference?) to analyzers;build? The default normally includes contentfiles.

re: c++/cli: you're absolutely right, it can only build netcoreap* or netfx targets. I hadn't realized that you were dealing with c++/cli when I made that comment.

unfortunately I couldn't find any official documentation. Any chance there is some documentation somewhere that I missed?

You didn't miss any - there just isn't any out there. Folks including me who have implemented this have done so through trial and error.

The general idea goes like this:

  • Number of distinct packages needed and suggested nomenclature:

    • $(Package).$(version).nupkg

    • For each applicable $(RID)

    • runtime.$(RID).$(Package).$(version).nupkg (e.g., runtime.win-x64.$(Package).$(version).nupkg)

  • Content/Structure

    • Follow folder conventions

    • Main package $(Package).$(version).nupkg will have RID-neutral artifacts.

    • Notably, ref/$(tfm) content will be hosted in this bundle.

    • The main package will also contain a runtime.json file. It's content-structure will be described later.

    • The main package can be empty/devoid of any binaries, and may only carry text files (like LICENSE, COPYRIGHT etc.) and runtime.json.

    • The RID-specific packages will contain content that are specific to the $(RID) mentioned in the package name.

    • Notably, architecture specific binaries under runtimes/$(RID)/native path will be part of these packages.

    • runtime.json file.

    • The main $(Package).$(version).nupkg package contains a runtime.json file that associates this architecture-neutral package with various $(RID) specialized versions of the same package with names like runtime.$(RID).$(Package).$(version).nupkg.

    • The content/structure of this file is as follows:

  "runtimes": {
    "$(RID1)": {
      "$(PackageName)": {
        "runtime.$(RID1).$(PackageName)": "$(version)"
      }
    },
    "$(RID2)": {
      "$(PackageName)": {
        "runtime.$(RID2).$(PackageName)": "$(version)"
      }
    }, 
    "$(RID3)": {
       ..
    }
  }
}

A concrete example may look like this:

  "runtimes": {
    "win-x64": {
      "$(NormalizedPackageName)": {
        "runtime.win-x64.$(PackageName)": "$(PackageVersion)"
      }
    },
    "win-x86": {
      "$(NormalizedPackageName)": {
        "runtime.win-x86.$(PackageName)": "$(PackageVersion)"
      }
    }
  }
}

@vatsan-madhavan Thanks for the very detailed reply, greatly appreciated πŸ‘

I took a look at CefSharp.Winforms,

I'll rework the demo to illustrate the problems I'm having using runtimes/{rid}/native with the Mixed Mode CLI/C++ dlls loading the unmanaged dlls, perhaps there is something trivial I'm missing or perhaps switching to the runtime.json will resolve the issues.

Hopefully have a demo of the problem shortly.

Have you tried changing PrivateAssets (in the PackageReference?) to analyzers;build? The default normally includes contentfiles.

I haven't yet no, I'll give that a try.

I did see the Nuget 5+ supports buildTransitive which should allow me to use a .targets file to copy the swiftshader and locales folders to the runtimes/{rid}/native folder, they're only required at runtime so this sounds workable to me.

Folks including me who have implemented this have done so through trial and error.

Thanks again for taking the time to write such a detailed post, I'm pretty sure I understand the basic concept πŸ˜„

Looking at the microsoft.netcore.app.2.2.8 package in a little more detail to understand how the bait and switch works for the managed dlls. From what I can tell it provides a set of compiler reference assemblies that likely target AnyCPU in the ref directory. Are you aware of any packages that use VC++ dlls? The From a convention-based working directory section for ref say the dlls should target AnyCPU. For CefSharp.Core.dll which is a Mixed Mode CLI/C++ dll I cannot compile as AnyCPU, it's required for both compile time and runtime.

You're independently discovering many the problems we worked through with DirectWriteForwarder and System.Printing.dll (C++/CLI assemblies) in WPF πŸ˜‰

So C++/CLI tooling is not very good at generating ref assemblies. In fact there is no support for it 😒

C#'s /refout and /refonly also have weaknesses. The main one is that if an assembly has an InternalsVisibleTo attribute, then /refout or /refonly will generate a ref assembly containing all the internal types/methods. Sometimes this is the desired outcome, and at other times one may not want internal types/methods in the ref assemblies. See https://github.com/dotnet/roslyn/issues/36409 for the tracking bug for this problem.

GenApi is a tool/package that can generate a ref assembly from any [1] CLI assembly. It doesn't quite generate a ref _assembly_ per se - it generates _sources_ for a C# project that, when built, will produce an assembly that can stand-in for a ref-assembly. These sources would have the methods, getters, setters etc. all hollowed out, just like a real ref-assembly.

GenApi is based on Microsoft Common Compiler Infrastructure, which is deprecated in favor of Mono.Cecil. I recently started tinkering with the idea of writing something equivalent (RefGen) with mono.cecil + ICsharpCode.DeCompiler, but it hasn't seen much progress just yet - GenApi is the most mature solution I know today that's ready to be used in a product.

You can get Microsoft.DotNet.GenApi from https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json NuGet feed (browsable feed). Microsoft.DotNet.GenApi.targets should help you figure out how to use the package in your builds, and also these:

C# CommandArgument assemblyArg = app.Argument("assembly", "Path for an specific assembly or a directory to get all assemblies."); assemblyArg.IsRequired(); CommandOption libPath = app.Option("-l|--lib-path", "Delimited (',' or ';') set of paths to use for resolving assembly references", CommandOptionType.SingleValue); CommandOption apiList = app.Option("-a|--api-list", "Specify a api list in the DocId format of which APIs to include.", CommandOptionType.SingleValue); CommandOption outFilePath = app.Option("-o|--out", "Output path. Default is the console. Can specify an existing directory as well and then a file will be created for each assembly with the matching name of the assembly.", CommandOptionType.SingleValue); CommandOption headerFile = app.Option("-h|--header-file", "Specify a file with an alternate header content to prepend to output.", CommandOptionType.SingleValue); CommandOption<WriterType> writerType = app.Option<WriterType>("-w|--writer", "Specify the writer type to use. Legal values: CSDecl, DocIds, TypeForwards, TypeList. Default is CSDecl.", CommandOptionType.SingleValue); CommandOption<SyntaxWriterType> syntaxWriterType = app.Option<SyntaxWriterType>("-s|--syntax", "Specific the syntax writer type. Only used if the writer is CSDecl. Legal values: Text, Html, Xml. Default is Text.", CommandOptionType.SingleValue); CommandOption<DocIdKinds> docIdKinds = app.Option<DocIdKinds>("-d|--doc-id-kinds", "Only include API of the specified kinds. Legal values: A, Assembly, Namespace, N, T, Type, Field, F, P, Property, Method, M, Event, E, All. Default is All.", CommandOptionType.SingleValue); CommandOption exceptionMessage = app.Option("-t|--throw", "Method bodies should throw PlatformNotSupportedException.", CommandOptionType.SingleValue); CommandOption globalPrefix = app.Option("-g|--global", "Include global prefix for compilation.", CommandOptionType.NoValue); CommandOption excludeApiList = app.Option("--exclude-api-list", "Specify a api list in the DocId format of which APIs to exclude.", CommandOptionType.SingleValue); CommandOption excludeAttributesList = app.Option("--exclude-attributes-list", "Specify a list in the DocId format of which attributes should be excluded from being applied on apis.", CommandOptionType.SingleValue); CommandOption followTypeForwards = app.Option("--follow-type-forwards", "[CSDecl] Resolve type forwards and include its members.", CommandOptionType.NoValue); CommandOption apiOnly = app.Option("--api-only", "[CSDecl] Include only API's not CS code that compiles.", CommandOptionType.NoValue); CommandOption all = app.Option("--all", "Include all API's not just public APIs. Default is public only.", CommandOptionType.NoValue); CommandOption memberHeadings = app.Option("--member-headings", "[CSDecl] Include member headings for each type of member.", CommandOptionType.NoValue); CommandOption hightlightBaseMembers = app.Option("--hightlight-base-members", "[CSDecl] Highlight overridden base members.", CommandOptionType.NoValue); CommandOption hightlightInterfaceMembers = app.Option("--hightlight-interface-members", "[CSDecl] Highlight interface implementation members.", CommandOptionType.NoValue); CommandOption alwaysIncludeBase = app.Option("--always-include-base", "[CSDecl] Include base types, interfaces, and attributes, even when those types are filtered.", CommandOptionType.NoValue); CommandOption excludeMembers = app.Option("--exclude-members", "Exclude members when return value or parameter types are excluded.", CommandOptionType.NoValue); CommandOption langVersion = app.Option("--lang-version", "Language Version to target", CommandOptionType.SingleValue);

[1] I've only tried this on a C++/CLI pure and C# based .NET Core assemblies. You'll have to let me know how this goes for a C++/CLI mixed assembly. My expectation is that it ought to work. I know that Mono.Cecil can read (but not write) mixed-mode assemblies. I would think that Microsoft.Cci was capable of reading mixed-mode assemblies as well. edit I checked on a very simple test-assembly with PE32+, CorFlags 0x10 (i.e., mixed mode) that GenApi can indeed produce ref-assembly sources.

The first set of -pre release packages to include a .Net Core 3.1 specific build are now on Nuget.org

The https://github.com/cefsharp/CefSharp.MinimalExample/tree/cefsharp/87 branch of the MinimalExample can be used for testing purposes.

They should work for both .Net Core and .Net 5.0. In a version of two I'll change the main CefSharp.WinForms/Wpf/OffScreen packages to be just meta packages and create a set of Net452 packages, so Nuget will choose the correct package based on framework.

See https://github.com/cefsharp/CefSharp/issues/3284#issuecomment-757130143 for further details.

NOTE A minimum of .Net Core 3.1 is required (for .Net 3.0 which is no longer supported by Microsoft you'll need to use the older packages).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

canton7 picture canton7  Β·  29Comments

8 picture 8  Β·  39Comments

amaitland picture amaitland  Β·  34Comments

amaitland picture amaitland  Β·  29Comments

amaitland picture amaitland  Β·  20Comments