Running Paraffin when building a wixproj - wix

I've got a WiX project which pulls in a WiX Fragment with a load of supporting files.
I'm using Paraffin to build the wsx file for the fragment. At the moment I manually run a one line batch file to run with paraffin with the appropriate arguments whenever I make a change the supporting files folder.
Instead I would like paraffin to run as part of the build process. I'm guessing I need to add something to inside the .wixproj file, but I'm not actually sure what.
How do I do this?

Found a solution:
<Target Name="BeforeBuild">
<Exec Command="paraffin -dir SourceDir -groupname MyGroupId -dirref MyDirId output.wxs"/>
</Target>

Related

How to dynamically load properties from a file in MSBuild

I'm scripting my build process, and I'd like to have a single MSBuild script that clones a repo, then includes properties in a file in that repo to drive the build. The only way I've found to include properties from another file is with the Import task, which can't reside inside a Target, so the file it's importing has to exist when MSBuild is initially invoked. Is there any way to run the Import after a target has run, or another way altogether to get properties out of a file in the middle of a build?
You have to call "msbuild" task to run another msbuild process for same project with specific params (path to .props file for example).
<Target Name="Default">
<MSBuild
Projects="$(MSBuildThisFileFullPath)"
Properties="ParamsPath='./ParamsPath/name.props"
Targets="DoSomethingTarget"/>
</Target>
<Import Project=$(ParamsPath) Condition="Exists('$(ParamsPath)')"/>
<Target Name="DoSomethingTarget">
<DoSomeThingTasks/>
</Target>
But Im sure that "the right tool for right the job". Maybe you should look at solutions such as FAKE, PSake, Cake?
I decided to make two separate calls to my script in the BAT script that invokes it. The first calls my Clone task, which creates the properties file. The second calls the tasks that require those properties. I made sure the <Import> task has a conditional requiring the file to exist. I'm still open to a cleaner approach, but this works.

How to change msbuild working directory in TFS 2013 workflow

I have a TFS 2013 build xaml workflow, that eventually calls the Microsoft.TeamFoundation.Build.Workflow.Activities.MSBuild activity once for each solution that I want to build. When msbuild.exe is called, it's working directory is the working directory of the current solution being built. I can see this through the 'MSBuildStartupDirectory' property when running msbuild with a 'diagnostic' verbosity.
Unfortunately, I need the working of msbuild.exe to be somewhere else when msbuild.exe starts. This is because I use the MSBuild SonarQube runner that imposes constraints on the directory from which msbuild is called.
I have looked at the 'msbuild' activity and there is no way to control the working directory. Is there another way to control the working directory of this activity?
Its been a while since I edited a build process template but I believe you could use an activity that just executes a command in CMD and provide the full MSBuild command. I'm sure there are tons of variables you will need to setup for this to work.
Instead of editing the build process template have you considered using a PowerShell script in the Post-build script to execute SonarQube?
I still haven't found any way to control the working directory of msbuild. But since I know that the working directory will be the directory of the project being built by msbuild, I created a new proj file at the root of my workspace (where my working directory has to be) and only build this new proj file from my workflow. This new proj file then builds all my other solutions. That way, my working directory is the same for all the solutions being built.
Here is an example of my top level proj file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<ItemGroup>
<Solutions Include="**\*.sln"/>
</ItemGroup>
<Target Name="Build">
<MSBuild Projects="#(Solutions)" Targets="Build"/>
</Target>
</Project>
But beware that doing this may affect the output directory (OutDir) given to each solution. So you may want to do something like this:
<MSBuild Projects="#(Solutions)" Targets="Build" Properties="OutDir=$(OutDir)..\%(Solutions.Filename)"/>

WiX Heat: Pre-build event fires too early on build server

I'm harvesting a directory for my Visual Studio solution.
It works on my local system so far probably because the project build order is being respected.
When I run the installer on a build server it finds the right directory but it has not been created at the time of building the setup file. It throws a HEAT5052 error saying The directory 'a:\b\c' could not be found.
Is there any way to "wait" until or to execute the heat command after all project references are built?
OK so I've spent hours to figure out how to fire Heat AFTER all references are resloved. I only found solutions for the <PreBuildEvent> and <PostBuildEvent> using the Heat command line and the BeforeBuild and AfterBuild targets.
So I found all kind of targets inside the wix2010.targets file located in my
Program files (x86)\MSBuild\Microsoft\Wix\ folder. It contains a target called AfterResolveReferences and it does exactly that. So here's my code I ended up with (in case someone is interested):
<Target Name="AfterResolveReferences">
<HeatDirectory
ToolPath="$(WixToolPath)"
OutputFile="Product.Binaries.wxs"
SuppressFragments="$(HarvestDirectorySuppressFragments)"
Transforms="Filter.xslt"
Directory="$(HarvestFolder)"
DirectoryRefId="MY_FOLDER"
ComponentGroupName="Binaries"
GenerateGuidsNow="true"
SuppressRootDirectory="true"
SuppressRegistry="true"
PreprocessorVariable="var.App.TargetDir">
</HeatDirectory>
</Target>
I had the same problem and it was solved by combining the accepted answer and this answer to ensure that my post build event, which was copying files, always runs:
<RunPostBuildEvent>Always</RunPostBuildEvent>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
Also, my build server was using the MSBuild command line, and I used this answer to locate my local MSBuild.exe so I could test my changes locally without having to push to the build server.

Modify files after deployment package is created

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.

How make MSBuild build custom target specified in csproj building sln?

I am facing an issue with MSBuild I can't overcome it by myself. As a result I rely on community's wisdom.
The real situation I'm having troubles with
I have a soluiton file containing several projects with dependencies to other projects in same solution. I'd like to append a custom target to one of the project's csproj file and build it from the command line. It will allow me to make all the necessary output binaries for this project for further processing during the building of the custom target. But the main thing is that I can't figure out how to do it, googling doesn't help either.
Simplification
To make thing simplier I decided to make a new C# console project, add a simple custom target to the project's file and try to make it build. Still no success! Here what I've done so far:
Created a solution app with a default console project coreapp. This gaves me at least two files:
app.sln
coreapp\coreapp.csproj
Modified coreapp.csproj with addition of my custom target inside of the Project tag
<Target Name="SampleTarget">
<Message Text="This is a SampleTarget" />
</Target>
Run on the command line the following command
%windir%\Microsoft.NET\framework\v3.5\msbuild.exe app.sln /t:coreapp:SampleTarget
or even
%windir%\Microsoft.NET\framework\v3.5\msbuild.exe app.sln /t:coreapp.csproj:SampleTarget
Results
No luck, facing the error
MSB4057: The target "coreapp.csproj:SampleTarget" does not exist in the project.
I suspect that MSBuild thinks somehting fundamentally different from what I want it to think...
BEsides that, I also tried to set on the same command line the environment variable MSBuildEmitSolution=1 to force msbuild dump a temporary solution file it creates while processing the solution. In this file, indeed, no such target. However I guess it isn't the reason because I asked msbuild to build coreapp.proj where target SampleTarget really resides.
The question is how to build SampleTarget in this simplified scenario using solution file since potencially it can contain dependencies for the project containing this SampleTarget target?
I'd be greatful for any sort of help or firection for further investigation!
Instead of inserting a custom target in your project file, you could try creating a new standalone msbuild file, which would:
build the solution file (which builds projects)
defines your extra target
Call it app-custom-Debug.msbuild , for example.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WorkingFolder>$(MSBuildProjectDirectory)</WorkingFolder>
<Configuration>Debug</Configuration>
<SolutionFile>app.sln</SolutionFile>
</PropertyGroup>
<Target Name="Build" DependsOnTargets="Compile" />
<Target Name="Compile">
<Message Text="=== COMPILING $(Configuration) configuration ===" />
<MSBuild Projects="$(SolutionFile)"
Properties="Configuration=$(Configuration)" />
</Target>
<Target Name="SampleTarget">
<Message Text="This is a SampleTarget" />
</Target>
</Project>
Then you execute:
msbuild.exe app-custom-Debug.msbuild /t:SampleTarget
One option is to tie your SampleTarget to the standard Build targets via overriding the appropriate DependsOn property. In this case you could tell BeforeBuild that it DependsOn SampleTarget or you do the same thing with AfterBuild. This will ensure that MSBuild processes your target prior to the standard target indicated.