Post-Build event msbuild. Rename file at end of successful build - visual-studio

I don't know MSbuild scripting and don't have time to learn it right now. I need a method at the end of successful build to rename a dacpac file to include the version that is currently being built.
Example: (TfsDropLocation)\filename.dapac to (TfsDropLocation\filename.1.0.0.0.dacpac)
Is there a way to do this?

Is there a way to do this?
The answer is yes. If you don't mind editing the Visual Studio project file, then there is a simple solution that allows you to use a macro which looks like this:#(VersionNumber):
To accomplish this, unload your project. Then at the very end of the project, just before the end-tag, place below scripts:
<PropertyGroup>
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
PostBuildMacros;
</PostBuildEventDependsOn>
</PropertyGroup>
<Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="Targets" />
</GetAssemblyIdentity>
<ItemGroup>
<VersionNumber Include="#(Targets->'%(Version)')"/>
</ItemGroup>
</Target>
Now as promised, the assembly version is available to your post build event with this macro. So you add rename the file name by copy task in the post-build event with below command line:
copy /Y "(TfsDropLocation)\filename.dapac" "(TfsDropLocation)\filename.#(VersionNumber).dapac"
If you do not want to keep the previous filename.dapac, you can add a del command in the post-build event:
del "(TfsDropLocation)\filename.dapac"
Note: Do not ignore double quotation marks in the post-build event command line.
Then you can check you output and windows explorer, I used the file dll to test, you can check my test result:

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.

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/

Determine whether it's a build or rebuild in .cmd script called in prelink step inside Visual Studio

How can a .cmd script run from within a Visual Studio (2005, 2008, 2010, 2012 and 2013 respectively) project's pre-link stage determine whether this is a full rebuild (Build.RebuildSolution/Build.RebuildOnlyProject) or "ordinary" build (Build.BuildSolution/Build.BuildOnlyProject)?
This is an external script (LuaJIT, if you must know) and I don't want to rebuild the library every single build of the project. Instead I'd like to limit the complete rebuild to situations where I choose exactly that option.
How can a .cmd script run from within a Visual Studio (2005, 2008, 2010, 2012 and 2013 respectively) project's pre-link stage determine whether this is a full rebuild ... or "ordinary" build ... ?
I do not know if the exact thing that you are asking can be done - perhaps someone else knows how to do it. I will, however, suggest an alternate approach.
My approach is to remove the build of the Lua library from the pre-link step to a separate Visual Studio NMake project. If you create an NMake project, you will be able to know which type of build (build or rebuild) is occurring.
Note that later versions of Visual Studio simply refer to the project type as "Make". For discussion purposes here, I will refer to the project type as "NMake". I believe this is just a naming difference, and that the underlying build project remains the same between the two versions.
As a simple test, I created two Visual Studio applications: 1) an NMake project that calls a batch file to create a static library, and 2) a console application that consumes the library from step 1.
The NMake Project
In Visual Studio, if you create a new NMake project, you will see a dialog that allows you to provide MS-DOS commands:
As you can see, there are commands for: Build, Clean, Rebuild, and others. I don't have a screen shot of the above dialog with my commands, but here is my NMake project's properties:
My Build command just checks for the existence of the output file (lua.lib). If it does not exist, then it calls the rebuild.bat batch file. My Rebuild command always calls the batch file. My Clean command just deletes the output. I am not really sure what the Output command is used for, but I just filled in the path to the build output (lua.lib).
Now if you do a build, the lua.lib file will only be created if it is not there. If it is already there, nothing is done. If you do a rebuild, then a new lua.lib file is created.
The Console Application
In my console application, I added a reference to the NMake project - this way the NMake project is built prior to the console application. Here is the console application's reference page:
I also added the lua.lib file as an input during the application's link stage:
When the console application is built (during a build), it will build the NMake project if needed, and use the output (lua.lib) during the linker stage. When the console application is rebuilt (during a rebuild), it will also rebuild the NMake project.
Other Thoughts
My screen shots above only show the debug version of the properties. Your projects will have to account for the release version. There probably is a VS macro to handle this, but I am not sure since it has been ages since I've done anything with C/ C++.
In my testing above I use a single build batch file for both the build and rebuild. Obviously, you could do the same or you could use different batch files.
It may be a bit of a hack, but in .csproj file there are sections
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
You can set an variable from BeforeBuild and retrieve it from cmd script. Later on reset this variable in AfterBuild and you should be good to go.
Ok, this is going to be a long one.
First of all - do not take my code 'as is' - it is terrible one with lots of hacks, I had no idea msbuild is so broken by default (it seems at work I have access to waaaay more commands that make life easier). And another thing - it seems vcxproj is broken at some poin - I was not able to integrate the way I wanted with only BeforeRebuild and AfterRebuild targets - I had to redefine hole Rebuild target (it is located in C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets)
So, the idea is the following: when a Rebuild is happening we create an anchor. Then, during PreLink stage we execute cmd which is able to use created anchor. If the anchor is in place - we deal with Rebuild, if there is no anchor - it is a simple Build. After Rebuild is done - we delete the anchor.
modifications in vcxproj file:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
....
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
....
<PreLinkEventUseInBuild>true</PreLinkEventUseInBuild>
....
</PropertyGroup>
....
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
.....
<PreLinkEvent>
<Command>D:\PreLink\b.cmd</Command>
</PreLinkEvent>
.....
</ItemDefinitionGroup>
.....
<Target Name="BeforeRebuild">
<Exec Command="echo 2 > D:\PreLink\2.txt" />
</Target>
<Target Name="AfterRebuild">
<Exec Command="del D:\PreLink\2.txt" />
</Target>
<!-- This was copied from MS file -->
<PropertyGroup>
<_ProjectDefaultTargets Condition="'$(MSBuildProjectDefaultTargets)' != ''">$(MSBuildProjectDefaultTargets)</_ProjectDefaultTargets>
<_ProjectDefaultTargets Condition="'$(MSBuildProjectDefaultTargets)' == ''">Build</_ProjectDefaultTargets>
<RebuildDependsOn>
BeforeRebuild;
Clean;
$(_ProjectDefaultTargets);
AfterRebuild;
</RebuildDependsOn>
<RebuildDependsOn Condition=" '$(MSBuildProjectDefaultTargets)' == 'Rebuild' " >
BeforeRebuild;
Clean;
Build;
AfterRebuild;
</RebuildDependsOn>
</PropertyGroup>
<Target
Name="Rebuild"
Condition=" '$(_InvalidConfigurationWarning)' != 'true' "
DependsOnTargets="$(RebuildDependsOn)"
Returns="$(TargetPath)"/>
<!-- End of copy -->
</Project>
And the cmd looks like this:
if exist 2.txt (
echo Rebuild818181
) else (
echo Build12312312
)
The output from Output window:
1>Task "Exec" (TaskId:41)
1> Task Parameter:Command=D:\PreLink\b.cmd
1> :VCEnd (TaskId:41)
1> Build12312312 (TaskId:41)
Things to improve:
Use normal variables instead of external file (it seems MsBuild extension pack should do it)
Probably find a way to override only BeforeRebuild and AfterRebuild instead of the hole Rebuild part
It is much easier. Just add the following target to your build file or visual Studio Project
<Target Name="AfterRebuild">
<Message Text="AFTER REBUILD" Importance="High" />
<!--
Do whatever Needs to be done on Rebuild - as the message shows in VS Output
window it is only executed when an explicit rebuild is triggered
-->
</Target>
If you want a two step solution use this as a template:
<PropertyGroup>
<IsRebuild>false</IsRebuild>
</PropertyGroup>
<Target Name="BeforeRebuild">
<Message Text="BEFORE REBUILD" Importance="High" />
<PropertyGroup>
<IsRebuild>true</IsRebuild>
</PropertyGroup>
</Target>
<Target Name="BeforeBuild">
<Message Text="BEFORE BUILD: IsRebuild: $(IsRebuild)" Importance="High" />
</Target>

How to add a command line code generator to Visual Studio?

I'm working on a project that uses code generation to generate C# classes using a command line tool from a text-based description. We are going to start using these descriptions for javascript too.
Currently these classes are generated and then checked in, however, I would like to be able to make the code generate automatically so that any changes are propagated to both builds.
The step that is run manually is:
servicegen.exe -i:MyService.txt -o:MyService.cs
When I build I want MSBuild/VS to first generate the CS file then compile it. It is possible to do this using, by modifying the csproj, perhaps using a MSBuild Task with Exec, DependentUpon & AutoGen?
Normally I would recommend a pre-build command be placed in a pre-build event, but since your command line tool will be creating C# classes needed for compiling, this should be done in the BeforeBuild target in the .csproj file. The reason for this is because MSBuild looks for the files it needs to compile between the time BeforeBuild is called and the time when PreBuildEvent is called in the overall process (you can see this flow in the Microsoft.Common.targets file used by MSBuild).
Call the Exec task from within the BeforeBuild target to generate the files:
<Target Name="BeforeBuild">
<Exec Command="servicegen.exe -i:MyService.txt -o:MyService.cs" />
</Target>
See the Exec task MSDN documentation for more details about specifying different options for the Exec task.
Antlr has an example of a process that can be used to add generated code to a project. This has the advantage of showing the files that are generated nested under the source file, although it is more complex to add.
You need add an item group with the file to be generated from, for example:
<ItemGroup>
<ServiceDescription Include="MyService.txt"/>
</ItemGroup>
Then add the cs file to be generated to the ItemGroup containing the rest of the source code.
<ItemGroup>
...
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
...etc..
<Compile Include="MyService.txt.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>MyService.txt</DependentUpon> <!--note: this should be the file name of the source file, not the path-->
</Compile>
</ItemGroup>
And then finally add the build target to execute the code generation (using % to execute the command for each item in the ItemGroup). This could be put into a separate file, so that it can be included from many projects.
<Target Name="GenerateService">
<Exec Command="servicegen.exe -i:%(ServiceDescription.Identity) -o:%(ServiceDescription.Identity).cs" />
</Target>
<PropertyGroup>
<BuildDependsOn>GenerateService;$(BuildDependsOn)</BuildDependsOn>
</PropertyGroup>

Running FxCop directly through VS project file

I am interested in setting up FxCop to run on each of our VS .csproj files in our developing environment by calling it as a target in the .csproj file itself without creating a separate MSBuild file for the project. Is this
<Target Name="AfterBuild">
<Exec Command=""C:\Program Files\Microsoft FxCop\FxCopCmd.exe" /searchgac /p:FxCopProject.fxcop /out:FxCopOutput.xml" ContinueOnError="true">
</Exec>
</Target>
possible to get working in one way or another being included at the tail end of my .csproj file?
I think you're looking for the post-build event.
Right Click the Project
Click Properties
Go to the "Build Events" Tab
Add the command line to the "Post-build event command line" box.
The following should work - paste it anywhere at just under the node level:
<PropertyGroup>
<PostBuildEvent>"%25ProgramFiles%25\Microsoft FxCop 1.36\FxCopCmd.exe" /p:$(SolutionDir)Bank.FxCop /o:$(TargetDir)FxCopResults.xml /d:"%25ProgramFiles%25\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies"
</PropertyGroup>
Note the /d parameter I'm using to point to where my project is using additional assemblies (in this case, the MSTest unit testing stuff).

Resources