Set content files to "copy local : always" in a nuget package
copy-local, nuget, nuget-package, visual-studio, visual-studio-2012
Solution
You can use PowerShell and the `Install.ps1` hook provided by NuGet.
See the documentation.
Via PowerShell you have to 'search' for the content element which includes your `importantfile.xml` in an attribute. When the script found it, it has to add `<CopyToOutputDirectory>Always</CopyToOutputDirectory>` as a child element.
<Content Include="importantfile.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
You can find some PowerShell snippets here. Just take a look at the `.ps1` files.
You could try the following (not tested). The file has to be named `Install.ps1` and copied into the `tools` folder:
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)
}
}
You should also check if everything is removed completely when uninstalling the package.
Note by Jonhhy5
When updating the package via `update-package`, Visual Studio warns that the project is modified "outside the environnment". That's caused by `$doc.Save($project.FullName)`. If I click reload before the command is fully terminated, it sometimes causes errors. The trick is to leave the dialog there until the process finishes, and then reload the projects.
Problem
I generate a nuget package from a project with this command in the post-build event. the variable `%conf%` is set to the right configuration (debug or release) and `%1` is the project name (e.g. "MyCompany.MyProject"). ``` nuget pack -Prop Configuration=%conf% "%1.csproj" -exclude *.sql -IncludeReferencedProjects ``` This package is for our own usage only, it will never be published on nuget. It ends in our private repository. In the project, there is a file that is set to `generate action : content` and `copy local : always`. (My Visual Studio is in French, so I'm not 100% sure of the translation). Let's name it `importantfile.xml`. In the generated package, I end up with this structure : ``` - content - importantfile.xml - lib -net45 (.NetFramework,Version=v4.5) -MyCompany.MyProject.dll ``` Which is fine, I want `importantfile.xml` to be deployed in the package, because, well, this file is important! When I install the package in another project, `importantfile.xml` is deployed at the root of the project. That's OK. But it is not set to `copy local : always`. I need `importantfile.xml` to be `copy local : always` in this project where I install my package. How can I achieve that? Notes : I can set `copy local : always` on the file just after installing the package, that's no big deal. I would live with it if later updates of the package would let this property as-is, which is not the case. When updating the package, `copy local` is reset to `never` (as stated here). There's a nuspec file in the project's folder, here it is : ``` <?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> ```