通常,当引用使用 PInvoke 包装非托管 DLL 的托管 DLL 时,必须分别引用这两个 DLL - 托管 DLL 作为标准<Reference/>
在您的 csproj 和链接的非托管项目中<content/>
(如概述here https://stackoverflow.com/questions/16420595/how-to-add-external-native-dependency-dll)。然而,我最近遇到了一个托管包装库,它不仅在构建过程中自动复制非托管 DLL,而且当非托管 DLL 不存在于同一目录中时实际上会产生构建错误!这是Microsoft.Z3 库 https://github.com/Z3Prover/z3/releases,它有一个托管 DLL (Microsoft.Z3.dll),它使用 PInvoke 包装了一个非托管 DLL (libz3.dll),因此您可以在 C# 中使用该库。
如果将两个 Z3 DLL 放在一个目录中,仅引用 Microsoft.Z3.dll,然后使用 msbuild 编译项目,那么您将在输出目录中获得这两个 DLL,而根本不引用 libz3.dll!查看产生的输出msbuild /verbosity:diag
,我看到以下对 libz3.dll 的引用:
Primary reference "Microsoft.Z3, Version=4.7.1.0, Culture=neutral, PublicKeyToken=9c8d792caae602a2". (TaskId:9)
Resolved file path is "C:\Users\ahelwer\source\test\Framework\lib\z3\Microsoft.Z3.dll". (TaskId:9)
Reference found at search path location "{HintPathFromItem}". (TaskId:9)
Found embedded scatter file "libz3.dll". (TaskId:9)
The ImageRuntimeVersion for this reference is "v4.0.30319". (TaskId:9)
...
Output Item(s):
_ReferenceScatterPaths=
C:\Users\ahelwer\source\test\Framework\lib\z3\libz3.dll
CopyLocal=true
FusionName=
HintPath=lib\z3\Microsoft.Z3.dll
OriginalItemSpec=C:\Users\ahelwer\source\test\Framework\lib\z3\Microsoft.Z3.dll
ResolvedFrom={HintPathFromItem}
Version=4.7.1.0 (TaskId:9)
这不知何故导致它被复制:
Task "Copy" (TaskId:22)
Task Parameter:
SourceFiles=
C:\Users\ahelwer\source\test\Framework\lib\z3\Microsoft.Z3.dll
CopyLocal=true
FusionName=Microsoft.Z3, Version=4.7.1.0, Culture=neutral, PublicKeyToken=9c8d792caae602a2
HintPath=lib\z3\Microsoft.Z3.dll
ImageRuntime=v4.0.30319
OriginalItemSpec=Microsoft.Z3
ReferenceSourceTarget=ResolveAssemblyReference
ResolvedFrom={HintPathFromItem}
Version=4.7.1.0
C:\Users\ahelwer\source\test\Framework\lib\z3\libz3.dll
CopyLocal=true
FusionName=
HintPath=lib\z3\Microsoft.Z3.dll
OriginalItemSpec=C:\Users\ahelwer\source\test\Framework\lib\z3\Microsoft.Z3.dll
ResolvedFrom={HintPathFromItem}
Version=4.7.1.0 (TaskId:22)
Task Parameter:
DestinationFiles=
bin\Debug\Microsoft.Z3.dll
CopyLocal=true
FusionName=Microsoft.Z3, Version=4.7.1.0, Culture=neutral, PublicKeyToken=9c8d792caae602a2
HintPath=lib\z3\Microsoft.Z3.dll
ImageRuntime=v4.0.30319
OriginalItemSpec=Microsoft.Z3
ReferenceSourceTarget=ResolveAssemblyReference
ResolvedFrom={HintPathFromItem}
Version=4.7.1.0
bin\Debug\libz3.dll
CopyLocal=true
FusionName=
HintPath=lib\z3\Microsoft.Z3.dll
OriginalItemSpec=C:\Users\ahelwer\source\test\Framework\lib\z3\Microsoft.Z3.dll
ResolvedFrom={HintPathFromItem}
Version=4.7.1.0 (TaskId:22)
它变得更加神秘,因为如果我将 libz3.dll 从目录中取出,构建将失败并出现以下错误:
"C:\Users\ahelwer\source\test\Framework\FrameworkTest.csproj" (default target) (1) ->
(_CopyFilesMarkedCopyLocal target) ->
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\bin\Microsoft.Common.CurrentVersion.targe
ts(4358,5): error MSB3030: Could not copy the file "C:\Users\ahelwer\source\test\Framework\lib\z3\libz3.dll" because it
was not found. [C:\Users\ahelwer\source\test\Framework\FrameworkTest.csproj]
即使我以标准方式引用 libz3.dll<content/>
在我的 csproj 中!
问题:
- Microsoft.Z3.dll 有什么特别之处,使其能够在构建过程中要求 libz3.dll 位于同一目录中?它是用某些标志编译的吗?
- 如何将此效果添加到我自己的托管包装库中?
- 有什么方法可以从 Microsoft.Z3.dll 中消除这种影响,或者我必须以不同的方式重新编译它?