Estoy tratando de crear el paquete NuGet para un ensamblado .Net que hace pinvoke a un win32 dll nativo. Necesito empacar tanto el ensamblado como el dll nativo con el ensamblado agregado a las referencias del proyecto (no hay problema en esta parte) y el dll nativo debe copiarse en el directorio de salida del proyecto o en algún otro directorio relativo.
Mis preguntas son:
- ¿Cómo empaco el dll nativo sin que Visual Studio intente agregarlo a la lista de referencias?
- ¿Tengo que escribir un archivo install.ps1 para copiar el dll nativo? Si es así, ¿cómo puedo acceder al contenido del paquete para copiarlo?
nuget
nuget-package
nuget-spec
AlonFStackoverflow
fuente
fuente
Respuestas:
El uso del
Copy
destino en el archivo de destino para copiar las bibliotecas requeridas no copiará esos archivos a otros proyectos que hagan referencia al proyecto, lo que dará como resultado unDllNotFoundException
. Sin embargo, esto se puede hacer con un archivo de objetivos mucho más simple, utilizando unNone
elemento, ya que MSBuild copiará todos losNone
archivos a proyectos de referencia.Agregue el archivo de destino al
build
directorio del paquete nuget junto con las bibliotecas nativas requeridas. El archivo de objetivos incluirá todos losdll
archivos en todos los directorios secundarios delbuild
directorio. Así que añadir unax86
yx64
versión de una biblioteca nativa utilizada por unAny CPU
ensamblado administrado que terminaría con una estructura de directorios similar a la siguiente:Lo mismo
x86
y losx64
directorios se crearán en el directorio de salida del proyecto cuando se construyan. Si no necesita subdirectorios, el**
y el%(RecursiveDir)
se pueden eliminar y, en su lugar, incluir los archivos necesarios en elbuild
directorio directamente. Otros archivos de contenido necesarios también se pueden agregar de la misma manera.Los archivos agregados como
None
en el archivo de destino no se mostrarán en el proyecto cuando se abran en Visual Studio. Si se pregunta por qué no uso laContent
carpeta en el nupkg es porque no hay forma de configurar elCopyToOutputDirectory
elemento sin usar un script de PowerShell (que solo se ejecutará dentro de Visual Studio, no desde el símbolo del sistema, en los servidores de compilación o en otros IDEs, y no es compatible con proyectos project.json / xproj DNX ) y prefiero usar aLink
para los archivos en lugar de tener una copia adicional de los archivos dentro del proyecto.Actualización: aunque esto también debería funcionar en
Content
lugar deNone
parecer que hay un error en msbuild, por lo que los archivos no se copiarán a proyectos de referencia que se eliminen más de un paso (por ejemplo, proj1 -> proj2 -> proj3, proj3 no obtendrá los archivos del paquete NuGet de proj1 pero proj2 lo hará).fuente
'$(MSBuildThisFileDirectory)' != '' And HasTrailingSlash('$(MSBuildThisFileDirectory)')
requiere la condición ? Pensé que elMSBuildThisFileDirectory
siempre está configurado. ¿Cuándo ese no sería el caso?**\*.dll
? Eso es copiar todos los.dll
archivos en todos los directorios. Podría hacer fácilmente**\*.*
para copiar un árbol de directorios completo.Recientemente tuve el mismo problema cuando intenté construir un paquete Nuguet de EmguCV que incluye tanto ensamblados administrados como bibliotecas compartidas no administradas (que también tuvieron que colocarse en un
x86
subdirectorio) que tuvieron que copiarse automáticamente al directorio de salida de compilación después de cada compilación .Aquí hay una solución que se me ocurrió, que se basa solo en NuGet y MSBuild:
Coloque los ensamblados administrados en el
/lib
directorio del paquete (parte obvia) y las bibliotecas compartidas no administradas y los archivos relacionados (por ejemplo, paquetes .pdb) en el/build
subdirectorio (como se describe en los documentos de NuGet ).Cambie el nombre de todas las
*.dll
terminaciones de archivos no administradas a algo diferente, por ejemplo,*.dl_
para evitar que NuGet se queje de que los supuestos ensamblajes se coloquen en un lugar incorrecto ( "Problema: ensamblaje fuera de la carpeta lib" ).Agregue un
<PackageName>.targets
archivo personalizado en el/build
subdirectorio con algo como los siguientes contenidos (consulte la descripción a continuación):El
.targets
archivo anterior se inyectará en una instalación del paquete NuGet en el archivo de proyecto de destino y es responsable de copiar las bibliotecas nativas en el directorio de salida.<AvailableItemName Include="NativeBinary" />
agrega un nuevo elemento "Build Action" para el proyecto (que también está disponible en el menú desplegable "Build Action" dentro de Visual Studio).<NativeBinary Include="...
agrega las bibliotecas nativas ubicadas en el/build/x86
proyecto actual y las hace accesibles para el destino personalizado que copia esos archivos en el directorio de salida.<TargetPath>x86</TargetPath>
agrega metadatos personalizados a los archivos y le dice al objetivo personalizado que copie los archivos nativos en elx86
subdirectorio del directorio de salida real.El
<PrepareForRunDependsOn ...
bloque agrega el objetivo personalizado a la lista de objetivos de los que depende la compilación; consulte el archivo Microsoft.Common.targets para obtener más información.El objetivo personalizado
CopyNativeBinaries
, contiene dos tareas de copia. El primero es responsable de copiar cualquier*.dl_
archivo al directorio de salida mientras cambia su extensión de nuevo al original*.dll
. El segundo simplemente copia el resto (por ejemplo, cualquier*.pdb
archivo) a la misma ubicación. Esto podría ser reemplazado por una tarea de copia única y un script install.ps1 que tuvo que cambiar el nombre de todos los*.dl_
archivos*.dll
durante la instalación del paquete.Sin embargo, esta solución aún no copiaría los binarios nativos al directorio de salida de otro proyecto que haga referencia al que inicialmente incluye el paquete NuGet. Todavía tiene que hacer referencia al paquete NuGet en su proyecto "final" también.
fuente
DllNotFoundException
.<NoWarn>NU5100</NoWarn>
a su archivo de proyectoAquí hay una alternativa que usa
.targets
para inyectar la DLL nativa en el proyecto con las siguientes propiedades.Build action
=None
Copy to Output Directory
=Copy if newer
El principal beneficio de esta técnica es que la DLL nativa se copia en la
bin/
carpeta de proyectos dependientes transitiva.Vea el diseño del
.nuspec
archivo:Aquí está el
.targets
archivo:Esto inserta el
MyNativeLib.dll
como si fuera parte del proyecto original (pero curiosamente el archivo no es visible en Visual Studio).Observe el
<Link>
elemento que establece el nombre del archivo de destino en labin/
carpeta.fuente
Content
aNone
?Si alguien más se topa con esto.
El
.targets
nombre del archivo DEBE ser igual al Id. Del paquete NuGetCualquier otra cosa no funcionará.
Los créditos van a: https://sushihangover.github.io/nuget-and-msbuild-targets/
Debería haber leído más a fondo, ya que en realidad se señala aquí. Me llevó años ...
fuente
Es un poco tarde, pero he creado un paquete nuget exactamente para eso.
La idea es tener una carpeta especial adicional en su paquete nuget. Estoy seguro de que ya conoces Lib y Content. El paquete nuget que he creado busca una carpeta llamada Salida y copiará todo lo que está allí a la carpeta de salida de proyectos.
Lo único que debe hacer es agregar una dependencia nuget al paquete http://www.nuget.org/packages/Baseclass.Contrib.Nuget.Output/
He escrito una publicación de blog al respecto: http://www.baseclass.ch/blog/Lists/Beitraege/Post.aspx?ID=6&mobile=0
fuente
Hay una solución C # pura que encuentro bastante fácil de usar y no tengo que molestarme con las limitaciones de NuGet. Sigue estos pasos:
Incluya la biblioteca nativa en su proyecto y establezca su propiedad Build Action en
Embedded Resource
.Pega el siguiente código en la clase donde invocas esta biblioteca.
Llame a este método desde el constructor estático de la siguiente manera
UnpackNativeLibrary("win32");
y desempaquetará la biblioteca en el disco justo antes de que lo necesite. Por supuesto, debe asegurarse de tener permisos de escritura en esa parte del disco.fuente
Esta es una vieja pregunta, pero ahora tengo el mismo problema, y encontré un cambio que es un poco complicado pero muy simple y efectivo: cree en la carpeta de Contenido estándar de Nuget la siguiente estructura con una subcarpeta para cada configuración:
Cuando empaque el archivo nuspec, recibirá el siguiente mensaje para cada biblioteca nativa en las carpetas Debug and Release:
No necesitamos esa "solución" porque este es solo nuestro objetivo: que las bibliotecas nativas no se agreguen como referencias de ensamblados NET.
Las ventajas son:
Las desventajas son:
fuente
No puedo resolver tu problema exacto, pero puedo darte una sugerencia.
Su requisito clave es: "Y que no se registre automáticamente la referencia" .....
Por lo tanto, deberá familiarizarse con los "elementos de solución"
Ver referencia aquí:
Agregar elementos a nivel de solución en un paquete NuGet
Tendrá que escribir un poco de vudú de PowerShell para obtener la copia de su dll nativo en su hogar (de nuevo, porque NO desea que se active el vudú de referencia automática)
Aquí hay un archivo ps1 que escribí ... para colocar archivos en una carpeta de referencias de terceros.
Hay suficiente para que descubras cómo copiar tu dll nativo a algún "hogar" ... sin tener que empezar desde cero.
De nuevo, no es un golpe directo, pero es mejor que nada.
fuente
Ponlo es la carpeta de contenido
El comando
nuget pack [projfile].csproj
lo hará por usted automáticamente si marca los archivos como contenido.luego edite el archivo del proyecto como se menciona aquí agregando el elemento ItemGroup & NativeLibs & None
trabajó para mi
fuente