Skip to content
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 AnyCPU Support #1714

Closed
amaitland opened this issue Jun 17, 2016 · 7 comments
Closed

Feature Request - Add AnyCPU Support #1714

amaitland opened this issue Jun 17, 2016 · 7 comments

Comments

@amaitland
Copy link
Member

amaitland commented Jun 17, 2016

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.

visualstudioprefer32bit

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.

@amaitland
Copy link
Member Author

amaitland commented Jun 20, 2016

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.

@amaitland
Copy link
Member Author

amaitland commented Jun 20, 2016

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.

@amaitland

This comment has been minimized.

@cefsharp cefsharp locked and limited conversation to collaborators Sep 8, 2016
@amaitland
Copy link
Member Author

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

@amaitland
Copy link
Member Author

amaitland commented Jul 13, 2018

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 the x86 or x64 folder depending on application bitness
  • Removes x86 and x64 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);
}

@amaitland
Copy link
Member Author

@amaitland
Copy link
Member Author

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 (whilst Microsoft 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>

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant