I am creating nuget package which should contain also config file. Problem is that if I want to use csproj for nuget package definition, I don't know how to specify that config file should be copied and "copy to output directory" on file set when package is being installed.
https://learn.microsoft.com/en-us/nuget/guides/create-net-standard-packages-vs2017
Previously I used nuspec and for install.ps1.
Thanks
(https://learn.microsoft.com/en-us/nuget/guides/create-net-standard-packages-vs2017)
To include a file, you need to add / modify an update item for the file. If you have set "copy to output directory" to "preserve newest", you might already have one in the csproj file. To include this file into the resulting nuget package, you need to set the Pack="true" metadata:
<ItemGroup>
<None Update="config.txt" CopyToOutputDirectory="PreserveNewest" Pack="true" />
</ItemGroup>
Note that depending on your project type (=> web sdk or "normal" sdk is being used) you may see different item types (None, Content) for files.
Related
I have build NuGet package consisting of Razor Class Library (RCL) project at .net core 2.2. Once packed I see that it contains static assets that I have configured:
When I install package inside target project, assets refs are visible inside project structure:
But when I try to access them at runtime - i get 404:
https://localhost:44312/localizer-assets/lib/vue/vue.min.js
I see that those files are not "physically" placed inside wwwroot folder (they are iniside package folder).
Is there any way to serve those files? How this should be configured?
So far I have been using those approches:
https://www.learnrazorpages.com/advanced/razor-class-library
Can Razor Class Library pack static files (js, css etc) too?
They work fine when I directly reference RCL project, but when packed with NuGet and installed does not work any more.
They work fine when I directly reference RCL project, but when packed
with NuGet and installed does not work any more.
As far as l know, when you use nuget and choose PackageReference nuget management foramt, the files which targets to import into the main project are introduced into your main project as links(The corresponding files will not exist in the physical path of your solution , but will be linked to the corresponding file address in the %userprofile%\.nuget\xxx). It is the feature of PackageReference nuget management format.
Solution
To solve it, l think you can add a custom build target in the nuget project(Include MSBuild props and targets in a package). With it, you can copy the files from nuget package into the main project.
1.add a target file like .targets or .props(must be the same as the package id) into the \build folder(must be created under the project root directory) of the project. All of these are based on nuget packaging mechanism.
2.add these codes into the target file
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<SourceScriptFiles Include="$(MSBuildThisFileDirectory)..\content\xxxx(relative paths in the current project)" />
</ItemGroup>
<Target Name="CopyScriptsToProject" BeforeTargets="Build">
<Copy SourceFiles="#(SourceScriptFiles)" DestinationFolder="$(ProjectDir)\wwwroot\xxxx\"
/>
</Target>
</Project>
Use a target to copy the file #(SourceScriptFiles) into the main project.(The DestinationFolder is just the destination address).
3.If you use nuspec file to pack your package. You should also add these files under the files node in it.
<files>
<!-- Include everything in \build -->
<file src="build\**" target="build" />
<!-- Other files -->
<!-- ... -->
</files>
In addition, such operation is a pre-build event and when you install the package, you should build your project first and then you will find the file under the destination folder.
Besides, here is a good sample in the github and l hope it can give detailed information and steps.
Hope it could help you.
I have .NET452 project - lets call it Consumer.csproj that I want to consume nuget lets call it SharedTargets that contained some custom targets files (SharedTargets.targets) from msbuild.
I'm using PackageReference format and now (compared to what it used to be) nuget packages are being restored to shared folder (%userprofile%.nuget\packages), and I'm not sure if it is good idea to reference it via that (doesn't feel right).
Eg:
<PackageReference Include="SharedTargets">
<Version>1.0</Version>
</PackageReference>
<Import
Project="$(USERPROFILE)\.nuget\packages\SharedTargets\1.0\SharedTargets.targets"
/>
Also this works only in VS, running this from command line (msbuild) I'm getting chicken-egg problem:
Confirm that the path in the <Import> declaration is correct, and that
the file exists on disk.
Obviously since I need to restore nuget first before I can use it :)
So question:
is there some more elegant way how to resolve path to the nuget package inside project file
is there a way how to make msbuild succeed (i.e. restore packages before SharedTargets.target is imported)
You shouldn't try to manually import targets distributed via NuGet.
Put your .targets file inside a build subfolder inside the package and name it SharedTargets.targets (package id + .targets) and NuGet will automatically include the targets - for packages.config projects it will modify the project file on install and for PackageReference projects the targets will be imported by modifying an implicitly generated targets file in the obj\ directory.
I am having a problem with nuget (version 4.3.0.4406) and msbuild (version 15.3.409.57025). I am using VS2017 to create class library. Using the pack capability of VS2017 i can successfully create a nuget package (that i can install in another solution). Now i want to add an install.ps1 script to the package in the tools folder that runs when the nuget is installed.
In the csproj file i am specifying multiple target frameworks:
<TargetFrameworks>net45;net452</TargetFrameworks>
I cannot figure out how to do this. I've created a nuspec file using the nuget -spec command which generates a simple nuspec file. When i use the msbuild command with the /t:pack and /p:Nuspecfile=path.to.nuspec I get the following errors:
NuGet.Build.Tasks.Pack.targets(141,5): error : Value cannot be null or an empty string.
I have nuspec files from other projects (from VS2015 solutions) that work without problem, and the structure of the one i am using now is basically the same. Can anyone let me know whether i am trying something that cannot be done?
You can pack any item by updating its metadata in the csproj file:
<ItemGroup>
<None Update="install.ps1" CopyToOutputDirectory="PreserveNewest" Pack="true" PackagePath="\tools" />
</ItemGroup>
Note that the ps1 file is only run for projects using packages.config to reference the NuGet package and you should investigate alternative ways to accomplish what you are trying to do with the script as PackageReference is now more likely to be used instead.
I'm in the process of creating a web deployment package through an automatic build trigger on the server.
The package should take care of everything (including creation of a specific website, apppool, and the latest code) on any server desired.
I extracted manually a deploy package from a configured local IIS site, containing all information needed by MsDeploy to create the site, apppool, etc...
They are present in following files
archive.xml
parameters.xml
systeminfo.xml
The idea is now that I would create automatic a deploy package on the build server, that contains the new compiled code, but with the above xml files in the .zip package.
Right now, I'm building the application, after which I execute a PowerShell script that will manually overwrite the files in the .zip with the ones I have.
However, I know you can extend the Target file (with a .wpp.targets file in your project) to plug into the pipeline and modify things along the way.
Unfortunately I'm getting a little lost with the information I found.
I'd like to:
1) configure the creation of the deployment package to use my existing .xml files.
2) if that's not possible, overwrite the files with my own files after the package creation.
My goal is to have a full executable deploy package after the build is finished, so I won't need to PowerShell script anymore.
Any information that will point me closer to a solution or helps me to understand more clearly msbuild targets and/or webdeploy is very appreciated.
I managed doing this by extending the Package MsBuild target.
Adding a .wpp.targets file in the root of the web project with following content.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSBuild.ExtensionPack.4.0\MSBuild.ExtensionPack.tasks"/>
<PropertyGroup>
<DeployFilesDirectory>$(MSBuildProjectDirectory)\Deploy\</DeployFilesDirectory>
</PropertyGroup>
<PropertyGroup>
<OnAfterPackageUsingManifest>
$(OnAfterPackageUsingManifest);
CopyDeployFiles;
ReplaceSetParametersFile;
<!--ZipDeploymentFiles;-->
</OnAfterPackageUsingManifest>
</PropertyGroup>
<Target Name="CopyDeployFiles">
<Message Text="Copy Deploy Files"></Message>
<ItemGroup>
<Files Include="$(DeployFilesDirectory)*.xml" Exclude="$(DeployFilesDirectory)setParameters.xml"></Files>
</ItemGroup>
<MSBuild.ExtensionPack.Compression.Zip TaskAction="AddFiles"
CompressFiles="#(Files)"
ZipFileName="$(PackageFileName)"
RemoveRoot="$(DeployFilesDirectory)"/>
</Target>
<Target Name="ReplaceSetParametersFile" DependsOnTargets="GenerateSampleDeployScript">
<Message Text="Replace Default SetParameters File"></Message>
<Copy DestinationFiles="$(GenerateSampleParametersValueLocationDefault)"
SourceFiles="$(DeployFilesDirectory)setParameters.xml"></Copy>
</Target>
</Project>
The first target is executed after MsDeploy has created the package and will replace the .xml files within the .zip file. I'm using the MsBuild.ExtensionPack Zip support.
The second target is executed after the build has created the sample .cmd and setParameters files and will overwrite the setParameters.xml with my own as well.
It takes a while to understand the concepts of MsBuild targets etc, but once you understand it becomes indeed very powerful.
Creating the package is now as simple as just launching the MsBuild
msbuild "D:\Projects\MyWebProject.csproj" /T:Package /P:Configuration=Release;Platform="AnyCPU";PackageLocation="D:\DeployPackage\package.zip";PublishProfile=MyProfile
And deploying is the same as before
package.deploy.cmd /Y –setParamFile :myParameterFile.xml
Assuming your paths stay the same, you can achieve this by specifying the existing zip as your -dest:package=package.zip. MSDeploy will automatically overwrite the files inside the zip.
Using msbuild in .NET 4.0, I can build web project with the "Package" target, and it does a nice job of putting the package in a zip file. But, when I look at the web.config in there, it's not transformed, it has "$(ReplacableToken_Web_SiteConnection-Web.config Connection String_0)"
I can run the "TransformWebConfig" target and it will do the proper transform, but just in its own silo.
I can also run the "Build" target and pass the "DeployOnBuild=True;DeployTarget=MSDeployPublish" properties and it will deploy the package on my server with the proper web.config transform done.
But, if I want to manually deploy the package to the server, how do I do a "Package" with a "TransformWebConfig" so that the zip file has the final web.config in there?
If you want to skip this from happening then you need to set a property in your build. You can do this in two ways
Edit your project file
Create a .wpp.targets file
I would recommend #2. For this case create a new file in the same directory as your project file with the name {ProjectName}.wpp.targets where {ProjectName} is the name of your project. Then inside of this file you should place the following contents.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
ToolsVersion="4.0">
<PropertyGroup>
<AutoParameterizationWebConfigConnectionStrings>false</AutoParameterizationWebConfigConnectionStrings>
</PropertyGroup>
</Project>
In this case you are setting the property AutoParameterizationWebConfigConnectionStrings which tells the Web Publishing Pipeline to not insert those {} placeholders in the web.config for the connection strings.
The way we do this is by modifiying the project build to do the transform prior to packaging it up.
The Target is call TransformXml and is a part of Microsoft.Web.Publishing.Tasks.dll
In your own targets its
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
But it will be included in a default VS C# build.
So
<TransformXml Source="web.config" Transform="web.release.config" Destination="$(DeployPath)\web.config" />
Does the trick for us.
Set up those paths with the right ItemGroup ("content" most likely) and make sure that target gets fired prior to the call to Package in your .csproj, and the build output will contain a "Web.config" like normal, with the right transformed values.
Alternatively (we've used this for packages that need to be everything to everyone), you can use that trick to do ALL the transforms and include each of them in the final package.
Then you call Msdeploy manually and use its skip and replace directives (forgot the technical term) to only output the right one at deploy-time
Assuming you have a web.usethisone.config in your package, that looks like
-skip:objectname=filepath,absolutepath=web\..*\.config
-replace:objectName=filepath,match=.*web\.usethisone\.config,replace=web.config