visual-studio 有没有更好的方法将本机 dll 复制到 bin 文件夹?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3863419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 12:32:44  来源:igfitidea点击:

Are there any better ways to copy a native dll to the bin folder?

.netvisual-studiobuildpost-build-event

提问by Ahmad

I have C# wrapper code that calls functions from a native (C++) dll. Currently, I can add a reference to the C# dll and have set the 'Copy Local' option to true. However the native dll, which is a dependency, cannot be added as a reference - so there is no 'Copy Local' option.

我有从本机 (C++) dll 调用函数的 C# 包装器代码。目前,我可以添加对 C# dll 的引用并将“复制本地”选项设置为 true。但是,作为依赖项的本机 dll 无法添加为参考 - 因此没有“复制本地”选项。

I have tried the following approaches

我尝试了以下方法

  1. Using a post-build events to copy the native dll from the Libs folder to the $(TargetFolder)

    copy "$(ProjectDir)Libs\NQuantLibc.dll" "$(TargetDir)NQuantLibc.dll"

  2. Included the native dll as an existing item in the project (Add -> Existing Item -> Include dll). This option allows me to use the 'Copy Local' option. The downside to this approach is that the dll always shows as a project item.

  1. 使用构建后事件将本机 dll 从 Libs 文件夹复制到 $(TargetFolder)

    copy "$(ProjectDir)Libs\NQuantLibc.dll" "$(TargetDir)NQuantLibc.dll"

  2. 将本机 dll 作为现有项目包含在项目中(添加 -> 现有项目 -> 包含 dll)。此选项允许我使用“复制本地”选项。这种方法的缺点是 dll 始终显示为项目项。

I also tried "Show All Files" which allowed me to see the Libs folder. I then include the NQuantLibc.dll file in the project which allowed me to set the 'Copy Local' option. However, this gave me a unexpected result. It created a Libs subfolder containing the dll within the bin folder (eg bin/debug/Libs/NQuantLibc.dll). Not ideal since the C# dll was not able to properly call the native dll since it was not there.

我还尝试了“显示所有文件”,这让我可以看到 Libs 文件夹。然后我在项目中包含 NQuantLibc.dll 文件,这允许我设置“复制本地”选项。然而,这却给了我意想不到的结果。它在 bin 文件夹(例如bin/debug/Libs/NQuantLibc.dll)中创建了一个包含 dll 的 Libs 子文件夹。不理想,因为 C# dll 无法正确调用本机 dll,因为它不存在。

Both of the above options above work. Are there any better ways to copy a native dll to the bin folder such that the dependency will always be resolved? Alternatively, is there a different approach to this type of scenario?

上述两个选项都有效。有没有更好的方法将本机 dll 复制到 bin 文件夹,以便始终解决依赖关系?或者,对于这种类型的场景是否有不同的方法?

回答by Hans Passant

Use Project + Add Existing Item and select the DLL. Select the added file in the Solution Explorer window. In the Properties window, change the Copy to Output Directory setting to "Copy if newer".

使用 Project + Add Existing Item 并选择 DLL。在解决方案资源管理器窗口中选择添加的文件。在“属性”窗口中,将“复制到输出目录”设置更改为“如果更新则复制”。

回答by Yochai Timmer

You can add the native dll as a linked item, and use "Copy if newer".
The problem with native dlls, is that sometimes you'll want to use different dlls according to the project's configuration (Debug/Release or platform).

您可以将本机 dll 添加为链接项,并使用“如果更新则复制”。
本机 dll 的问题在于,有时您需要根据项目的配置(调试/发布或平台)使用不同的 dll。

You can edit the project's .csproj and link the native dll conditionally:

您可以编辑项目的 .csproj 并有条件地链接本机 dll:

 <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">
    <Content Include="..\..\bin\Win32\Release\NQuantLibc.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
 </ItemGroup>   
 <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">
    <Content Include="..\..\bin\Win32\Debug\NQuantLibc_d.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
  <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
    <Content Include="..\..\bin\x64\Debug\NQuantLibc_d.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
  <ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
    <Content Include="..\..\bin\x64\Release\NQuantLibc.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

Note the copy option is set to PreserveNewestwhich means "copy if newer".

请注意,复制选项设置为PreserveNewest,意思是“如果更新则复制”。

回答by Floyd

Found a better way. Nuget can add .targets files, witch are stored in the build folder of the package, into your project. With this way you can copy at each build some files of your package wherever you want. In the following example, I have stored some Non DotNet DLL into a "binaries" folder. At each build, It checks if DLLs are already copied in the output folder ($OutputPath variable) and copy them if necessary.

找到了更好的方法。Nuget 可以将 .targets 文件(存储在包的 build 文件夹中)添加到您的项目中。通过这种方式,您可以在每次构建时随时随地复制您的包的一些文件。在以下示例中,我将一些非 DotNet DLL 存储到“二进制文件”文件夹中。在每次构建时,它会检查 DLL 是否已复制到输出文件夹($OutputPath 变量)中,并在必要时复制它们。

Nuspec content :

Nuspec内容:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
        <id>Example</id>
        <version>1.0.0</version>
        <authors>Example</authors>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>Example</description>
    </metadata>
    <files>
        <file src="Non-DotNet.dll" target="binaries\Non-DotNet.dll" />
        <file src="DotNet.dll" target="lib\net40\DotNet.dll" />
        <file src="Example.targets" target="build\Example.targets" />
    </files>
</package>

Example.targets content :

Example.targets 内容:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <Target Name="CopyBinaries" BeforeTargets="BeforeBuild">
        <CreateItem Include="$(MSBuildThisFileDirectory)..\binaries\**\*.*">
            <Output TaskParameter="Include" ItemName="PackageBinaries" /> 
        </CreateItem>

        <Copy SourceFiles="@(PackageBinaries)"
              DestinationFolder="$(OutputPath)"
              SkipUnchangedFiles="true"
              OverwriteReadOnlyFiles="true"
        />
    </Target>
</Project>

回答by Adrian Zanescu

Add the dll as a file in the project ("As link" maybe if u still want it to reside in another directory). Then set the Build Action to content and Copy to output directory to true.

将 dll 作为文件添加到项目中(如果您仍然希望它驻留在另一个目录中,则可能是“作为链接”)。然后将 Build Action 设置为 content 并将 Copy to output directory 设置为 true。

回答by Igal Tabachnik

If you're OK with the created "Libs" folder, you can try adding it to the probing pathfor your application, by adding the following in the app.configfile:

如果您对创建的“Libs”文件夹没问题,您可以尝试将其添加到应用程序的探测路径中,方法是在app.config文件中添加以下内容:

<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <probing privatePath="Libs;Bin2"/>
      </assemblyBinding>
   </runtime>
</configuration>

This will cause the runtime to look in all the specified directories for the DLL.

这将导致运行时在所有指定的 DLL 目录中查找。

EDITUnfortunately, this does not impact the unmanaged DLL loading by DllImport.

编辑不幸的是,这不会影响 DllImport 的非托管 DLL 加载

回答by Manfred Wippel

Apparently I happened to have the same problem, but I did not want to do project file editing so much, so I ended up using following post-build script:

显然我碰巧遇到了同样的问题,但我不想做太多的项目文件编辑,所以我最终使用了以下后期构建脚本:

xcopy /y "$(ProjectDir)\lib_$(Platform)\*.dll" "$(ProjectDir)$(OutDir)"

xcopy /y "$(ProjectDir)\lib_$(Platform)\*.dll" "$(ProjectDir)$(OutDir)"

Just make sure you have a folder for every targeting platform needed, e.g.: lib_x86, lib_x64and maybe lib_AnyCPU

只需确保您为所需的每个定位平台都有一个文件夹,例如:lib_x86lib_x64也许lib_AnyCPU