Исключение FileNotFound, когда включена теневая копия сборки - PullRequest
0 голосов
/ 30 июня 2019

Я пытаюсь заставить CefSharp.Wpf работать в надстройке VSTO Office, в которой по умолчанию включена теневая копия, и нет способа отключить ее, которую я смог найти.Во время выполнения сборки копируются во временную папку (AppData\local\assembly ...... и т. Д.);проблема заключается в том, что не все необходимые файлы копируются в расположение сборки для CefSharp.Фактически, при первом запуске или при создании нового местоположения теневой копии для AppDomain выдается исключение, потому что cefsharp.core.dll даже не найден;однако после этого создается место сборки cef, но с ТОЛЬКО cefsharp.core.dll, поэтому при любых последовательных выполнениях будет найдено cefsharp.core.dll, но ни одна из его зависимостей не будет найдена, поскольку приложение использует это местоположение теневой копии в качестве базы сборки.

Я попытался несколько способов явно указать расположение библиотеки, но без особого успеха:

  • kernel32 SetDllDirectory
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).

...