Развертывание приложения WPF с помощью DLL сторонних производителей
Я был крайне расстроен, пытаясь развернуть приложение С#/WPF, которое я создал, которое имеет некоторые ссылки на сторонние DLL. Я создал папку в проекте под названием lib
, где я разместил все эти DLL. В VS2012 я добавил ссылки, перейдя в эту папку и выбрав все библиотеки DLL. Copy Local
для true
. Все хорошо, когда я строю и запускаю, но когда я выбираю публикацию и создаю установщик OneClick, все не так гладко. Во время публикации мастера я установил его для установки с диска и установил, чтобы он никогда не проверял наличие обновлений. Я беру эту папку, размещаю ее на флеш-накопителе, подключаю ее к другому компьютеру, запускаю настройку и выбрасываю исключение. Я считаю, что знаю, что происходит, но я не могу понять, как это сделать, чтобы правильно его развернуть.
Одна из моих DLL - это оболочка С# для DLL, предназначенная для проекта С++. Скажем, Application
требует DLL1
и DLL1
требует DLL2
. DLL2
не может быть добавлено как ссылка в проекте, потому что это не .NET
DLL. DLL1
требует, чтобы DLL2
находился в одной папке, чтобы забрать его. Я использую CefSharp, который обертывает Chromium Embedded Framework.
Я попытался разместить требуемые DLL для CefSharp.dll в каталоге publish/Application Files
, но это не сработало. Я заметил, что все DLL файлы, которые есть у VS2012, имеют расширение .deploy
, я даже пошел и добавил это расширение, чтобы проверить, было ли это сканирование для этого, но оно тоже не работает. Это мой первый опыт разработки и развертывания для приложения Windows, и все обучающие материалы на MSDN или сообщениях в блоге, которые я прочитал, похоже, не охватывают этот случай, и я не вижу других параметров в диспетчере развертывания для обработки этих типы случаев.
Если это помогает, генерируемый код исключения: CLR20r3
Когда я поймаю и покажу Exception, вся информация, которую я предоставляю, в основном говорит CefSharp.dll or one of it dependencies cannot be loaded
. Который я получил раньше, когда DLL2
не был в той же папке, что и DLL1
.
Может ли кто-нибудь предоставить помощь по развертыванию из VS2012 с такой ситуацией?
Спасибо заранее!
Изменить: обновление информации
Я пытался вытолкнуть версию отладки на тестовую машину без установки Visual Studio. При построении для CefSharp
или любого другого С++ Runtime DLL
он будет искать все версии отладки DLL
, которые обычно имеют одно и то же имя, но с буквой "d", добавленной в конец. Как упоминалось ниже, версия Debug С++ Runtime не распространяется. Не то, чтобы вы не могли вручную добавить эти DLLs
в свой проект и установить их как Copy Always
, но такую работу взлома. Я начал новый проект с нуля, добавил все версии версий DLL, построил, и все было в порядке.
Ответы
Ответ 1
Я разорвал свои волосы, пытаясь решить эту проблему сегодня утром, и в итоге нашел решение. Кажется, вы уже знаете, какие DLL и т.д. Вам нужны для работы CEFSharp, но я подумал, что я пропустил бы это, если у кого-то будет такая же проблема. У меня есть приложение С# WPF, и я использую CEFSharp в качестве веб-представления. Я использую CEFSharp v1, потому что мне нужен модуль JavaScript → С#, который они предоставляют, который еще не реализован в v3. Вот грубые шаги, которые я провел при настройке проекта (я использую VS2013, но это, вероятно, будет работать в VS2012).
Установка CefSharp
- Установите CefSharp.Wpf через NuGet (я использую v1.25.7)
- Это должно помещать соответствующие файлы в
$(SolutionDir)packages\CefSharp.Wpf.1.25.7\cef
Настройка сборки
-
Чтобы библиотеки DLL CefSharp могли копироваться в наши папки создания, щелкните правой кнопкой мыши на своем проекте, выберите "Свойства" → "События сборки" и введите в "Командная строка события после сборки" следующее:
xcopy "$ (SolutionDir) пакеты \CefSharp.Wpf.1.25.7\cef *" "$ (TargetDir)" /s/y/i
-
Теперь необходимо скопировать все требуемые DLL из папки cef, а также файл devtools_resources.pak
и папку locales
и его содержимое. Я требую их в своем проекте, поскольку мне нужны инструменты для создания хрома.
- Дважды проверьте ссылки на проект, содержащие
CefSharp
и CefSharp.Wpf
. Это должно было заботиться NuGet.
Уход за файлами Runtime Visual С++ 2012
-
Я не хотел, чтобы пользователь загружал все файлы Runtime Visual С++ 2012 как часть развертывания, поэтому через Visual Studio добавьте папку Lib\Microsoft.VC110.CRT
и добавьте 3 библиотеки DLL (msvcp110.dll
, msvcr110.dll
, vccorlib110.dll
) из следующей папки на вашем компьютере в папку, которую вы только что создали в своем проекте:
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\redist\x86\Microsoft.VC110.CRT
-
Выберите 3 DLL файла в Visual Studio, щелкните правой кнопкой мыши → свойства. Убедитесь, что для параметра "Действие сборки" установлено значение "Нет", а для "Копировать в выходной каталог" выбрано "Не копировать". Теперь вам нужно добавить еще одно событие post-build, чтобы убедиться, что они скопированы правильно (т.е. Скопированы в корневой каталог, чтобы они сидели рядом с DLL CEF и вашим exe проекта) для отладки.
-
Щелкните правой кнопкой мыши на своем проекте, выберите "Свойства" → "События сборки" и введите следующую команду в командной строке "Послестрочная сборка событий" сразу после вашей другой команды xcopy для CEF:
xcopy "$ (ProjectDir) Lib\Microsoft.VC110.CRT *. *" "$ (TargetDir)" /s/y/i
В этот момент все должно строиться. Чтобы опубликовать приложение с помощью ClickOnce, мне нужно, чтобы он удалял все DLL-библиотеки CEF, а также обеспечивал наличие файлов/папок, необходимых для инструментов Chrome. Если вам не нужны инструменты dev или все библиотеки DLL, вы можете настроить их соответствующим образом.
Обеспечение развертывания файлов времени выполнения CEF и С++ с помощью ClickOnce
- Щелкните правой кнопкой мыши свой проект в Visual Studio и выберите "выгрузить проект".
- Щелкните правой кнопкой мыши и выберите, чтобы отредактировать файл csproj.
-
Перед закрывающим тегом </Project>
добавьте этот
<ItemGroup>
<Content Include="$(SolutionDir)packages\CefSharp.Wpf.1.25.7\cef\**\*">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<Visible>false</Visible>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="$(ProjectDir)Lib\Microsoft.VC110.CRT\**\*">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<Visible>false</Visible>
</Content>
</ItemGroup>
-
Это добавит все из папки cef в проект и убедитесь, что двоичные файлы С++ скопированы в корень проекта при развертывании. В моем случае для CEF я использую синтаксис \**\*
в конце Include и %(RecursiveDir)
, чтобы обеспечить копирование всех файлов, а также папку locales
с сохранением содержимого и структуры. Установив <Visible>false</Visible>
, вы не увидите элементы в проводнике решений.
Релакс
Теперь, если вы публикуете свое приложение, оно должно скопировать все необходимые файлы и папки.
Ответ 2
Вы можете попробовать это, которое решило для меня аналогичную проблему:
Добавьте DLL-библиотеки, не являющиеся библиотеками .NET, в решение в виде файлов:
Right click project > Add > Existing Item
Затем установите действие сборки для содержимого и "Скопировать в выходной каталог" на "Копировать всегда".
Таким образом, библиотеки будут включены в выходной каталог.
Ответ 3
Поскольку вы уже пытались вручную добавить подозрительную DLL, и это все еще не работает, следующая вещь, которую я бы сделал, это запустить fusion и посмотреть, на что она действительно жалуется, другими словами, что именно зависимость, которую нельзя загрузить, Вот хороший учебник о том, как выслеживать эти типы ошибок:
Обратно к основам: использование Fusion Log Viewer для отладки ошибок Obscure Loader
Ответ 4
Возможно, вы можете использовать его из https://github.com/Code52/DownmarkerWPF источников?
У них есть хотя бы рабочий установщик ClickOnce для своего приложения, встраивающего CefSharp. Я знаю, потому что так оно и было установлено на моей машине!
обновление только что увидело в комментариях, что это VC Redist, который, как вы говорите, отсутствует, Распространение библиотек времени выполнения Visual С++ (MSVCRT) кажется актуальным.
Кроме того, я, похоже, что-то смутно вспоминаю об этом для "причин VCRedist", вы не должны распространять отладочные версии своего приложения. Вы не можете просто переключиться с отладки на версию Release? С этим я думаю, что вы можете либо связать необходимые файлы VCRedist, как это предлагается в FAQ по CefSharp, либо добавить VCRedist в качестве предварительного условия в вашем установщике. DownmarkerWPF делает это со своей установкой установщика WIX, которую вы можете найти в филиале в своем репозитории GitHub. Что-то подобное AFAIK возможно с установкой VStudio в комплекте, если это то, что вы используете.
Ответ 5
Спасибо Барри ответить на это, это очень помогло мне. Я использую его ответ ниже, но обновляю его для работы с последним CEF, используя Visual Studio 2015.
ПРИМЕЧАНИЕ. Я только создаю/настраиваю платформу x86. Возможно, вам придется изменить или включить x64 в приведенные ниже команды копирования в соответствии с вашими потребностями.
Установка CefSharp
-
Установите CefSharp.Wpf через NuGet (я использую v51.0.0)
Библиотека NuGet после установки
-
Это должно помещать соответствующие файлы в
$(SolutionDir) пакеты \CefSharp.Wpf.51.0.0\CefSharp (CefSharp.Wpf) $(SolutionDir)\CefSharp.Common.51.0.0\CefSharp (CefSharp.Common) $(SolutionDir)\cef.redist.x86.3.2704.1432\CEF (Cef x86 redist) $(SolutionDir)\cef.redist.x64.3.2704.1432\CEF (Cef x64 redist)
Настройка сборки
- Чтобы библиотеки DLL CefSharp копировались в наши папки сборки... Я не думаю, что это необходимо больше с более поздними версиями CefSharp. Я обнаружил, что мне не нужен какой-либо из материалов xcopy из командной строки "Post-build event", чтобы получить "Click-Once", чтобы отправить его. (И да, DevTools тоже работает!)
Уход за файлами Runtime Visual С++ 2012
-
(переключился на видеомагнитофон 2013) Я не хотел, чтобы пользователь загружал все Runtime файлы Visual С++ 2013 как часть развертывания, поэтому через Visual Studio добавьте папку lib\Microsoft.VC120. CRT и добавьте 3 библиотеки DLL (msvcp110.dll, msvcr110.dll, vccorlib110.dll) из следующей папки на вашем компьютере в папку, которую вы только что создали в своем проекте:
C:\Windows\SysWOW64
(Не видел их в C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist)
В этот момент все должно строиться. Чтобы опубликовать приложение с помощью ClickOnce, нам нужно, чтобы он удалял все библиотеки CEF DLL. Вы можете настроить это соответственно...
Обеспечение развертывания файлов времени выполнения CEF и С++ с помощью ClickOnce
- Щелкните правой кнопкой мыши свой проект в Visual Studio и выберите "выгрузить проект".
- Щелкните правой кнопкой мыши и выберите, чтобы отредактировать файл csproj.
-
Перед закрывающим тегом добавьте следующее:
<!-- BEGIN: CUSTOM ITEM GROUP INCLUDES INTO THE PROJECT (SO CLICK-ONCE PUBLISHES THEM) -->
<ItemGroup>
<Content Include="$(SolutionDir)packages\cef.redist.x86.3.2704.1432\CEF\**\*" Exclude="$(SolutionDir)packages\cef.redist.x86.3.2704.1432\CEF\x86\**\*;$(SolutionDir)packages\cef.redist.x86.3.2704.1432\CEF\locales\**\*.pak">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<Visible>false</Visible>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="$(SolutionDir)packages\cef.redist.x86.3.2704.1432\CEF\**\en-GB.*;$(SolutionDir)packages\cef.redist.x86.3.2704.1432\CEF\**\en-US.*">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<Visible>false</Visible>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="$(SolutionDir)packages\cef.redist.x86.3.2704.1432\CEF\x86\**\*">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<Visible>false</Visible>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="$(SolutionDir)packages\CefSharp.Common.51.0.0\CefSharp\x86\**\CefSharp.BrowserSubprocess.*">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<Visible>false</Visible>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="$(ProjectDir)lib\Microsoft.VC120.CRT\**\*">
<Link>%(Filename)%(Extension)</Link>
<Visible>false</Visible>
</Content>
</ItemGroup>
<!-- END: CUSTOM ITEM GROUP INCLUDES INTO THE PROJECT (SO CLICK-ONCE PUBLISHES THEM) -->
-
Это добавит все из папки cef в проект и убедитесь, что двоичные файлы С++ скопированы в корень проекта при развертывании. Установив false, вы не увидите элементы в проводнике решений.
- ПОМНИТЕ: Я только создаю/настраиваю платформу x86. Возможно, вам потребуется изменить или включить x64 в приведенные ниже команды копирования в соответствии с вашими потребностями.
Опубликовать
Теперь, если вы публикуете свое приложение, оно должно скопировать все необходимые файлы и папки.
(ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ) Поддержка более ранних операционных систем ниже
Если вам нужно использовать CefSharp для более старых машин (XP и Vista), просто
установите CefSharp.Wpf через NuGet, используя более старую версию v47.0.0, и измените свой таргетинг .NET на профиль клиента .NET 4.0.
Chromium завершила поддержку XP и Vista в апреле 2016 года, CefSharp версии 47 (или там abouts) все еще поддерживала его.
Еще одно примечание к проблеме и исправление для XP:
Существует проблема Chromium для развертывания XP. Ниже приведена статья, описывающая исправление, а затем шаги по развертыванию исправления для JBCB.
Здесь ссылка на статью:
https://bitbucket.org/chromiumembedded/cef/issues/1787
... в нем вы увидите ссылку для загрузки "dbghelp.dll". Загрузите и извлеките.
ВЫ МОЖЕТЕ ПРИНИМАТЬ ПОСТ-УСТАНОВКУ ПОДХОДА, КАК НИЖЕ ИЛИ ВЫБИРАТЬ, ЧТОБЫ ВКЛЮЧАТЬ ДИСКУ С ДРУГИМИ ОПУБЛИКОВАННЫМИ ФАЙЛАМИ. Я ВЫБИРАЮ, ЧТОБЫ НЕ РАЗЛИЧИТЬ ДОПОЛНИТЕЛЬНУЮ DLL И ТОЛЬКО РАЗМЕЩЕНИЕ НА СТАНКАХ XP (МЫ ТОЛЬКО НЕСКОЛЬКО) ПРОЧИТАНО.
Выполните следующие действия, чтобы исправить развертывание на компьютере XP:
- Установите браузер CefSharp на компьютере XP (через Click-Once)
- Скопируйте файл "dbghelp.dll"
- Вставьте его в локальный каталог установки на компьютере XP (в соответствии с инструкциями в предыдущей ссылке: вдоль файла "libcef.dll" ).
ПРИМЕЧАНИЕ. Для установок с однократной установкой будет находиться в подпапке в этом месте:
C:\Documents and Settings\<UserName>\Local Settings\Apps\2.0\<auto-gen ostificated ID>
Ответ 6
Внимательно прочитайте официальный список зависимостей CefSharp - их много! Вам нужно как-то поместить их в папку "ClickOnce bin".
Вот как я это решил:
- Перед развертыванием установите последнюю версию Visual C++ Redistributable. на каждом ПК, на котором вы развертываете (используя групповую политику или просто вручную).
- Начните с пустого тестового проекта.
- Добавьте ссылки на
CefSharp
в CefSharp
, CefSharp.Core
и т.д. - Добавьте каждую зависимость в одну папку в каталоге проекта, чтобы сохранить их организованность (
Files\CefSharp\
). - Убедитесь, что все файлы настроены с помощью
Build Action: Content
и Copy to Output Dir: Copy always
. - Создайте функцию
Initalise_CefSharpFiles()
для копирования файлов/папок в корневую папку bin (где их ищет CefSharp). Например, скопируйте из: Bin\Files\CefSharp\*
в: Bin\*
. - И, наконец, во время выполнения, вызывайте
Initalise_CefSharpFiles()
один раз после загрузки приложения и перед инициализацией настроек CefSharp.