c# asp.net-core nuget nuget-package .net-core

c# - Extracción automática de archivos DLL nativos y administrados que se extraen del paquete Nuget



asp.net-core nuget-package (1)

Trataré de explicar todo el dolor y las soluciones por las que he pasado lo más detallado posible. En mi ejemplo, uso archivos de texto simples AAA86.txt , AAA64.txt y AAAany.txt lugar de archivos DLL nativos para simplemente demostrar el proceso de extracción.

Lo primero que debe saber: si intenta mezclar la arquitectura native NuGet con una carpeta lib contiene algunas bibliotecas administradas, NO FUNCIONARÁ

En ese caso, las DLL administradas se copiarán en el directorio de salida de su proyecto, pero NO en las nativas.

Gracias a Jon Skeet que me señaló en la buena dirección, aconsejándome que eche un vistazo al paquete Grpc.Core . El truco es crear un archivo de targets que manejará la extracción de DLL.

Su archivo de objetivos debe contener algo como esto

<?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Condition=" ''$(Platform)'' == ''x64'' "> <Content Include="$(MSBuildThisFileDirectory)../../runtimes/win-x64/native/AAA64.txt"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Link>AAA64.txt</Link> </Content> </ItemGroup> <ItemGroup Condition=" ''$(Platform)'' == ''x86'' OR ''$(Platform)'' == ''AnyCPU'' "> <Content Include="$(MSBuildThisFileDirectory)../../runtimes/win-x86/native/AAA86.txt"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <Link>AAA86.txt</Link> </Content> </ItemGroup> </Project>

Ahora hay algunas otras cosas que debes saber:

1) Visual Studio no se preocupa en absoluto por la configuración que elija, siempre usará un RID ficticio. (En mi caso, siempre termino con una carpeta win7-x64 aunque estoy en Windows 10 ...)

2) La configuración de la plataforma en su project.json también es totalmente inútil

{ "buildOptions": { "platform": "x64" } }

3) En la configuración de tiempos de ejecución si establece solo win y / o win-x64

"runtimes": { "win": {}, "win-x64": {} }

Visual Studio en su lugar usará win7-x64 . Pero si agrega win10-x64 mientras está en una máquina con Windows 10, entonces se usará

4) Si compila su aplicación con un RID genérico como este

dotnet build -c debug -r win

Luego, su archivo de targets recibirá la arquitectura de su máquina (x64 en mi caso) en lugar de AnyCPU como esperaba

5) Si solo tiene bibliotecas nativas sin ninguna administrada, la extracción funcionará sin un archivo de destino si sigue los runtimes/RID/native la arquitectura runtimes/RID/native

6) Con SOLO bibliotecas nativas en mi paquete, el RID elegido siempre se construirá con win-x64 con Visual Studio, como le dije, la carpeta de tiempo de ejecución siempre creada es win7-x64 , sin importar la configuración que seleccione. Si solo tuviera un RID de una sola win en mi paquete, se seleccionará con éxito.

Esto me está volviendo loco durante varios meses y todavía no puedo lograrlo. Mis bibliotecas administradas se extraen del paquete Nuget pero no las nativas.

Tenemos un montón de bibliotecas administradas y nativas proporcionadas por otra compañía. Tenemos versiones x86 y x64 de ellos. Para usarlos en un proyecto ASP.NET Core, tengo que crear un paquete Nuget.

Mi arquitectura es:

  • una biblioteca de clase ASP.NET Core que cambié para apuntar solo a .NET Framework completo. Este proyecto hace referencia a mi paquete Nuget
  • un sitio web ASP.NET Core también dirigido a .NET Framework completo y haciendo referencia a la biblioteca de clases

Por supuesto, al final, necesito que mis bibliotecas nativas se extraigan a la carpeta de tiempo de ejecución adecuada del sitio web (por ejemplo: /bin/Debug/net461/win7-x64 ).

Por el momento mi solución fue:

  • para poner las bibliotecas nativas dentro de la carpeta de build
  • cree un archivo de targets que los $(OutputPath) (que ni siquiera es la carpeta de tiempo de ejecución)
  • agregar algunos comandos de xproj al xproj de mi sitio web para obtener el archivo de destino en mi carpeta $(USERPROFILE)/.nuget/packages/ y ejecutarlo
  • copie a mano las DLL nativas ahora extraídas en la carpeta bin al runtime

Intenté copiarlos directamente a la carpeta de tiempo de ejecución usando alguna configuración en project.json (sinceramente, no recuerdo todas las cosas que intenté para esta parte), pero esto siempre fallaba. Además, aunque especifiqué SkipUnchangedFiles="true" en mi archivo de objetivos, esto simplemente se ignora y mis archivos DLL se copian en mi carpeta bin durante cada compilación.

Este es un proceso pesado solo para lograr una extracción de DLL, ahora realmente quiero deshacerme de todo eso MsBuild y obtener una solución mucho más simple.

Sé que con las versiones más nuevas de Nuget, ahora es capaz de extraerlas de forma nativa sin la ayuda de agregar comandos personalizados MsBuild. Como está escrito here , los proyectos de C # ni siquiera necesitan un archivo de targets

A continuación, los proyectos de C ++ y JavaScript que pueden consumir su paquete NuGet necesitan un archivo .targets para identificar el ensamblaje necesario y los archivos winmd. (Los proyectos de C # y Visual Basic hacen esto automáticamente).

Mantuve una pestaña abierta en mi navegador durante varios meses ( enlace original ) y me di cuenta de que este recurso se ha eliminado recientemente del sitio web de Nuget. Explicaba cómo usar la carpeta de runtimes para extraer automáticamente las DLL nativas. Sin embargo, nunca he podido obtener un resultado exitoso como se explicó. Ahora esta página ha sido eliminada y reemplazada por esta con tan pocas explicaciones y sin hablar de esta carpeta de runtimes .

Supongo que debería usar la carpeta de runtimes para las DLL nativas y la lib para las administradas, pero no estoy 100% seguro de eso. (¿también debería usar la carpeta de build ?)

He intentado varias cosas (no puedo recordar el número de intentos, como dije varios meses de dolor de cabeza ...) como esta arquitectura (no entiendo cuál es el punto de tener carpetas de build/native y nativas en runtimes )

También intenté usar la estructura de versión de .NET Framework como se describe here para mis bibliotecas administradas.

This parece ser también parte de la solución.

El compilador ignora la arquitectura al crear una referencia de ensamblaje. Es un concepto de tiempo de carga. El cargador preferirá una referencia específica de arquitectura si existe.

Un truco que puede usar para producir un ensamblaje AnyCPU es usar corflags para eliminar la arquitectura de su ensamblaje x86. Por ejemplo: corflags / 32BITREQ- MySDK.dll. Corflags es parte del SDK de .NET y se puede encontrar en el símbolo del sistema del desarrollador de VS.

Eso es lo que hice, convirtiendo las DLL x86 y x64 a AnyCPU (no sé si hace algo para las DLL x64 pero no obtuve errores) y luego probé varias arquitecturas diferentes en mi paquete Nuget pero aún no funciona.

El tiempo de ejecución predeterminado sin ninguna entrada en project.json es win7-x64 , por lo que decidí especificarlo explícitamente por si acaso

"runtimes": { "win7-x64": {} },

Así que este es el identificador de tiempo de ejecución que estoy usando para todos mis intentos en mi paquete Nuget. Sin embargo, no me importa la versión de Windows. De hecho, preferiría tener win-x86 o win-x64 pero parece ser un valor no válido de acuerdo con esta página

RID de Windows

Windows 7 / Windows Server 2008 R2

  • win7-x64
  • win7-x86

Windows 8 / Windows Server 2012

  • win8-x64
  • win8-x86
  • win8-arm

Windows 8.1 / Windows Server 2012 R2

  • win81-x64
  • win81-x86
  • win81-arm

Windows 10 / Windows Server 2016

  • win10-x64
  • win10-x86
  • win10-arm
  • win10-arm64

Sin embargo, esta fuente de Github está describiendo más RID, ¿cuál es la fuente correcta?

Como puede ver, hay tantos misterios aquí, principalmente debido a la falta de documentación o incluso a contradicciones entre diferentes documentos.

Si al menos pudiera tener un ejemplo de trabajo, podría realizar mis pruebas para responder otras preguntas, como probar RID win-x64 genérico o ver si puedo incluir una vez que mis bibliotecas administradas sean cuales sean las versiones de .NET Framework.

Preste atención a mi contexto especial: tengo un proyecto ASP.NET Core dirigido a .NET Framework completo

Gracias por sus respuestas, estoy desesperado por hacer que esto funcione.