nuget package deploy with VisualStudio publish vs. msbuild publish - visual-studio

I'm trying to deploy a netstandard2.0 class library nuget to a local folder repository (specified in FolderProfile.pubxml). This works fine via VisualStudio's publish context action on a project: the process behind the scenes builds the project and packs desired items according to project.csproj and then copies the nuget package according to FolderProfile.pubxml. I've expected this could be achieved with msbuild as well (to be used in scripts).
msbuild /t:Publish /p:PublishProfile=FolderProfile.pubxml
This builds the project and copies content of bin/Debug/netstandard2.0 to the local folder repository. Unfortunately this differs from what was requested, the PublishProfile specifies Release configuration and project.csproj explicitly states just .dll to be packed (neither .deps.json nor .pdb)
msbuild /t:Pack
Packs the nuget content according to the project.csproj but it leaves the package in bin/Debug.
Switch to Release could be achieved via /p:Configuration=Release but that is still not enough to achieve the desired.
I've created simple a demonstration project, available at https://github.com/JanCervak/NugetPublishDifferenceRepro,
local folder repository is set to %TEMP%
Used VS 2019 16.8.3

The publish button of VS IDE for class library projects is msbuild -t:pack rather than msbuild -t:publish.
On VS IDE, when you click on the Publish button for lib projects, it actually does Pack button to create the nuget packages which reads from the pubxml file. It is the special feature of VS IDE and caused by the integrated tasks, tools from VS IDE. In other words, it is designed by that.
For different vs projects, Publish Button does different functions.
However, when you use msbuild -t:publish for lib projects from command line, which gets rid of the VS IDE environment, it does the function like the web projects, windows projects.(put the final output files into the custom publish folder).
So if you want to use commands which does the same function as VS IDE for lib projects, you should abandon the pubxml file and use this command:
msbuild NugetPublishDifferenceRepro.csproj -t:pack -p:Configuration=Release;Platform=AnyCPU;PackageOutputPath=%Temp%
PackageOutputPath is for pack target and specify the path of the generated nuget package.

Related

Post-build events of Visual Studio projects are not fired in TFS Build Definition

I'm new to Team Foundation Build. I've set the post-build events of all my C# projects in Visual Studio to copy the binaries to a physical directory. The command line in each project is:
xcopy "$(TargetDir)*.*" "$(SolutionDir)..\TempOutput\" /Y
The post-build events are fired and the files are copied when I build the solution in Visual Studio. But when building using TFS Build Definition, the events are not fired. Is there anything I need to set separately in my Build Definition to trigger all the projects' post-build events?
I have this in my TFSBuild.proj but still does not work:
<PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup>
To narrow down if the issue related to TFS build definition. You should manually remote to the build agent and run msbuild command to trigger the build instead of through TFS server.
Since you are using XAML build, take a look at below:
Team Build use a different directory layouts from Visual Studio
builds. All Binaries go in a single folder for any project built, so
references are automatically solved and it is easy to copy the DLL to
the final Drop folder.
You should use $(OutDir) MSBuild variable to properly reference the
binaries directory in VS and TFS builds. See
Is there a single MSBuild and TFSBuild variable that will point to where the binaries are?
for some details.

Where does Visual Studio is referring the actual NuGet referenced DLL?

I've added Autofac library using NuGet and I see it in my references as shown below.
But when I check the properties [F4] of Autofac by clicking on it, it shows empty property box in Visual Studio.
Also, I don't see Autofac folder under packages folder.
I see only Package reference in .csproj file. Then how does it locates the DLL? Where is the actual DLL? I see it's automatically coming inside BIN. How does it come?
Main Issue: Locally I'm able to build the solution but same solution fails on TFS build agents. It's unable to find the NuGet reference. So where can I find DLL references? or how to push it to TFS?
As #magicandre1981 already explained, with PackageReference style package referencing (as apposed to package.config-style, also see this for more background on the differences, in case you didn't know), the packages are not located in a per-solution packages-folder, but in a central one (by default %USERPROFILE%\.nuget\packages). Albeit you can easily change the location using the NUGET_PACKAGES environment variable (which also works as a TFS Build variable, because they are provided as environment variables to build steps).
Furthermore, inside Visual Studio you see no path, because the actual path to the DLL is determined at build time. You can see part of that path in your <project-dir>\obj\project.assets.json file (which is generated during the restore target/operation), but the full path you will only see in the MSBuild logs (for example when actually calling the csc.exe executable/C# compiler or during ResolveAssembyReferences-task).
Note that for .NET Core, i.e. "SDK style" projects, the path is actually shown in properties (as are the actual DLLs in a node underneath the "package" node.
One can only assume that the integration of PackageReference in "old" projects is not fully done yet (if ever).
For comparison a PackageReference in an "old" / non-SDK-style project:
You use the new Package Reference where the NuGet files get get stored into a cache:
Solution-local packages folders are no longer used – Packages are now
resolved against the user’s cache at %userdata%\.nuget, rather than
a solution specific packages folder. This makes PackageReference
perform faster and consume less disk space by using a shared folder of
packages on your workstation.
Assume you are using TFS 2015, the NuGet Restore task name should be NuGet Installer which under Package when you add tasks.
So, if you have installed Nuget in the build machine, then you can use the task directly.
You can also custom nuget.exe for TFS 2015 build -- Just specify the Path to NuGet.exe
You can refer to Mummy's blog- Custom nuget.exe for TFS 2015 build for details.
Add a NuGet Restore task to your build so that the packages are restored.

Integrate advanced installer Merge Module project with Visual studio

I have some merge module projects created using advanced installer. I need to integrate them with visual studio. I have done same for MSI projects and they work fine. but I don't know how to achieve continuous integration for MSM using Visual Studio.
Advanced Installer extension for Microsoft Visual Studio allows to create Advanced Installer Projects for Visual Studio. Each such project is a container that can include a single .AIP file.
The Visual Studio Solution can include one or more Advanced Installer Project for Visual Studio, in accordance with your needs.
Note that you need to remove the default project that is created when adding a new Installer Project to the .sln and add the existing project, the project that builds the .msm package.
edit
Indeed, you are right. It was a misunderstanding on our end.
On my machine I have several extensions installed side by side. One of these extensions also supports the build of a merge module project type.
We do not officially support this yet. The option to build other project types (e.g. Merge Module Project, Updates Configuration Project) with our VS extension will be available in a future version of Advanced Installer. I will let you know when we will add support for this.
Until then, you can use a build event as a workaround to build the Merge Module Project within the Visual Studio project.
To build the .msm project you can use a command line as described below:
http://www.advancedinstaller.com/user-guide/command-line.html#build-project
The command line can be something as below:
AdvancedInstaller.com" /build "$(SolutionDir)Merge module sample.aip"

How to "inject" NuGet package in Jenkins CI build job

So here is the case: We have a web application which can be deployed for different customers. The web application can be extended by different modules per customer. The modules are created as NuGet packages and contain the DLLs together with static files like e.g. HTML, CSS, JS, ASMX...
As not all customers use the same modules and the base web application shall be as sleek as possible, the web application project itself doesn't know anything about the modules. Instead a Jenkins build job is available for each customer. In this build job the packages.config file will be modified to add the NuGet package entry for the wanted module. Then we do a nuget.exe restore and a nuget.exe update (to ensure it's on the latest version) for the module NuGet package. After this we use msbuild and Octopack to build and deploy the web application.
All of this works great for the DLLs included in the modules NuGet package and for the web.config transformations (done via web.config.install.xdt), but unfortunately it doesn't work for the static files included in the modules NuGet package :(
I assume that this is the case due to the missing references in the web applications .csproj file!? So the static files are actually copied to the correct locations, but are not added to the final Octopack Nuget package as they are not recognized as project content.
As far as I have researched till now this is nothing we can solve using the NuGet CLI itself, but are there any other options maybe? The Package Manager Console is only available within the powershell context of Visual Studio, right? (Update-Package -Reinstall would be perfect I guess)
Any other ideas?
We found the following solution (Octopack to win!). Instead of relying solely on NuGet, we use an option provided by Octopack which is OctoPackEnforceAddingFiles=true. This tells Octopack to not only add the project files to the resulting NuGet package (as it would normally do), but on top of this add files/folders listed in the <files> section defined in a .nuspec file you added to the project. See: http://docs.octopusdeploy.com/display/OD/Using+OctoPack#UsingOctoPack-IncludingadditionalfilesusingaNuSpecfile(.nuspec)
So our base project only has the nuspec file with an empty <files> section. The module then includes XDT files to tranform the nuspec file on (un)install to configure the additional files/folders which shall be added by Octopack. This way they don't have to be part of the csproj file.
I would love to see this option to handle the <files> section as an inclusive list of additional files (instead of either csproj or files section) be added to the nuget cli as well.

Visual Studio copys .config file to bin on build, but MSBuild does not

I have a WebAPI project in Visual Studio 2013. If I build the project in Visual Studio, in the bin/ directory I see a file called MyProject.dll.config, which represents the web.config file at build time.
However, if I execute MSBuild from the command line, the .config file is missing, but all other files are present.
> msbuild.exe /t:build /v:q /p:Configuration=Debug /nologo \
D:\Workspace\MyProject\src\MyProject.sln
What gives? Why isn't the .config copied?
For deploying a web project or a web api project, the fact that there's no $(TargetName)$(TargetExt).config isn't a big deal. At run-time, IIS will use Web.config to figure out everything it needs for your assembly.
BUT!
If you're using a Web App or Web Api project as the basis for testing* then you can hit some snags. In particular, when it comes to assembly binding redirects (as is the case with something within the bowels of MVC which still relies on Newtonsoft.Json 4.5.0 when the current version at time of writing is 7.0.0). A colleague had a similar issue with another assembly his test project was depending on.
Now when you run your tests through Visual Studio (eg, via Resharper), they all work just fine. However, when your tests get to the CI server and they are run by nunit-console, you'll see assembly load errors. Not pretty. This is because of the described behaviour where VS is sneakily copying the .config file to the correct output and msbuild isn't. However, you can work around this with a post-build build event:
copy $(ProjectDir)Web.Config $(TargetDir)$(TargetName)$(TargetExt).config
This has resolved my issues with redirects. I hope it helps someone else.
You may ask "Why use a Web App or Web API project as your test project?". A Web* project is a lot more comfortable to deal with as a base for a test project which deals with .net assemblies and JavaScript tests as JavaScript is properly recognised (syntax highlighting) and there's a Scripts folder which has the quick "Add -> Javascript File" menu item for itself and descendant folders, so I prefer to use this instead of a plain Class Library project.
When I create a WebAPI project the web.config Copy to Output Directory is set to Do Not Copy by default. Did you select the Web.config in Solution Explorer and set this to a copy action?
I'm at a loss to explain why it seems to copy for you with the IDE build but NOT the msbuild cmd you show, this is not the behavior I see with a fresh WebAPI project in 2013.

Resources