Feature Request - Add AnyCPU Support
amaitland opened this issue · 7 comments
UPDATE: Starting with release v87.1.132 the Nuget
packages have been restructured to greatly simplify using AnyCPU
. Issue #3319 has some specific information.
Those upgrading from versions prior to v87.1.132
shouldn't need to make any code changes.
Option 1
When targeting AnyCPU
when your project has Prefer 32bit
set to true
then the resulting exe
will be 32bit
, the Nuget
package checks for this and copies only the x86
files. This is the default for a number of Visual Studio
project templates. No further changes are required.
To manually set Prefer 32bit
open your project properties and under the build tab check prefer 32bit.
Option 2
Add a dependency resolver, this is more complicated and needs to be hooked up before any calls to classes in the CefSharp.*
namespaces. Here is one method of doing this. It's important that LoadApp
is not in-lined, so the calls to CefSharp
are delayed long enough to hookup the Assembly Resolver
- Add
<CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>
to the first<PropertyGroup>
in your project (e.g..csproj
file). - Implement the code below (modifying any setting that you require).
[STAThread]
public static void Main()
{
CefRuntime.SubscribeAnyCpuAssemblyResolver();
LoadApp();
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void LoadApp()
{
var settings = new CefSettings();
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
var browser = new BrowserForm();
Application.Run(browser);
}
The MinimalExample now has AnyCPU
as a target to demo the CefSharpAnyCpuSupport
option.
Example WPF
solution.
You must add <CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>
to the first <PropertyGroup>
in your project (e.g. .csproj
file).
public partial class App : Application
{
public App()
{
CefRuntime.SubscribeAnyCpuAssemblyResolver();
//Any CefSharp references have to be in another method with NonInlining
// attribute so the assembly rolver has time to do it's thing.
InitializeCefSharp();
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void InitializeCefSharp()
{
var settings = new CefSettings();
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
}
}
The MinimalExample now has AnyCPU
as a target to demo the CefSharpAnyCpuSupport
option.
I've updated the original issue at the top here to include details about adding a CefSharpAnyCpuSupport
property to your project file. This is only required for AnyCPU
support and will through an error as part of your build process until it's been added. The error directs people to this issue.
See https://github.com/cefsharp/CefSharp.MinimalExample/tree/demo/anycpu for the original demo project that I used for testing. I currently have no plans on maintaining this branch, it's purely provided as a working example. See the commit log to see exactly what changes were made to get things working.
There was a mismatch between the processor architecture of the project being built "MSIL" and the processor architecture of the reference "CefSharp.Core", "x86".
The above warning in your Error List
is safe to ignore. If you wish to disable this warning see http://thebuildingcoder.typepad.com/blog/2013/06/processor-architecture-mismatch-warning.html
You must add <CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>
to the first <PropertyGroup>
in your project (e.g. .csproj
file).
Option 3
I've not tested this option in any great detail, so use at you own risk. It requires the user to have Write Permission to the applications executing folder. No special resolves or methods of loading the dlls
is required. The relevant files are copied to the executing folder and unused resources deleted
- Copies
CefSharp
resources from thex86
orx64
folder depending on application bitness - Removes
x86
andx64
folders
NOTE
- If you upgrade/downgrade you will need to manually remove the libs from the executing folder (A simple
Git Cleanup
would suffice) - This option would be best used when deploying using an installer.
//Example WinForms Code (WPF would be very similar)
[STAThread]
public static void Main()
{
var executingFolder = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
//If libcef.dll doesn't exist in our executing folder then we'll copy the files
//For this method the user must have write permissions to the executing folder.
if (!File.Exists(Path.Combine(executingFolder, "libcef.dll")))
{
var libPath = Path.Combine(executingFolder, Environment.Is64BitProcess ? "x64" : "x86");
CopyFilesRecursively(new DirectoryInfo(libPath), new DirectoryInfo(executingFolder));
Directory.Delete("x86", recursive: true);
Directory.Delete("x64", recursive: true);
}
LoadApp();
}
//https://stackoverflow.com/a/58779/4583726
private 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())
{
file.CopyTo(Path.Combine(target.FullName, file.Name));
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void LoadApp()
{
//Perform dependency check to make sure all relevant resources are in our output directory.
var settings = new CefSettings();
Cef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: null);
var browser = new BrowserForm();
Application.Run(browser);
}
Examples of all three options can be found at https://github.com/cefsharp/CefSharp.MinimalExample/branches/all?utf8=%E2%9C%93&query=anycpu
Starting with release v87.1.132 there is another option for AnyCPU
support.
Option 4
- Unlike the other options don't set
CefSharpAnyCpuSupport
in your project file. - Make sure your application has an app.config
- Ensure your copy of Visual Studio has the
Web Developer Tools
installed OR - Install the MSBuild.Microsoft.VisualStudio.Web.targets
Nuget
package (whilstMicrosoft
is included in the package name, this package is released by a 3rd party).
The resulting app.config
file (e.g. CefSharp.MinimalExample.OffScreen.exe.config
) will look something like below.
The Microsoft.Web.Publishing.Tasks.dll
contains a transform which modifies your app.config as part of the build process adding entries that resolve the CefSharp.Core.Runtime.dll
at runtime. Note this doesn't modify your app.config
in your project root, only the generated version in your bin folder.
THIS IS AN EXAMPLE OF THE GENERATED APP.CONFIG, NO CODE CHANGES ARE REQUIRED
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup>
<!--<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="MyCefSharpTargetDir"/>
</assemblyBinding>
</runtime>-->
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="CefSharp.Core.Runtime" processorArchitecture="x86" publicKeyToken="40c4b6fc221f4138" culture="neutral"/>
<codeBase version="89.0.170.0" href="x86/CefSharp.Core.Runtime.dll"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="CefSharp.Core.Runtime" processorArchitecture="amd64" publicKeyToken="40c4b6fc221f4138" culture="neutral"/>
<codeBase version="89.0.170.0" href="x64/CefSharp.Core.Runtime.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>