-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request - Add .Net Core 3.1 Support #2796
Comments
With #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. |
This comment has been minimized.
This comment has been minimized.
Hi, I was able to successfully use I also tested that the 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 Another thing to consider is the browser subprocess ( 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). Thank you! |
You can try setting |
Hi @campersau,
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 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. 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 [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, This means you won't have to bother with building and copying the correct subprocess executable before running your main application. What do you think? |
Future reference for myself https://github.com/dotnet/samples/tree/master/core/hosting/HostWithHostFxr |
Regarding the subprocess handling for .NET Core, my idea was the following:
<PropertyGroup>
<TargetFrameworks>net452;netcoreapp3.0</TargetFrameworks>
...
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)'!='netcoreapp3.0'">
<OutputType>WinExe</OutputType>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
#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
That way, a user could modify the [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 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 This seems to occur because the subprocess executable ( 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 👍
For simplicity we'll just rewrite the
Will keep the changes to
My initial plan is to create a new
Some sort of runtime check would be idea, will have to investigate alternatives as
What does declare dependencies to
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 |
Hi @amaitland, thanks for your reply!
Agreed, that way no change to the project file for
Sorry, actually here I only meant that the For example, right now if I create a new .NET Core 3.0 project and add <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
This seems to have the effect that the dependency is not specified in the To summarize, CefSharp.WinForms already works today on a .NET Core 3.0 WinForms project (created with <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 <When Condition="'$(Platform)' == 'x64'"> Maybe this needs to be changed to use Thanks! |
It was my understanding (and that's a limited understanding at this point) that transitive dependencies meant that only top level references were included?
The files should be copied via the
The current packages require that you set the solution target, this is a current limitation.
Last I checked this isn't possible, If you have the time to contribute a |
Hi @amaitland,
Sorry, I'm not sure if I fully understood what you say here. With 'transitive reference', I meant that if project I don't have detailed knowledge about how NuGet packages work, but I think that when the <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 Currently, when using a .NET Core 3.0 project I also have to add
Actually, the files are copied correctly into the output directory, but because the
OK, thanks. It might be worth to check if this is also the case with SDK-style (.NET Core) projects.
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:
Looking around i found [https://github.com/dotnet/coreclr/issues/24008]https://github.com/dotnet/coreclr/issues/24008 where @vatsan-madhavan points out that:
Its not just CopyMemory, as you can see in [https://github.com/dotnet/pinvoke/issues/431]dotnet/pinvoke#431, other memory related functions are also affected - MoveMemory, CopyMemory, FillMemory and ZeroMemory at least |
Contributes to cefsharp#2796
@537mfb Thanks! I created #2885 to fix the I also updated cefsharp/CefSharp.MinimalExample#57 to include a minimal WPF example using .NET Core 3.0 which should work once the |
@537mfb Thanks for the links 👍 I am planning on releasing |
@kpreisser Thanks for the quick |
* Fix the entrypoint declaration for CopyMemory. Contributes to #2796 * Follow-Up: Switch to RtlCopyMemory which is faster, but requires that the buffers do not overlap.
Started the refactor of the
@kpreisser Have you tested that adding |
This ensures the transitive dependencies (CefSharp.Common) are correctly resolved in .NET Core 3.0 projects. Contributes to cefsharp#2796
Yes, I tested it with the minimal .NET Core examples and the transitive references were successfully resolved. I created PR #2894 to add these. |
@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).
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.
This can be worked around in an inline MSBuild task. Take a look at |
@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.
For the current set of
The current I was hoping to create a new set of The folder structure used by the
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 There are some other issues that I've run into along the way:
I haven't yet no, I'll check it out thanks.
The situation as it stands
There are quite a few other build environment complexities that I won't get into now.
I downloaded I got stuck on the earlier issues and reverted to a more traditional
Thanks for the reference, hopefully others will find this helpful 👍 |
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 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...
Have you tried changing 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.
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:
"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'll rework the demo to illustrate the problems I'm having using Hopefully have a demo of the problem shortly.
I haven't yet no, I'll give that a try. I did see the
Thanks again for taking the time to write such a detailed post, I'm pretty sure I understand the basic concept 😄 Looking at the |
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 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 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. |
…serSubprocess.Core, CefSharp.WinForms, CefSharp.Wpf, CefSharp.OffScreen. Contributes to cefsharp#2796
…not used in the corresponding .NET Framework projects. Add CefSharp.Example.netcore and CefSharp.WinForms.Example.netcore. Output documentation files. Use "bin.netcore" and "obj.netcore" as [intermediate] output path for the .NET Core projects, to allow side-by-side builds with the .NET Framework projects. Remove WindowsTargetPlatformVersion property as that is declared in CefSharp.props. Switch project CefSharp.netcore.csproj to AnyCPU as it doesn't require different builds for each platform. - Remove dependencies to "opengl32.lib" and "glu32.lib" which aren't available for ARM64 and don't seem to be needed. - Clean up project files. Add .NET Core 3.1 projects for CefSharp, CefSharp.Core, CefSharp.BrowserSubprocess.Core, CefSharp.WinForms, CefSharp.Wpf, CefSharp.OffScreen. Contributes to cefsharp#2796
…not used in the corresponding .NET Framework projects. Add CefSharp.Example.netcore and CefSharp.WinForms.Example.netcore. Output documentation files. Use "bin.netcore" and "obj.netcore" as [intermediate] output path for the .NET Core projects, to allow side-by-side builds with the .NET Framework projects. Remove WindowsTargetPlatformVersion property as that is declared in CefSharp.props. Switch project CefSharp.netcore.csproj to AnyCPU as it doesn't require different builds for each platform. - Remove dependencies to "opengl32.lib" and "glu32.lib" which aren't available for ARM64 and don't seem to be needed. - Clean up project files. Add .NET Core 3.1 projects for CefSharp, CefSharp.Core, CefSharp.BrowserSubprocess.Core, CefSharp.WinForms, CefSharp.Wpf, CefSharp.OffScreen. Contributes to cefsharp#2796
…not used in the corresponding .NET Framework projects. Add CefSharp.Example.netcore and CefSharp.WinForms.Example.netcore. Output documentation files. Use "bin.netcore" and "obj.netcore" as [intermediate] output path for the .NET Core projects, to allow side-by-side builds with the .NET Framework projects. Remove WindowsTargetPlatformVersion property as that is declared in CefSharp.props. Switch project CefSharp.netcore.csproj to AnyCPU as it doesn't require different builds for each platform. - Remove dependencies to "opengl32.lib" and "glu32.lib" which aren't available for ARM64 and don't seem to be needed. - Clean up project files. Add .NET Core 3.1 projects for CefSharp, CefSharp.Core, CefSharp.BrowserSubprocess.Core, CefSharp.WinForms, CefSharp.Wpf, CefSharp.OffScreen. Contributes to cefsharp#2796
* Add .NET Core 3.1 projects for CefSharp, CefSharp.Core, CefSharp.BrowserSubprocess.Core, CefSharp.WinForms, CefSharp.Wpf, CefSharp.OffScreen. Contributes to #2796 * - Remove dependencies to "opengl32.lib" and "glu32.lib" which aren't available for ARM64 and don't seem to be needed. - Clean up project files. * Switch project CefSharp.netcore.csproj to AnyCPU as it doesn't require different builds for each platform. * Remove WindowsTargetPlatformVersion property as that is declared in CefSharp.props. * Use "bin.netcore" and "obj.netcore" as [intermediate] output path for the .NET Core projects, to allow side-by-side builds with the .NET Framework projects. * Output documentation files. * Add CefSharp.Example.netcore and CefSharp.WinForms.Example.netcore. * Follow-up: Remove properties from the example projects that are also not used in the corresponding .NET Framework projects.
This comment has been minimized.
This comment has been minimized.
The first official release to support
They should work for both See #3284 (comment) for further details. |
@amaitland won't the multiple targeting just work ? why create a metapackage instead of direct use multiple-targeting ? |
@John0King What do you mean by this exactly? The new net core packages only contain a set of dlls compiled with .Net Core 3.1, whilst the original Nuget package contain dlls compiled using .Net 4.5.2. |
@amaitland I'm not familiar with c++/cil , but in just c#, we can just multiple-targeting the it's on nuget package contains multiple set of dlls for different TFM , and will choose the correct dll base on the TFM of user's class library |
@John0King See #2796 (comment) (which links to https://docs.microsoft.com/en-us/dotnet/core/porting/cpp-cli#ccli-net-core-limitations). There is no multi targeting for C++/CLI or support for the newer SDK project format.
Having a single package that contains all versions is a nice idea in theory, the reality is that C++/CLI project support currently makes this very complicated. In theory the meta package will have the same result from an end user point of view (or at least that's my current understanding). |
After reading all the previous comments, I would like to summarize the facts regarding AnyCpu support with .NET Core 3.1. Is there any example showing the steps needed when someone would like to upgrade from .NET 4.8 with AnyCPU support to the .NET Core 3.1 version? |
There is kind of AnyCPU support in .NET Core, when you don't specify a
However, generally there is no "real" AnyCPU suppot in .NET Core/.NET 5 for application projects, because when building the application, the apphost ( This is different from .NET Framework |
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.
The text was updated successfully, but these errors were encountered: