How can I retrieve major/minor/build/revision number on build events - visual-studio

Hy there!
I'm using this piece of code, to copy some files on post-build-event:
<PropertyGroup>
<DemoPath1>..\demoPath1</DemoPath1>
</PropertyGroup>
<Target Name="AfterBuild">
<Exec Command="robocopy $(ProjectDir)$(DemoPath1) $(ProjectDir)demoPath2/$(Revision) * /XD .svn _svn /XF *.cs /S" IgnoreExitCode="true" />
</Target>
As you can see, I would like to use $(Revision) - obviously, this is not going to work ...
Can anybody help me out?
#mods: I dunno exactly which tag to use ... on the one hand it's msbuild, on the other one visual studio ...? feel free to edit!

The easiest way is:
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="AssemblyVersion" />
</GetAssemblyIdentity>
and I've used it this way:
<Exec Command="robocopy $(ProjectDir)$(SomeProperty) $(ProjectDir)somePath/%(AssemblyVersion.Version) * /S" IgnoreExitCode="true" />

You left out of your question where you want to get the version number from. However you get it, all you need to do is populate the $(Revision) property yourself. Give a little more detail and I can probably help you out.

Related

Limit custom MSBuild target to the file(s) selected in Visual Studio

I have a small custom MSBuild target:
<ItemGroup>
<Foo Include="file1.foo"/>
<Foo Include="file2.foo"/>
<Foo Include="file3.foo"/>
...
</ItemGroup>
<Target Name="Foo2Bar" Inputs="foo.config;#(Foo)" Outputs="%(Foo.Filename).bar">
<Exec Command="path\to\script #(Foo) -o %(Foo.Filename).bar"/>
</Target>
Now I want to be able to to select one of the *.foo-files in Visual Studio and trigger processing just this one (e.g. by pressing CtrlF7 or right clicking in the Solution Explorer -> Compile). It seems that this sets a property $(SelectedFiles), but I don't find any usable tutorial or example how to make this work...
Limit custom MSBuild target to the file(s) selected in Visual Studio
If I understand you correctly, you want to select one of *.foo file to the target, if yes, you can pass the list around as a property, so we need to convert item into a property:
<Target Name="BuildMigrationZip">
<PropertyGroup>
<FooProperty>#(Foo)</FooProperty>
</PropertyGroup>
<MSBuild Projects="$(MSBuildThisFile)" Targets="Foo2Bar"
Properties="FilesToFoo=$(FooProperty)" />
</Target>
Then when we build the this file with MSBuild command line, we could pass the property FooProperty:
msbuild.exe "YourCustomTargetFile" /p:FooProperty=file1.foo
You can check this thread for some more details info.
If I understand you incorrect, please let me know for free, I will keep follow ASAP.
Hope this helps.

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.

Adding A Version To Post-Build Event In WiX

I'm new to WiX and having some trouble achieving what I think should be really simple. I'm using WiX v3.8 in Visual Studio 2013. Overall what I'm trying to accomplish is having one place where I can change the version of the installer and this will be propagated throughout the WiX project.
In the project properties of the WiX project => Build tab => "Define preprocessor variables" textbox I have:
ProjectVersion=3.6.7.0
However, where i run into problems is in the Post-Build Events when this fails:
copy !(TargetPath) "C:\Development\Release Builds\MyProject\$(TargetName) $(var.ProjectVersion)$(TargetExt)"
I've been scouring the internet, but unable to find a solution to my problem. Maybe I just don't know what to ask?
My question is: How can I make this post-build event work? What am I doing wrong? All I want to do is be able to do is easily change the ProjectVersion variable or another such variable in the post-build event.
This isn't exactly what you are asking for, but maybe it can help you achieve what you want?
I do it slightly different than your approach. I read the version from my 'main' assembly bundled with the wix installer, renames the msi filename to contain the version string, and sign it afterwards in a post-build event.
Resources:
https://stackoverflow.com/a/19371257/767926
https://stackoverflow.com/a/12323770/767926
To rename the msi to contain the version in the filename (wixproj):
<Target Name="BeforeBuild">
<GetAssemblyIdentity AssemblyFiles="$(SolutionDir)'HARDCODED PATH'\bin\$(Configuration)\'HARDCODED NAME OF ASSEMBLY'">
<Output TaskParameter="Assemblies" ItemName="AssemblyVersions" />
</GetAssemblyIdentity>
<CreateProperty Value="$(OutputName).%(AssemblyVersions.Version)">
<Output TaskParameter="Value" PropertyName="TargetName" />
</CreateProperty>
<CreateProperty Value="$(TargetName)$(TargetExt)">
<Output TaskParameter="Value" PropertyName="TargetFileName" />
</CreateProperty>
<CreateProperty Value="$(TargetDir)$(TargetFileName)">
<Output TaskParameter="Value" PropertyName="TargetPath" />
</CreateProperty>
</Target>
To sign the msi after the renaming (wixproj):
<PropertyGroup>
<PostBuildEvent>"C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bin\signtool.exe" sign /sha1 'CERTIFICATEHASH' /v /t http://timestamp.verisign.com/scripts/timstamp.dll /d "DESCRIPTION" "$(ProjectDir)\bin\$(ConfigurationName)\'HARCODED PARTIAL MSI NAME'#(AssemblyVersions->'%(Version)').msi"</PostBuildEvent>
</PropertyGroup>
It's important to manually add/edit this post-build event in the wixproj file(use the editor), if you use the GUI it will mess up:
#(AssemblyVersions->'%(Version)')
Also, if you would like to sign your MSI's, make sure you add a description for the MSI, otherwise the UAC prompt will show a temporary filename. Resource: http://kentie.net/article/wixtipstricks/

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.

How to turn off caching of build definitions in Visual studio

In project file I import my own target file
<Import Project="Build\CopyDependencies.target" />
and later I call target from that target file
<CallTarget Targets="CopyDependencies" UseResultsCache="false" />
If I edit CopyDependencies.target file I have to reload whole solution and only then changes to CopyDependencies.target take effect. I believe it is some sort of build definitions caching in Visual Studio? If it is, maybe it can be turned off?
Thanks #KazR
Here is a smaller Solution that you can insert into your .csproj file
<Target Name="AfterBuild">
<PropertyGroup>
<TempProjectFile>Build.$([System.Guid]::NewGuid()).proj</TempProjectFile>
</PropertyGroup>
<Copy SourceFiles="Build.proj" DestinationFiles="$(TempProjectFile)" />
<MSBuild Projects="$(TempProjectFile)" />
<ItemGroup>
<TempProjectFiles Include="Build.????????-????-????-????-????????????.proj"/>
</ItemGroup>
<Delete Files="#(TempProjectFiles)" />
</Target>
Problem solved
I don't know how you would disable the VS cache, however I may have a workaround that would allow you to edit the build target without having to reload the solution.
You could use the MSBuild task in your proj file to call a wrapper target that copies your CopyDependencies.target file to CopyDependencies.[RandomNumber].target, then invokes your CopyDependencies target in the newly created file, and finally deletes it.
This would force VS to reload the target on each invocation as the filename is different.
Here's an example:
myProject.proj
Add this to the AfterBuild target:
<MSBuild Projects="Wrapper.target" Targets="MyWrappedTarget" UnloadProjectsOnCompletion="true"/>
Wrapper.target
Here we have the target that will - at build time - copy the real target file and invoke the desired build target within it (I've used an inline c# task which is only available in MSBuild 4.0):
<UsingTask TaskName="RandomNumber" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<Number ParameterType="System.Int32" Output="true"/>
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs">
<!-- CDATA -->
Random rndGenerator = new Random();
Number = rndGenerator.Next(Int32.MaxValue);
<!-- CDATA -->
</Code>
</Task>
</UsingTask>
<Target Name="MyWrappedTarget">
<Message Text="MyWrappedTarget target called"/>
<RandomNumber>
<Output TaskParameter="Number" PropertyName="FileNumber"/>
</RandomNumber>
<PropertyGroup>
<CopiedTarget>inner.test.$(FileNumber).target</CopiedTarget>
</PropertyGroup>
<Copy SourceFiles="inner.test.target" DestinationFiles="$(CopiedTarget)"/>
<MSBuild Projects="$(CopiedTarget)" Targets="_innerTestTarget"/>
<Delete Files="$(CopiedTarget)"/>
</Target>
inner.test.target
This contains the real build target you want to execute, in this example it's a simple file copy.
<Target Name="_innerTestTarget">
<Message Text="This is a inner test text message"/>
<Copy SourceFiles="x.txt" DestinationFiles="x1.txt"/>
</Target>
This isn't production ready, but hopefully illustrates my point.
With this (slightly convoluted) process in place, you can change the inner.test.target file without having to reload the solution in VS.
Here's a solution that doesn't require any MSBuild scripting at all.
I noticed that unloading and reloading a project doesn't get around the cache, but closing and reopening the solution does. In addition, Visual Studio will prompt you to reload the solution if it notices the .sln file has changed. And finally, this superuser question explains how to touch a file in Windows.
Putting these together, I added a Visual Studio external tool to touch the current solution file. Here's how:
Select TOOLS > External Tools ...
Click the Add button to add a new tool.
Set properties as follows:
Title: Reload Solution
Command: cmd.exe
Arguments: /c copy "$(SolutionFileName)"+>nul
Initial directory: $(SolutionDir)
and turn on Use Output window
Click OK to close the External Tools window
Now if you have made changes to your MSBuild files, just select TOOLS > Reload Solution and all your build files will be reloaded.
I'm using Windows 7 64-bit and Visual Studio 2012 Express for Windows Desktop.
I have a different solution, not involving temporary files:
Include.targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Foobar">
<Copy SourceFiles="test.source" DestinationFiles="testFoobar.dest" />
</Target>
</Project>
Project file:
....
<Target Name="BeforeBuild">
<Exec Command="$(MSBuildToolsPath)\MSBuild.exe Include.targets /t:Foobar" ContinueOnError="false" />
</Target>
....
in this case VS does not recognize the MSBuild command, and does not cache the file.
happy coding!
Before running MSBuild I run this to clear the download cache:
call "%VS120COMNTOOLS%vsvars32.bat"
echo Clear download cache
gacutil -cdl

Resources