Establecer archivos de contenido para “copiar local: siempre” en un paquete nuget

Genero un paquete nuget de un proyecto con este comando en el evento posterior a la construcción. la variable %conf% se establece en la configuración correcta (depuración o liberación) y %1 es el nombre del proyecto (p. ej., “MiEmpresa.MisProyecto”).

 nuget pack -Prop Configuration=%conf% "%1.csproj" -exclude *.sql -IncludeReferencedProjects 

Este paquete es para nuestro uso exclusivo, nunca será publicado en Nuget. Termina en nuestro repository privado.

En el proyecto, hay un archivo que está configurado para generate action : content y copy local : always . (Mi estudio visual está en francés, así que no estoy 100% seguro de la traducción). Vamos a llamarlo importantfile.xml .

En el paquete generado, termino con esta estructura:

 - content - importantfile.xml - lib -net45 (.NetFramework,Version=v4.5) -MyCompany.MyProject.dll 

Lo cual está bien, quiero que el archivo importantfile.xml se despliegue, porque, ¡bueno, este archivo es importante!

Cuando instalo el paquete en otro proyecto, importantfile.xml se implementa en la raíz del proyecto. Está bien. Pero no está configurado para copy local : always .

Necesito importantfile.xml para copy local : always en este proyecto donde instalo mi paquete.

¿Cómo puedo lograr eso?

Notas:

Puedo configurar copy local : always en el archivo justo después de instalar el paquete, eso no es gran cosa. Yo viviría con eso si las actualizaciones posteriores del paquete dejaran esta propiedad tal cual, que no es el caso. Al actualizar el paquete, copy local se restablece a never (como se indica aquí ).

Hay un archivo nuspec en la carpeta del proyecto, aquí está:

    $id$ $version$ $title$ $author$ $author$ false $description$ Copyright 2014 some random tags   

Puede usar PowerShell y el gancho Install.ps1 provisto por NuGet.

Ver la documentación .

A través de PowerShell debe ‘buscar’ el elemento de contenido que incluye su archivo importantfile.xml en un atributo. Cuando el script lo encontró, tiene que agregar Always como un elemento secundario.

   Always  

Puede encontrar algunos fragmentos de PowerShell aquí . Solo eche un vistazo a los archivos .ps1 .

Podría intentar lo siguiente (no probado). El archivo debe llamarse Install.ps1 y copiarse en la carpeta de tools :

 param($installPath, $toolsPath, $package, $project) # Load project XML. $doc = New-Object System.Xml.XmlDocument $doc.Load($project.FullName) $namespace = 'http://schemas.microsoft.com/developer/msbuild/2003' # Find the node containing the file. The tag "Content" may be replace by "None" depending of the case, check your .csproj file. $xmlNode = Select-Xml "//msb:Project/msb:ItemGroup/msb:Content[@Include='importantfile.xml']" $doc -Namespace @{msb = $namespace} #check if the node exists. if($xmlNode -ne $null) { $nodeName = "CopyToOutputDirectory" #Check if the property already exists, just in case. $property = $xmlNode.Node.SelectSingleNode($nodeName) if($property -eq $null) { $property = $doc.CreateElement($nodeName, $namespace) $property.AppendChild($doc.CreateTextNode("Always")) $xmlNode.Node.AppendChild($property) # Save changes. $doc.Save($project.FullName) } } 

También debe verificar si todo se elimina por completo al desinstalar el paquete.

Nota por Jonhhy5

Al actualizar el paquete mediante update-package , Visual Studio advierte que el proyecto se modifica “fuera del entorno”. Eso es causado por $doc.Save($project.FullName) . Si hago clic en volver a cargar antes de que el comando finalice por completo, a veces causa errores. El truco es dejar el diálogo allí hasta que el proceso finalice y luego volver a cargar los proyectos.

En lugar de utilizar una secuencia de comandos de PowerShell, otro enfoque es utilizar un objective de MSBuild o un archivo de utilería con el mismo nombre que el ID del paquete:

    importantfile.xml Always    

En el archivo nuspec, en lugar de agregar los archivos necesarios al directorio de Content , agréguelos al directorio de Build junto con el archivo de objectives.

  • Construir
    • importantfile.xml
    • MyPackage.targets
  • lib
    • net45
      • MyAssembly.dll

Si necesita contenido diferente para diferentes architectures, entonces puede agregar carpetas de architecture en Build también cada una con su propio archivo de objectives.

Beneficios de usar un archivo de objectives sobre el script de PowerShell con el directorio de Content NuGet:

  • los archivos de contenido requerido no se muestran en el proyecto en Visual Studio
  • los archivos de contenido están vinculados en lugar de copiados en el directorio de cada proyecto que hace referencia al paquete NuGet (evitando que haya múltiples copias y manteniendo el mismo comportamiento que los ensamblados / bibliotecas de los paquetes NuGet)
  • Los scripts de PowerShell solo funcionan en Visual Studio y no se ejecutan cuando se ejecuta NuGet desde la línea de comandos (servidores de comstackción, otros IDE y otros sistemas operativos); este enfoque funcionará en todos lados.
  • Los scripts de instalación de PowerShell no son compatibles con el sistema NuGet 3.x project.json .

así que sé que ustedes obtuvieron una solución funcional para esto, pero no funcionó para mí, así que voy a compartir lo que saqué del paquete NLog.config NuGet install.ps1

NOTA: este no es mi código, este es el contenido de install.ps1 del paquete nuget NLog.config solo compartiendo el conocimiento.

me parece un poco más directo y espero ayudar a otros que probablemente tropezarán con esto.

puede encontrar los valores int aceptados para BuildAction aquí y los valores aceptados para CopyToOutputDirectory aquí .

 param($installPath, $toolsPath, $package, $project) $configItem = $project.ProjectItems.Item("NLog.config") # set 'Copy To Output Directory' to 'Copy if newer' $copyToOutput = $configItem.Properties.Item("CopyToOutputDirectory") # Copy Always Always copyToOutput.Value = 1 # Copy if Newer copyToOutput.Value = 2 $copyToOutput.Value = 2 # set 'Build Action' to 'Content' $buildAction = $configItem.Properties.Item("BuildAction") $buildAction.Value = 2 

He hecho esto, que copia los archivos de mi carpeta de comstackción a la carpeta de salida (bin / debug o bin / release). Funciona como un encanto para mí.

Archivo Nuspec:

         

MyProject.targets

     %(RecursiveDir)%(FileName)%(Extension) PreserveNewest    

He escrito una pequeña herramienta llamada NuGetLib para agregar automáticamente archivos al paquete Nuget después de la comstackción.

  1. crea una carpeta de tools con tu script Install.ps1
  2. construye tu nugetPackage
  3. agregue la carpeta de herramientas al nugetPackage construido

https://stackoverflow.com/a/47134733/6229375