使用第三方DLL部署WPF应用程序

时间:2014-04-03 15:03:18

标签: visual-studio-2012 dll windows-installer clickonce cefsharp

我一直非常沮丧地尝试部署我创建的C#/ WPF应用程序,该应用程序有一些对第三方DLL的引用。我在项目中创建了一个名为lib的文件夹,在那里我放置了所有这些DLL。在VS2012中,我通过浏览到该文件夹​​并选择所有DLL来添加引用。对于所有人,Copy Local设置为true。我构建和运行时一切都很好,但是当我选择发布并创建OneClick安装程序时,事情就不那么顺利了。在发布向导期间,我将其设置为从磁盘安装,并将其设置为从不检查更新。我拿这个文件夹,把它放在闪存驱动器上,插入另一台PC,运行安装程序,然后抛出异常。我相信我知道发生了什么,但我无法弄清楚如何打包它以便正确部署它。

我的一个DLL是为C ++项目设计的DLL的C#包装器。我们会说,Application需要DLL1DLL1需要DLL2DLL2无法作为项目中的引用添加,因为它不是.NET DLL。 DLL1要求DLL2位于同一文件夹中才能获取它。我正在使用CefSharp封装Chromium Embedded Framework

我已尝试将所需的CefSharp.dll DLL放在publish/Application Files目录中,但它不起作用。我注意到VS2012上的所有DLL都有一个.deploy扩展名,我甚至去添加扩展名以查看它是否正在扫描以获取它,但它也没有用。这是我第一次为Windows应用程序进行开发和部署,我读过的所有关于MSDN或博客文章的教程似乎都没有涵盖这种情况,我在Deployment Manager中看不到任何其他选项来处理这些案件类型。

如果有帮助,抛出的异常代码为:CLR20r3

当我抓住并显示Exception时,我提供的所有信息基本上都是CefSharp.dll or one of it's dependencies cannot be loaded。我DLL2DLL1不在同一文件夹中时所得到的。

任何人都可以提供有关如何从VS2012部署此类情况的帮助吗?

提前致谢!

修改:信息更新

我试图将调试版本推送到没有安装Visual Studio的测试机器。在构建CefSharp或任何其他C ++运行时DLL时,它将查找DLL的所有调试版本,这些版本通常具有相同的名称,但添加了字母“d”到最后。如下所述,C ++ Runtime的Debug版本不可再发行。并不是说您无法手动将DLLs添加到项目中并将其设置为Copy Always,但这是一种黑客工作。我从头开始了一个新项目,添加了DLL的所有Release版本,并且一切都很好。

6 个答案:

答案 0 :(得分:21)

我今天早上一直在试图解决这个问题,并最终找到了解决办法。看来你已经知道CEFSharp需要哪些DLL等工作但我想我会遇到这个以防其他人遇到同样的问题。我有一个C#WPF应用程序,我使用CEFSharp作为Web视图。我使用CEFSharp v1因为我需要JavaScript - >它们提供的C#桥在v3中尚未实现。以下是我在设置项目时所经历的粗略步骤(我使用的是VS2013,但这可能适用于VS2012)。

安装CefSharp

  • 通过NuGet安装CefSharp.Wpf(我使用v1.25.7)
  • 这应该将相关文件放在$(SolutionDir)packages\CefSharp.Wpf.1.25.7\cef

配置构建

  • 要将CefSharp DLL复制到我们的构建文件夹,请右键单击您的项目,选择Properties - >构建事件并在"构建后事件命令行":

    中输入以下内容
      

    xcopy" $(SolutionDir)packages \ CefSharp.Wpf.1.25.7 \ cef *" " $(TARGETDIR)" / s / y / i

  • 现在应该从cef文件夹以及devtools_resources.pak文件和locales文件夹及其内容中复制所有必需的DLL。我需要他们在我的项目中,因为我需要chrome dev工具。

  • 仔细检查您的项目引用是否包含CefSharpCefSharp.Wpf。应该由NuGet负责。

处理Visual C ++ 2012运行时文件

  • 我不希望用户必须下载整个Visual C ++ 2012运行时文件作为部署的一部分,因此通过Visual Studio添加文件夹Lib\Microsoft.VC110.CRT并添加3个DLL( msvcp110.dllmsvcr110.dllvccorlib110.dll)从您计算机上的以下文件夹到您刚刚在项目中创建的文件夹:

    C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\redist\x86\Microsoft.VC110.CRT

  • 在Visual Studio中选择3个DLL文件,右键单击 - >属性。确保将Build Action设置为" None"和复制到输出目录设置为"不复制"。现在你需要添加另一个post-build事件以确保它们被正确复制(即复制到root,以便它们与CEF dll和你的项目exe一起放置)进行调试。

  • 右键单击您的项目,选择属性 - >构建事件并在"构建后事件命令行中输入以下内容"紧跟CEF的其他xcopy命令之后:

      

    xcopy" $(ProjectDir)Lib \ Microsoft.VC110.CRT *。*" " $(TARGETDIR)" / s / y / i

此时,一切都应该建立起来。要使用ClickOnce发布应用程序,我需要它来推出所有CEF DLL以及确保chrome dev工具所需的文件/文件夹。如果您不需要开发工具或所有DLL,那么您可以相应调整它。

确保使用ClickOnce

部署CEF和C ++运行时文件
  • 在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文件夹中的所有内容添加到项目中,并确保在部署时将C ++二进制文件复制到项目的根目录。在我的CEF案例中,我使用Include和\**\*末尾的%(RecursiveDir)语法来确保复制所有文件以及locales文件夹。它的内容和结构得以保留。设置<Visible>false</Visible>后,您将无法查看解决方案资源管理器中的项目。

放松

现在,如果你发布你的应用程序,它应该复制所有必需的文件和文件夹。

答案 1 :(得分:1)

你可以尝试这个解决了类似的问题:

将不是.NET库的DLL作为文件添加到解决方案中:

Right click project > Add > Existing Item

然后将构建操作设置为Content,将“Copy to output directory”设置为“Copy Always”。

这样,库将包含在输出目录中。

答案 2 :(得分:1)

既然你已经尝试过手动添加可疑dll并且它仍然无效,我接下来要做的就是运行fusion并查看它真正抱怨的内容,换句话说,无法加载的依赖是什么。这是一个关于如何寻找这些类型的错误的好教程:

Back to Basics: Using Fusion Log Viewer to Debug Obscure Loader Errors

答案 3 :(得分:1)

也许你可以从https://github.com/Code52/DownmarkerWPF来源解决这个问题?

他们的应用嵌入CefSharp至少有一个工作ClickOnce installer。我知道,因为这是我在我的机器上安装的方式!

更新只是在评论中看到你说你失踪的VC Redist然后Distributing the Visual C++ Runtime Libraries (MSVCRT)似乎相关。

此外,我似乎还记得一些含糊不清的东西,因为VCRedist的原因&#34;您不应该分发应用程序的调试版本。你不能只是从Debug转换到Release版本吗?有了这个,我想你可以按照CefSharp FAQ中的建议捆绑所需的VCRedist文件,或者在你的安装程序中添加VCRedist作为先决条件。 DownmarkerWPF使用他们的WIX安装程序设置,您可以在他们的GitHub仓库中的分支上找到它。如果使用VStudio捆绑式安装程序,AFAIK可能会有类似的东西。

答案 4 :(得分:1)

感谢Barrie对此的回答,这对我帮助很大。我正在使用下面的答案,但是使用Visual Studio 2015将其更新为最新的CEF。

注意:我只构建/定位x86平台。您可能需要在下面的复制命令中更改或包含x64以满足您的需要。

安装CefSharp

  • 通过NuGet安装CefSharp.Wpf(我使用的是v51.0.0)

    NuGet Library After Install

  • 那应该将相关文件放在

      

    $(SolutionDir)packages \ CefSharp.Wpf.51.0.0 \ CefSharp(CefSharp.Wpf)   $(SolutionDir)packages \ CefSharp.Common.51.0.0 \ CefSharp(CefSharp.Common)   $(SolutionDir)packages \ cef.redist.x86.3.2704.1432 \ CEF(Cef x86 redist)   $(SolutionDir)packages \ cef.redist.x64.3.2704.1432 \ CEF(Cef x64 redist)

配置构建

  • 要将CefSharp DLL复制到我们的构建文件夹......我认为不再需要使用更高版本的CefSharp。我发现我不需要任何“后构建事件命令行”xcopy的东西来获得Click-Once将其发送出去。 (是的,DevTools也有效!)

处理Visual C ++ 2012运行时文件

  • (切换到VCR 2013)我不希望用户必须下载整个Visual C ++ 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。你可以相应地调整它......

确保使用ClickOnce

部署CEF和C ++运行时文件
  • 在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文件夹中的所有内容添加到项目中,并确保在部署时将C ++二进制文件复制到项目的根目录。设置为false后,您将无法在解决方案资源管理器中看到这些项目。

  • 请记住:我只是在构建/定位x86平台。您可能需要在下面的复制命令中更改或包含x64以满足您的需要。

发布

现在,如果您发布应用程序,它应该复制所有必需的文件和文件夹。

(EXTRA INFO)支持下面的旧操作系统信息

如果您需要将CefSharp用于旧机器(XP和Vista),请简单地说 使用旧的v47.0.0版本通过NuGet安装CefSharp.Wpf,并将.NET目标更改为.NET 4.0 Client Profile。

Chromium在2016年4月结束了对XP和Vista的支持,CefSharp版本47(或其他版本)仍然支持它。

关于问题和修复XP的另一个注意事项:

XP部署存在Chromium问题。下面是描述修复程序的文章,后面是为JBCB部署修补程序的步骤。

这是文章的链接: https://bitbucket.org/chromiumembedded/cef/issues/1787

...在其中你会看到一个下载“dbghelp.dll”的引用。下载并解压缩。

您可以采取下面的安装后方法,或选择与您的其他已发布文件一起包含DLL。我正在选择不部署额外的DLL并且只能手动部署XP机器(我们只有很少)。

采取以下步骤修复XP机器上的部署:

  1. 在XP机器上安装CefSharp浏览器(通过Click-Once)
  2. 复制“dbghelp.dll”
  3. 将其粘贴到XP计算机上的本地安装目录中(根据上一个链接中的说明:与“libcef.dll”文件一起)。
  4. 注意:对于一次性安装,将位于此位置下的子文件夹中:

    C:\Documents and Settings\<UserName>\Local Settings\Apps\2.0\<auto-gen ostificated ID>
    

答案 5 :(得分:0)

请仔细阅读CefSharp dependencies的官方列表-其中很多!您需要以某种方式将它们全部放入ClickOnce bin文件夹中。

这是我解决的方法:

  • 在部署之前,请安装最新版本的Visual C++ Redistributable。在您要部署到的每台PC上(使用组策略或手动)。
  • 从一个空白的测试项目开始。
  • 将项目引用添加到CefSharpCefSharp.Core
  • 将每个依赖项添加到项目目录中的单个文件夹中,以使它们保持井井有条(Files\CefSharp\)。
  • 确保所有文件都配置了Build Action: ContentCopy to Output Dir: Copy always
  • 使用功能Initalise_CefSharpFiles()将文件/文件夹复制到bin根文件夹(CefSharp在其中寻找它们)。例如,从以下位置复制:Bin\Files\CefSharp\*到:Bin\*
  • 最后,在运行时,在应用加载之后和初始化CefSharp的设置之前调用Initalise_CefSharpFiles()