visual studio - studio - Establecer archivos de contenido para "copiar local: siempre" en un paquete nuget
nuget package manager visual studio 2017 (5)
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 repositorio 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 here ).
Hay un archivo nuspec en la carpeta del proyecto, aquí está:
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<copyright>Copyright 2014</copyright>
<tags>some random tags</tags>
</metadata>
</package>
En lugar de utilizar una secuencia de comandos de PowerShell, otro enfoque es utilizar un objetivo de MSBuild o un archivo de utilería con el mismo nombre que el ID del paquete:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)importantfile.xml">
<Link>importantfile.xml</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
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 objetivos.
- Construir
- importantfile.xml
- MyPackage.targets
- lib
- net45
- MyAssembly.dll
- net45
Si necesita contenido diferente para diferentes arquitecturas, entonces puede agregar carpetas de arquitectura en Build
también cada una con su propio archivo de objetivos.
Beneficios de usar un archivo de objetivos 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 compilació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 .
He escrito una pequeña herramienta llamada NuGetLib
para agregar automáticamente archivos al paquete Nuget después de la compilación.
- crea una carpeta de
tools
con tu scriptInstall.ps1
- construye tu
nugetPackage
- agregue la carpeta de herramientas al
nugetPackage
construido
https://.com/a/47134733/6229375
He hecho esto, que copia los archivos de mi carpeta de compilación a la carpeta de salida (bin / debug o bin / release). Funciona como un encanto para mí.
Archivo Nuspec:
<package>
<files>
<file src="/bin/Release/*.dll" target="lib" />
<file src="/bin/Release/x64/*.dll" target="build/x64" />
<file src="/bin/Release/x86/*.dll" target="build/x86" />
<file src="MyProject.targets" target="build/" />
</files>
</package>
MyProject.targets
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)**/*.dll" />
<None Include="@(NativeLibs)">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Puede usar PowerShell y el gancho Install.ps1
provisto por NuGet.
Ver la documentation .
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 <CopyToOutputDirectory>Always</CopyToOutputDirectory>
como un elemento secundario.
<Content Include="importantfile.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
Puede encontrar algunos fragmentos de PowerShell here . 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.
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 here .
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