NAnt MSBuild Version - visual-studio-2010

Where is the configuration setting in nant that sets which version of MSBuild to use?
Nant wants to use 3.5 when it needs to use 4.0.

I wrote a blog entry a few years ago that explains how to leverage any version of MSBuild from your NAnt build script. Essentially, you would be using the <exec> node to make the call to MSBuild as it is installed on your computer.
http://enterpriseyness.com/2009/12/continuous-integration-with-cruise-control-net-nant/
<target name=”build”>
<exec program=”${MSBuildPath}”>
<arg line=’”${SolutionFile}”‘ />
<arg line=”/property:Configuration=${SolutionConfiguration}” />
<arg value=”/target:Rebuild” />
<arg value=”/verbosity:normal” />
<arg value=”/nologo” />
<arg line=’/logger:”C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll”‘/>
</exec>
</target>

You can also create a NAnt framework configuration. If you edit the NAnt.exe.config file make a duplicate of one of the <framework> elements with all it's children. Change the frameworkdirectory to use the version number of MSBuild you want to use. You can look at the other <framework> elements for the correct usage. For example if you wanted to have the 'net-3.5' <framework> element use MSBuild 4.0 just change the duplicated <framework> open element to look like:
<framework
name="net-3.5-msbuild-4.0"
family="net"
version="3.5"
description="Microsoft .NET Framework 3.5 with MSBuild 4.0"
sdkdirectory="${sdkInstallRoot}"
frameworkdirectory="${path::combine(installRoot, 'v4.0.30319')}"
frameworkassemblydirectory="${path::combine(installRoot, 'v2.0.50727')}"
clrversion="2.0.50727"
clrtype="Desktop"
vendor="Microsoft"
><!-- Rest of framework contents here --></framework>
Note the different version number in the frameworkdirectory attribute.
Then specify the framework you want to use in NAnt.
<property name="nant.settings.currentframework" value="net-3.5-msbuild-4.0" />

Related

How to see MsBuild output in Visual Studio in real time

I've added some additional targets to a .csproj file in order to carry out some additional tasks after the project build is completed.
Nothing appears in the Visual Studio output window until all targets have completed. I want to be able to see messages that occur as the targets are being processed.
If I use the MSBuild Task Explorer (a VS extension), I can see that the messages can be picked up by a Visual Studio window as they are generated, so am I just missing a setting somewhere?
I've also tried replacing the Exec tasks with SmartExec from the MSBuild Extensions package.
Here is a snippet from my .csproj project file:
<Target Name="PostBuildActions" AfterTargets="Build">
<!--Get the version number from the assembly info -->
<GetAssemblyIdentity AssemblyFiles="$(ProjectDir)$(OutputPath)$(TargetFileName)">
<Output TaskParameter="Assemblies" ItemName="ToolboxVersion" />
</GetAssemblyIdentity>
<CreateProperty Value="$(ProjectDir)$(OutputPath.TrimEnd('\'))">
<Output TaskParameter="Value" PropertyName="ToolboxTarget" />
</CreateProperty>
<!-- Run the Simulink Widget Generator tool -->
<CreateProperty Value=""$(SolutionDir)SimulinkWidgetGenerator\bin\$(Configuration)\SimulinkWidgetGenerator.exe" -v %(ToolboxVersion.Version) -d "$(ToolboxTarget)"">
<Output TaskParameter="Value" PropertyName="WidgetGenCommand" />
</CreateProperty>
<Message Text="Running Simulink Widget Generator:" Importance="High" />
<Message Text="$(WidgetGenCommand)" Importance="High" />
<Exec Command="$(WidgetGenCommand)" ConsoleToMSBuild="true" />
<!-- Invoke Matlab -->
<CreateProperty Value="try, PackageToolbox, catch ex, disp(getReport(ex)), exit(-1), end, exit(0);">
<Output TaskParameter="Value" PropertyName="MatlabScript" />
</CreateProperty>
<CreateProperty Value=""$(MATLAB_INSTALL_DIR)\bin\matlab.exe" -automation -wait -log -sd "$(ToolboxTarget)" -r "$(MatlabScript)"">
<Output TaskParameter="Value" PropertyName="MatlabCommand" />
</CreateProperty>
<Message Text="Invoking Matlab: " Importance="High" />
<Message Text="$(MatlabCommand)" Importance="High" />
<Exec Command="$(MatlabCommand)" ConsoleToMSBuild="true" />
In Visual Studio, you can config your MSBuild verbosity in Tools –> Options –> Projects and Solutions –> Build and Run.
From here:
Verbosity set to Quiet – shows either success or the build failure. 1 line displayed below for successful build.
Verbosity set to Minimal – shows the command line for the build. 2 lines displayed for successful rebuild.
Verbosity set to Normal. Shows the output from the MSBuild Targets. 25 lines displayed for successful rebuild.
Verbosity set to Detailed. Much more comments shown from MSBuild. 395 lines displayed for successful build.
And lastly, Verbosity set to Diagnostic, shows you everything. 1097 lines displayed for successful build.
For this issue, I recommend you use msbuild command like msbuild
xxx.csproj by developer command prompt to see the targets being processed.
So am I just missing a setting somewhere?
No, indeed you're right and for now, the output in Visual studio seems to not support for real-time display after my test.
Details to describe this situation:
As we know, there has two ways to build vs project:
1. Build in Visual Studio 2. Msbuild.exe.
Build process in VS(#1) actually calls the Msbuild tool(#2) to work.
Msbuild tool will display the target to a console window in real-time.
And in VS, the output of its build seems like a Non-real-time
log, which will display after the build process ends.If we add a Time-consuming operation like yours, it won't display until the command ends.
I've done a test for this, create a simple test.csproj, and add a script like this:
<Target Name="WaitingToDoSth" AfterTargets="Test1">
<Exec Command="$(ProjectDir)DoSth.exe"/>
</Target>
This DoSth.exe has a Thread.sleep(3000) in it. In VS, the output won't display anything until the DoSth.exe executes successfully and the entire build process ends.
When using msbuild xxx.csproj command in developer command prompt for VS2017, the display can be real-time and we can see messages that occur as the targets are being processed.
If my answer is helpful, please give a feedback. Thank you.
The key to seeing MSBuild output in realtime is to use the MSBuild project SDK. Many thanks to rainersigwald that posted this solution on GitHub:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>_5451</RootNamespace>
</PropertyGroup>
<Target Name="LogStuffInRealTime" BeforeTargets="CoreCompile">
<Exec Command="ping 127.0.0.1" YieldDuringToolExecution="True" ConsoleToMSBuild="true" StandardOutputImportance="high">
<Output TaskParameter="ConsoleOutput" ItemName="OutputOfExec" />
</Exec>
</Target>
</Project>

Is it possible to get Product Version in post build event?

I wish to copy MyDir (in my $ProjectDir) to $OutDir{ProductVersion} upon completion of a build.
Using the following configuration in csproj file I am able to get the File Version.
<Target Name="AfterBuild">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="AssemblyVersion" />
</GetAssemblyIdentity>
<Exec Command="robocopy $(ProjectDir)MyDir $(OutDir)/%(AssemblyVersion.Version) /E" IgnoreExitCode="true" />
</Target>
This however, retrieves the FileVersion and not the ProductVersion. Is there any way I can obtain the ProductVersion in post build event?
You're looking for Read AssemblyFileVersion from AssemblyInfo post-compile. You're going to need a custom task for this, since GetAssemblyIdentity doesn't return the productversion.
The linked question has the answer for AssemblyFileVersion, it shouldn't be too hard to adapt it to make it return the ProductVersion.

Visual Studio Express 2012 for Web - don't generate bin and obj folders

Can I turn off generating these folders on build? They contain some .dll, .pdb and other files I don't need. I'm just using Typescript compilation.
Yes, it is possible. I relied on the following nice overview on how to hijack a build process:
http://sedodream.com/2013/06/01/HijackingTheVisualStudioBuildProcess.aspx
Three main tricks:
1) project_name.csproj is the one you need to modify, it is XML MSBUILD file.
2) You cannot remove dependency from WebApplication.targets, you need to "deactivate" them as below.
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
3) You have to implement general contract for clean/build/rebuild targets.
Mine looks like:
<Target Name="Build">
<Exec Command="call node_modules\.bin\tsc.cmd src/main.ts --out js/game.min.js > $(Temp)\tscout.txt" IgnoreExitCode="true" WorkingDirectory="$(SolutionDir)" />
<Exec Command="type $(Temp)\tscout.txt" />
</Target>
<Target Name="Rebuild" DependsOnTargets="Clean;Build">
</Target>
<Target Name="Clean">
<RemoveDir Directories="js">
</RemoveDir>
</Target>
You could create a New WebSite instead of New Project. That one should not create any binary output.

Merging multiple jscript files into one with msbuild task?

I am using Microsoft Ajax Minifier to convert file1.js to file1.min.js. Now I would like to take file1.min.js and file2.min.js and merge them into files-merged.min.js.
I have found several open source msbuild projects but with no documentation on how to use them!
I am using Visual Studio 2010, is this something Ajax Minifier can do, if not do you have any tips on how to do it?
I want this to be an automated process, something done each time I build the solution.
Within MSBild solution you can use at the least three approaches.
Execute copy command (simply to understand and support, may affects
build performance in case of much calls perfomed);
Use ReadLinesFromFile/WriteLinesToFile msbuild tasks (simply enough, but resulting file will lose formatting)
Use .NET File.ReadAllText/WriteLinesToFile (good result, but may be complicated in some cases)
Executing copy command
To merge with copy command you should add something like this into your target:
<Exec Command="COPY /b file1.min.js + file2.min.js files-merged.min.js" />
In most cases it should be enough.
Using ReadLinesFromFile/WriteLinesToFile msbuild tasks
<ItemGroup>
<SourceFiles Include="file1.min.js;file2.min.js" />
</ItemGroup>
<ReadLinesFromFile File="%(SourceFiles.Identity)">
<Output TaskParameter="Lines" ItemName="FileLines" />
</ReadLinesFromFile>
<WriteLinesToFile File="files-merged.min.js" Lines="#(FileLines)" Overwrite="true" />
This example illustrates how to use native msbuild facilities to merge both files. Unfortunately, in that case we're loosing file formatting.
Using .NET File.ReadAllText() and msbuild WriteLinesToFile
<ItemGroup>
<SourceFiles Include="arrays.cmd;cp.cmd" />
<FileLines Include="$([System.IO.File]::ReadAllText(%(SourceFiles.Identity)))" />
</ItemGroup>
<WriteLinesToFile File="test.out" Lines="#(FileLines)" Overwrite="true" />
This approach fast and accurate, but uses some kind of .NET injection.
I did it by following this article:
http://encosia.com/2009/05/20/automatically-minify-and-combine-javascript-in-visual-studio/
I would prefer not to use the JSMin tool as I already have AJAX Minifier so I use JSMin just to merge the files. Can Minifier handle the merging of files?
C:\Progra~1\Microsoft\Micros~1\AjaxMin.exe js1.js js2.js -o jscombine.js -clobber

Publish ClickOnce from the command line

Is there a way to have Visual Studio 2008 execute the "Publish Now" button from the command line?
I've seen posts that suggest to use msbuild /target:publish to call it. That is OK, but MSBuild doesn't increment the revision number. I'm hoping for something like:
devenv mysolution.sln /publish
To increment build numbers, I am using MSBuild Extension pack inside my .csproj file as follows:
<Target Name="BeforeBuild" Condition=" '$(Configuration)|$(Platform)' == 'Release-VersionIncrement|AnyCPU' ">
<CallTarget Targets="CleanAppBinFolder" />
<MSBuild.ExtensionPack.VisualStudio.TfsSource TaskAction="Checkout" ItemCol="#(AssemblyInfoFiles)" WorkingDirectory="C:\inetpub\wwwroot\MySolution" ContinueOnError="true" />
<!-- Microsoft's task that goes over assembly files and increments revision number. -->
<MSBuild.ExtensionPack.Framework.AssemblyInfo Condition="'$(Optimize)'=='True' " AssemblyInfoFiles="#(AssemblyInfoFiles)" AssemblyRevisionType="AutoIncrement" AssemblyFileRevisionType="AutoIncrement">
<Output TaskParameter="MaxAssemblyVersion" PropertyName="MaxAssemblyVersion" />
</MSBuild.ExtensionPack.Framework.AssemblyInfo>
<Message Text="----current version---: '$(MaxAssemblyVersion)'" />
</Target>
This way, anytime the configuration is set to Release-VersionIncrement, the version number is changed. When this is done, I can use the following MSBuild command to publish it:
msbuild c:\projects\MyProject.csproj
/t:ResolveReferences;_CopyWebApplication
/p:Configuration=Release;BuildingProject=true;WebProjectOutputDir=c:\inetpub\wwwroot\OutputProject\MyProjectOutput;OutDir=c:\inetpub\wwwroot\OutputProject\MyProjectOutput
Note that this is for an ASP.NET 3.5 web application.

Resources