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

Configure directory where msbuild will copy CefSharp files #1753

Merged
merged 2 commits into from
Aug 19, 2016

Conversation

intrueder
Copy link
Contributor

During build process msbuild copies CefSharp files to $(TargetDir)
Sometimes it is not suitable, and instead of override $(TargetDir) globally another property has been introduced. It's name is $(CefSharpTargetDir)
It is possible to override this property in csproj file

<PropertyGroup>
  <CefSharpTargetDir>C:\MyProjectOutDir\Cef</CefSharpTargetDir>
</PropertyGroup>

If this property should depend on $(TargetDir) don't forget to override property after importing Microsoft.CSharp.targets ($(TargetDir) is defined there)

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
  <CefSharpTargetDir>$(TargetDir)\Cef</CefSharpTargetDir>
</PropertyGroup>

Also, $(TargetDir) is used by default if $(CefSharpTargetDir) was not specified in csproj file

@amaitland
Copy link
Member

@intrueder Thanks for the contribution! I'm currently working on other things at the moment, will probably take at least a few weeks before this is reviewed.

@amaitland
Copy link
Member

@intrueder I've had a quick look over your PR (still needs a full review). How do you plan on documenting this new feature? Simply copying to another folder isn't enough to resolve the unmanaged dependencies as I'm sure your aware.

@amaitland amaitland added this to the 53.0.0 milestone Aug 7, 2016
@intrueder
Copy link
Contributor Author

This feature should be used in conjunction with AnyCPU support ( #1714 ) code sample.
Actually AnyCPU support can be documented and CefSharpTargetDir property can be as a remark.

@amaitland
Copy link
Member

This feature should be used in conjunction with AnyCPU support ( #1714 ) code sample.

It's not limited to AnyCPU support though.......

Actually AnyCPU support can be documented

I have no plans to document AnyCPU support past what is already included in #1714

CefSharpTargetDir property can be as a remark.

Please write some documentation and I'll consider it for inclusion in #1714

@intrueder
Copy link
Contributor Author

intrueder commented Aug 8, 2016

Complete code sample. (I've modified original sample a bit, because AppDomain.CurrentDomain.SetupInformation.ApplicationBase does not work for me)

.csproj

<PropertyGroup>
  <CefSharpTargetDir>C:\MyProjectOutDir\Cef</CefSharpTargetDir>
</PropertyGroup>

.cs

public partial class App : Application
{
    public App()
    {
        //Add Custom assembly resolver
        AppDomain.CurrentDomain.AssemblyResolve += Resolver;

        // 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();
        settings.EnableInternalPdfViewerOffScreen();

        // Set BrowserSubProcessPath based on app bitness at runtime
        settings.BrowserSubprocessPath = GetArchitectureSpecificPath("CefSharp.BrowserSubprocess.exe");

        // Make sure you set performDependencyCheck false
        Cef.Initialize(settings, shutdownOnProcessExit: false, performDependencyCheck: false);
    }

    // Will attempt to load missing assembly from either x86 or x64 subdir
    // Required by CefSharp to load the unmanaged dependencies when running using AnyCPU
    private static Assembly Resolver(object sender, ResolveEventArgs args)
    {
        if (args.Name.StartsWith("CefSharp"))
        {
            string assemblyName = args.Name.Split(new[] { ',' }, 2)[0] + ".dll";
            string archSpecificPath = GetArchitectureSpecificPath(assemblyName);

            if (File.Exists(archSpecificPath))
            {
                return Assembly.LoadFile(archSpecificPath);
            }
        }

        return null;
    }

    private static string GetAssemblyDirectory()
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        string path = Uri.UnescapeDataString(uri.Path);
        return Path.GetDirectoryName(path);
    }

    private static string GetArchitectureSpecificPath(string fileName)
    {
        // subfolder is the same as $(CefSharpTargetDir) points to
        string cefSubfolder = "Cef";
        return Path.Combine(GetAssemblyDirectory(), cefSubfolder, Environment.Is64BitProcess ? "x64" : "x86", fileName);
    }
}

@amaitland
Copy link
Member

AppDomain.CurrentDomain.SetupInformation.ApplicationBase does not work for me)

What problems are you seeing using ApplicationBase?

@amaitland
Copy link
Member

This will likely be included as part of 53.0.0, should be merged before the first -pre release is built.

@intrueder
Copy link
Contributor Author

What problems are you seeing using ApplicationBase?

It is probably a special case..
That's what I have:

  1. Unmanaged MyApplication.exe located in C:\ProgramFiles\MyApp
  2. Additional libs/plugins in subfolder C:\ProgramFiles\MyApp\Libs. They are loaded via LoadLibrary
  3. Managed library ChromiumHost.dll located in C:\ProgramFiles\MyApp\Libs. It is the only who uses CefSharp.

and now, to avoid putting CefSharp files directly into C:\ProgramFiles\MyApp\Libs, I want to put them into subfolder.

ApplicationBase points to MyApplication.exe path, i.e. C:\ProgramFiles\MyApp.
I need a folder, that will be relative to assembly where CefSharp is used (ChromiumHost.dll -> C:\ProgramFiles\MyApp\Libs), Assembly.GetExecutingAssembly().CodeBase helps with this.

@amaitland amaitland merged commit 2f69165 into cefsharp:master Aug 19, 2016
@intrueder intrueder deleted the targets_fixes branch September 16, 2016 09:21
@syqjyh
Copy link

syqjyh commented Apr 17, 2018

i use CefSharp to create a wpf dialog to open a url ,and this dialog is embedded in excel. our product need call excelAddIn.dll and work on anyCPU platform . so i download the cef demo project from https://github.com/cefsharp/CefSharp.MinimalExample/tree/demo/anycpu .Now i encountered a problem that i just replace the url in MainWindow.xaml with my URL, and it works well, but after i finished all coding and dependency related according to the demo project , our project still can't work and throw a exception (An unhandled exception of type 'System.IO.FileNotFoundException' occurred in Unknown Module.
Additional information: Could not load file or assembly 'CefSharp, Version=63.0.0.0, Culture=neutral, PublicKeyToken=40c4b6fc221f4138' or one of its dependencies. The system cannot find the file specified.) but i have added the CefSharp and related dependency to the related directory. i don't know why. can someone help me. thanks. and the MIMICAddIn.txt is our product entrance csproj file and i need create the wpf dialog in the csproj Morningstar.Commodity.xL.Market.Data.
MIMICAddIn.txt
Morningstar.Commodity.xL.Market.Data.txt

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

Successfully merging this pull request may close these issues.

3 participants