在Visual Studio项目中本地复制本机依赖项 [英] Copy native dependencies locally in a Visual Studio project
问题描述
我有一个混合模式的C ++项目,该项目生成一个托管的dll程序集,该程序集导出了一些CLR类(称为Managed.dll)。该项目使用的是本机dll(称为Native.dll)。
I have a mixed mode C++ project producing a managed dll assembly exporting some CLR classes (call it Managed.dll). This project is using a native dll, (call it Native.dll).
当我从另一个生成Client.exe的项目中引用Managed.dll时,一切正常,除了我需要手动将Native.dll复制到与Client.exe相同的文件夹中。
When I reference the Managed.dll from another project producing Client.exe, everything works as expected, except than I need to manually copy the Native.dll in the same folder as Client.exe.
如果有办法说服VS在本地复制(在垃圾箱中)
If there a way to convince VS to copy locally (in the bin folder of Client.exe) not only Managed.dll but Native.dll as well?
我试图在清单中包括Native.dll作为依赖程序集,但这没有帮助。
I have tried to include Native.dll as a dependency assembly in the manifest but this didn't help.
编辑
Managed.dll将成为可重新分发的程序集。它将安装在 C:\Program Files .....的文件夹中。当使用Visual Studio的开发人员添加对Managed.dll的引用时,Native.dll也应复制到其项目的\bin文件夹中。
Managed.dll is going to be a redistributable assembly. It will be installed in a folder in "C:\Program Files.....". When a developer using Visual Studio adds a reference to Managed.dll, Native.dll should be also copied in the \bin folder of his project.
推荐答案
有几种方法可以告诉VS将dll复制到目标文件夹:
There are several ways to tell the VS to copy dlls to the destination folder:
1。将dll添加为项目的资源。并告诉VS如果dll是较新的副本
1.Add the dll as a resource of the project. And tell the VS to copy it if the dll is newer
2。添加一个引用该dll项目的新项目,并将OutDir设置为所需的文件夹。该项目除了复制dll外什么都不做。
2.Add a new project that reference to the dll project, and set the OutDir to the folder you want. This project does nothing but copy the dll.
3。在vcxproj文件中使用PostBuildEvent
3.Use a PostBuildEvent in vcxproj file
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
</ClCompile>
<Link>
</Link>
<PostBuildEvent>
<Command>
echo off
mkdir "$(ProjectDir)..\..\bin\$(Configuration)\"
copy "$(OutDir)xxx.dll" "$(ProjectDir)..\..\lib\$(Configuration)\"
echo on
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
4。在vcxproj文件中使用PreBuildEvent
4.Use a PreBuildEvent in vcxproj file
5。在vcxproj文件中使用CustomBuild
5.Use CustomBuild in vcxproj file
<ItemGroup>
<CustomBuild Include="..\..\xxx.dll">
<FileType>Document</FileType>
<Command>
call mkdir "$(OutDir)" 2>nul &
copy /Y "..\..\xxx.dll" "$(OutDir)xxx.dll"
</Command>
<Message>Copying xxx.dll to $(OutDir)\xxx.dll</Message>
<Outputs>$(OutDir)\xxx.dll</Outputs>
</CustomBuild>
</ItemGroup>
6。使用makefile并将dll复制到makefile中。并使用nmake来构建
6.Use a makefile and copy dll in makefile. and use nmake to build
7。编写一个执行复制作业的bat文件,然后像3-6一样调用bat文件
7.Write a bat file that do the copy job, and invoke the bat file as in 3-6
8。使用python这样的脚本,也可以从Internet下载dll。然后像3-6一样调用py文件。
8.Use script such as python, which can also download the dll from internet. And invoke the py file as in 3-6.
9。其他构建工具也可以提供帮助,例如gradle
9.Other build tools can help too, such as gradle
10。制作一个NuGet插件
10.Make it a NuGet plugin
11。有时候我只是写了一个蝙蝠,然后手动执行该蝙蝠。
11.Sometimes I just write a bat, and execute the bat manually.
更新01(自解压dll示例):
1。将本机dll添加为托管dll资源
1.Add you native dll as resource of managed dll
2。添加此init()方法
2.Add this init() method
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace DllSelfExtract
{
public class SelfExtract
{
public static void Init()
{
String managedDllPath = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
String nativeDllPath = managedDllPath.Replace("file:///", "").Replace("DllSelfExtract.DLL", "TestDll.dll");
if(!File.Exists(nativeDllPath))
{
Stream dllIn = Assembly.GetExecutingAssembly().GetManifestResourceStream("DllSelfExtract.TestDll.dll");
if (dllIn == null) return;
using (Stream outFile = File.Create(nativeDllPath))
{
const int sz = 4096;
byte[] buf = new byte[sz];
while (true)
{
int nRead = dllIn.Read(buf, 0, sz);
if (nRead < 1)
break;
outFile.Write(buf, 0, nRead);
}
}
}
//LoadLibrary Here
}
}
}
3。在使用托管dll的项目中,首先调用init()方法
3.In project that use your managed dll, invoke init() method first
SelfExtract.Init();
更新02(以NuGet为例):
1。创建一个新的NuGet项目
1.Create a new NuGet project
2。将托管程序集放在/ lib目录中
2.Place the managed assemblies in the /lib directory
3。将非托管共享库和相关文件放在/ build子目录中,并将所有非托管* .dll重命名为* .dl _
3.Place the non-managed shared libraries and related files in the /build subdirectory and rename all non-managed *.dll to *.dl_
4。在/ build子目录中添加一个自定义.targets文件,其内容类似于以下内容:
4.Add a custom .targets file in the /build subdirectory with something like the following contents :
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<AvailableItemName Include="NativeBinary" />
</ItemGroup>
<ItemGroup>
<NativeBinary Include="$(MSBuildThisFileDirectory)*">
<TargetPath></TargetPath>
</NativeBinary>
</ItemGroup>
<PropertyGroup>
<PrepareForRunDependsOn>
$(PrepareForRunDependsOn);
CopyNativeBinaries
</PrepareForRunDependsOn>
</PropertyGroup>
<Target Name="CopyNativeBinaries" DependsOnTargets="CopyFilesToOutputDirectory">
<Copy SourceFiles="@(NativeBinary)"
DestinationFiles="@(NativeBinary->'$(OutDir)\%(TargetPath)\%(Filename).dll')"
Condition="'%(Extension)'=='.dl_'">
<Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
</Copy>
<Copy SourceFiles="@(NativeBinary)"
DestinationFiles="@(NativeBinary->'$(OutDir)\%(TargetPath)\%(Filename).%(Extension)')"
Condition="'%(Extension)'!='.dl_'">
<Output TaskParameter="DestinationFiles" ItemName="FileWrites" />
</Copy>
</Target>
</Project>
5。在Package.nuspec中为build文件夹添加构建规则
5.Add build rule for build folder in Package.nuspec
<files>
<file src="lib\" target="lib" />
<file src="tools\" target="tools" />
<file src="content\" target="content" />
<file src="build\" target="build" />
</files>
6。构建程序包
7在其他C#项目中,只需添加此NuGet包即可。
7.In your other C# project just add this NuGet package.
这篇关于在Visual Studio项目中本地复制本机依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!