Обычно при обращении к управляемой DLL, которая оборачивает неуправляемую DLL, с помощью PInvoke, вы должны ссылаться на эти две библиотеки отдельно - управляемую как стандартную <Reference/>
в вашем csproj и неуправляемую как связанную <content/>
(как обрисовано в общих чертах) здесь ).Однако недавно я наткнулся на управляемую библиотеку-оболочку, которая не только автоматически копирует неуправляемую DLL вместе с ней во время сборки, но фактически выдает ошибку сборки, когда неуправляемая DLL отсутствует в той же директории!Это библиотека Microsoft.Z3 , в которой есть управляемая DLL (Microsoft.Z3.dll), которая оборачивает неуправляемую DLL (libz3.dll) с помощью PInvoke, поэтому вы можете использовать библиотеку в C #.
Если вы поместите две библиотеки DLL Z3 вместе в один каталог, ссылаясь только на 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 илия должен был бы перекомпилировать это по-другому?