Я пытаюсь заставить CefSharp.Wpf
работать в надстройке VSTO Office, в которой по умолчанию включена теневая копия, и нет способа отключить ее, которую я смог найти.Во время выполнения сборки копируются во временную папку (AppData\local\assembly
...... и т. Д.);проблема заключается в том, что не все необходимые файлы копируются в расположение сборки для CefSharp.Фактически, при первом запуске или при создании нового местоположения теневой копии для AppDomain выдается исключение, потому что cefsharp.core.dll
даже не найден;однако после этого создается место сборки cef, но с ТОЛЬКО cefsharp.core.dll
, поэтому при любых последовательных выполнениях будет найдено cefsharp.core.dll
, но ни одна из его зависимостей не будет найдена, поскольку приложение использует это местоположение теневой копии в качестве базы сборки.
Я попытался несколько способов явно указать расположение библиотеки, но без особого успеха:
namespace OutlookTools
{
public partial class AdvPrint : Window
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetDllDirectory(string lpPathName);
// This resolves to the original build folder
private static string cefFolder = new Uri(Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase)).LocalPath;
public AdvPrint()
{
SetDllDirectory(cefFolder);
InitializeCefSharp(); // First run exception is thrown here, before function is even executed (No cefsharp.core.dll)
InitializeComponent();
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void InitializeCefSharp()
{
CefSharpSettings.SubprocessExitIfParentProcessClosed = true;
var settings = new CefSettings();
settings.BrowserSubprocessPath = Path.Combine(cefFolder, "CefSharp.BrowserSubprocess.exe");
settings.LocalesDirPath = Path.Combine(cefFolder, "locales");
settings.ResourcesDirPath = cefFolder;
// Make sure you set performDependencyCheck false
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null); // Final exception is thrown here
}
}
}
namespace OutlookTools
{
public partial class AdvPrint : Window
{
// This resolves to the original build folder
private static string cefFolder = new Uri(Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase)).LocalPath;
public AdvPrint(Outlook.MailItem mailItem)
{
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
InitializeCefSharp(); // First run exception is thrown here, before function is even executed (No cefsharp.core.dll)
InitializeComponent();
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void InitializeCefSharp()
{
CefSharpSettings.SubprocessExitIfParentProcessClosed = true;
var settings = new CefSettings();
settings.BrowserSubprocessPath = Path.Combine(cefFolder, "CefSharp.BrowserSubprocess.exe");
settings.LocalesDirPath = Path.Combine(cefFolder, "locales");
settings.ResourcesDirPath = cefFolder;
// Make sure you set performDependencyCheck false
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null); // Final exception is thrown here
}
/// <summary>
/// Will attempt to load missing assemblies from build folder
/// </summary>
private static Assembly ResolveAssembly(object sender, ResolveEventArgs args)
{
if (args.Name.StartsWith("CefSharp"))
{
string assemblyName = args.Name.Split(new[] { ',' }, 2)[0] + ".dll";
string subfolderPath = Path.Combine(cefFolder, assemblyName);
return File.Exists(subfolderPath) ? Assembly.LoadFile(subfolderPath) : null;
}
return null;
}
}
}
public partial class AdvPrint : Window
{
// This resolves to the original build folder
private static string cefFolder = new Uri(Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase)).LocalPath;
public AdvPrint(Outlook.MailItem mailItem)
{
var libraryLoader = new CefLibraryHandle(Path.Combine(cefFolder, "libcef.dll"));
//Calls to CEF cannot be made directly in this method, doing so would
//attempt to load `CefSharp.Core` which requires `libcef.dll` which
//we are now dynamically loading from our own folder.
InitializeCefSharp(); // First run exception is thrown here, before function is even executed (No cefsharp.core.dll)
libraryLoader.Dispose();
InitializeComponent();
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void InitializeCefSharp()
{
CefSharpSettings.SubprocessExitIfParentProcessClosed = true;
var settings = new CefSettings();
settings.BrowserSubprocessPath = Path.Combine(cefFolder, "CefSharp.BrowserSubprocess.exe");
settings.LocalesDirPath = Path.Combine(cefFolder, "locales");
settings.ResourcesDirPath = cefFolder;
// Make sure you set performDependencyCheck false
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null); // Final exception is thrown here
}
}
}
Я установил BrowserSubprocessPath
, LocalesDirPath
, ResourcesDirPath
, и это, похоже, решает большинство ошибок времени выполнения, но теперь я столкнулся с этим неопределенным исключением:
System.IO.FileNotFoundException: «Не удалось загрузить файл или сборку»СefSharp, версия = 73.1.130.0, культура = нейтральная, PublicKeyToken = 40c4b6fc221f4138 'или одна из ее зависимостей.Система не может найти указанный файл. '
Я точно знаю, что все зависимости находятся в папке сборки, и я могу без проблем запускать проекты CefSharp.MinimalExample
.Кажется, все указывает на то, что используется сборка теневого копирования (если я не перезаписываю BrowserSubprocessPath
в настройках, я вижу, что он изначально указывает на C:....\AppData\local\assembly\some\long\temp\path
).