Wix Nuget Packages - msbuild

So here's the scenario: I have several wix projects that the exact same extra msbuild targets and tasks to automate some very tedious tasks: things like building a help file and authenticode signing the msi and output files using signtool.exe.
Having gotten tired of copying changes to these scripts into 5 different repositories every time I made a fix. So I got clever and I turned them into nuget packages with a .targets file in the build folder. A simple nuget restore turns a laundry list of packages into targets files.
The problem
Wix v3 doesn't like packages. It doesn't support package references so packages.config looks like the thing. Except that visual studio doesn't like packages.config. It will happily restore the packages (into the folder I specified with a nuget.config) but none of the .targets files are automatically imported.
Easy enough to fix: I just added an import statement into my wixproj file. Except that visual studio doesn't automatically re-evaluate the wixproj after running the restore operation. We can work with this, but it is really annoying to have to build, unload the project, reload the project, and rebuild any time the packages change.
So I tried to fix it
I crawled through the log output of a standard C# project build and discovered the Nuget.Targets file, which can be imported into a project to provide pack and restore targets. It also let me convert to packagereferences, which are somewhat more convenient and less messy than packages.config, but I still had to manually add the import statement for the nuget.g.targets and nuget.g.props files that were produced by the restore target.
And, since I had to manually import those files, I'm right back to the build, unload, reload, rebuild workflow.
Attempt number 2
I discovered through intense internet searching that msbuild recently added a /restore flag to their command line utility specifically to force a project re-evaluation after restoring packages. This works on the command line, but visual studio seems to be clueless. (Maybe because of something that wix v3 does behind the scenes in the Visual Studio template?) In any case, they mentioned in the issue notes that they are essentially using an msbuild task with new global properties to force a re-evaluation. So I attempted to add such a step to the pre-build event of my wixproj, but no sauce.
The question
How do I tell visual studio to re-evaluate this wixproj after running restore? Is there some sort of property or item group I need to add to the wixproj? Is there some kind of target I can insert into the build process?
Update 1:
Found a project property that looked promising: UseHostCompilerIfAvailable, but it didn't work. Still got the same problem.

Related

VB.net .exe cannot be run from another computer. Missing assemblies for ClosedXML

I must put this program into production today, and I can't get it to run independently.
In the program, I have included NuGet package "Imports ClosedXML.Excel" and use it to create spreadsheets. When I build my executable, and try to run it from another computer, it cannot find the ClosedXML and Documentformat.OpenXml assemblies.
I checked in References that "Copy Local" was = True for ClosedXML and Documentformat.OpenXml, but it's not working. I found another website that mentioned Global Assembly Cache, and that if the dependency is in there, it will not be included in the Build .exe.
I am running Visual Studio Professional 2017. I am in over my head on this one, so if you have answer (and I hope you do), please try to provide it in elementary terms I can understand.
Sometimes issue is solved by individually adding application files inside the following menu
Go to Publish-->Application Files
Select Show all files
Under Publish Status
Set the files you need to Include [not include(auto)]

Error CNDL0199 : The Wix element has an incorrect namespace of 'http://schemas.microsoft.com/wix/2003/01/wi'

I migrated my WIX project from V2 to V4 and then changed the namespace in the .WXS files
I replaced the below namespace
<Wix xmlns="http://schemas.microsoft.com/wix/2003/01/wi">
with
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
Once the changes have been made when i run the build installer i am getting the below error:
error CNDL0199 : The Wix element has an incorrect namespace of
'http://schemas.microsoft.com/wix/2003/01/wi'. Please make the Wix element
look like the following: <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
E:\Code\EMR\Wix\src\EMR_Registry_entries.wx
I replaced the new namespace but it is not reflecting. Once i run the build installer it is setting with the old namespace. I tried multiple times but it is always setting the old namespace.
Please help me to resolve the issue.
UPDATE: Question that came up from a second read of your question.
Source Control: "Once I run the build installer it is setting with the old namespace." - are you sure the build process doesn't
auto-magically 1) check the WiX source out of your source control system? Or 2) maybe it is doing some XML manipulation via the automation script?
WiX Version: Are you sure you are compiling with WiX 4? Maybe you are compiling with WiX 2 or WiX 3 unintentionally? Try hard coding the full path to the WiX binary in your build system - if you have one. Please see this (Sean is a WiX developer): Migrate Wix Project to version 4.0. Frankly I am not sure how well WiX handles multiple-version installations on the same box combined with migrated sources (identically named binaries of different versions - WiX 2, 3, 4 - globally applicable via the PATH variable? Not sure).
Visual Studio / Cmd.exe?: Are you compiling with Visual Studio or via the command line? (I am not quite sure reading your question). Maybe try via the command line (towards bottom) if you are using Visual Studio - or vice versa. Make sure you use the correct WiX binaries (in other words WiX 4).
Linked Files?: I don't have any WiX 2 sources to migrate, but I am wondering if you have several source files that are interconnected. Was that even possible in WiX 2? I can't remember. In either case, I would make sure you have updated all WiX source files that are pulled in during the build process. Please read the log carefully. Maybe try to compile them with Candle.exe directly using the command line (cmd.exe instead of Visual Studio) to see if the file compiles OK.
Source Files?: If it still does not work, please put the source file online so we can have a peek. Github.com for example. A quick look at the source (the real McCoy) goes a long way sometimes - and sometimes it doesn't help at all. Maybe give it a go. Redacted sources are just fine - encouraged even. Please pay close attention to sensitive data: How do I avoid distributing sensitive information in my MSI by accident? (and this also goes for published source files - obviously - not just the compiled MSI and its helper files - such as silent installation template batch files).
In summary: That became a lot of babble. Maybe first try to compile the migrated WiX source with the right WiX 4 binaries to
determine if that works or not. Then work backwards to figure out what
happens during the build process.

Exclude folder when building from VSO to Azure website

I am trying to exclude certain files/folders from deployment of a web project in Visual Studio Online to an Azure website.
The web project has a Content folder with CSS, JS, build scripts and so on, which are only necessary for development, once deployed to Azure the CSS and JS is loaded from a CDN. Currently the build from VSO is copying all those files to the webroot in Azure, which is unnecessary and a potential security issue in case of the build scripts.
Now I know this can be prevented by setting the build action of a file to None, but this a very tedious solution because there is a lot of development going on, new files get added all the time and it is easy to forget this setting.
First I tried setting the Content folder to Cloaked in the build definitions source settings, but this only causes VSO to not download this folder on build, msbuild will still complain that those files are missing.
Is there a way to tell msbuild to ignore the whole Content folder? I already tried adding /p:ExcludeFoldersFromDeployment="Content" as a msbuild argument in the build definition, and also tried the solutions in here How to get Visual Studio 'Publish' functionality to include files from post build event?, but nothing is working.
I was studying msbuild log files and came up with a solution that is good enough for us to work with.
The first thing I learned was that I cannot prevent msbuild from copying files with build action Content to the output directory, at least not without changing the Microsoft.WebApplication.targets file, which I didn't want to do and am not even sure is possible with VSO build.
Anyway because of this we cannot set the source settings of our Content folder to Cloaked in the build definition, since this will cause the build to fail.
What we ended up doing was described in this answer: https://stackoverflow.com/a/3140349/1230302
So by adding the ExcludeFoldersFromDeployment statement to the .csproj file, the Content folder is excluded from the webroot.
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\</OutputPath>
<ExcludeFoldersFromDeployment>Content</ExcludeFoldersFromDeployment>
</PropertyGroup>
It is not an ideal solution, but at least this way nothing gets deployed if a developer forgets to set the build action to None.
The built in continuous delivery options are designed for convenience. Of you need something custom, like skipping deployment of files that have not changed, then you will need to write something yourself.
You can easily call PowerShell to complete any task from the build process.
If you'd like to customize your build as part of the VSO build system, you can just override your BuildTemplate.xaml file.
Visual Studio Build uses Windows Workflow (xaml) to make a workflow on what the build is supposed to do. You can edit this file and do any modifications to the directory structure before or after the build.
Here is an example.

TeamCity - Microsoft.Bcl.Build Dependency

I've just committed some code changes to my repository and all of a sudden (after weeks of being fine). The TC build starts failing as it fails to download the NuGet package for Microsoft.Bcl.Build.1.0.6.
I ended up having to manually copy the contents of the packages directory to the TC build location which utterly defeats the point of NuGet.
What can I check to get to the root cause of this?
Everything about NuGet is enabled in the solution for getting packages.
I've blogged about this issue at http://sedodream.com/2012/12/24/SlowCheetahBuildServerSupportUpdated.aspx. To summarize NuGet package restore (prior to 2.7) is implemented as a part of the MSBuild build process. When MSBuild starts a build it will evaluate the project file and any Import declarations importing other files. This happens before any target gets executed.
Since NuGet pkg restore is a part of the build process the .targets files get restored at a point in time that it is too late for the Import statement to have any impact.
You can work around this by either checking in the .targets file as you stated, or by invoking pkg restore before the build process. I've created a NuGet package, PackageRestore, which can help with the latter approach.
To use PackageRestore just add the NuGet package to your project which will automatically create a file named packageRestore.proj in your projects directory. When configuring your build, you will need to build that item before your .sln/.csproj file.
OK This is a bit of a nasty issue.
If you are having this problem you need to do something rather ugly to your repository.
Make sure you are checking in the packages\repositories.config file.
Then if your build is failing with unresolved references to Microsoft.Bcl.Build you will need to also checkin the .targets file for this package. eg:
package\Microsoft.Bcl.Build.x.x.x\tools\Microsoft.Bcl.Build.targets
Hideous ...
This blog post is the most thorough one I've seen for explaining the workaround options:
http://blogs.msdn.com/b/dotnet/archive/2013/06/12/nuget-package-restore-issues.aspx
None are great IMO - this problem still needs a better solution.
But for the time being, the best recommended option is to check the Bcl.Build .targets file into source control - which means when the version of Bcl.Build is updated, you'll need to add the new .targets file, and remove the old one.
I think (but am not sure, so I created this SO question: What does the Microsoft.Bcl.Build NuGet package do?) that Microsoft.Bcl.Build is only needed for development, and is not needed on a build server. So, I have a Builder.targets file that only exists in the build environment, that is indirectly <import> ed into all of our projects, which includes this bit of MSBuild xml:
<!-- Skip Microsoft.Bcl.Build functionality when building only from Source. Presumably Microsoft.BclBuild is only needed for development. -->
<PropertyGroup>
<BclBuildImported>Ignore</BclBuildImported>
</PropertyGroup>
Since the block of MSBuild logic inserted into your project by the Bcl.Build nuget package is dependent on the BclBuildImported property being empty, this effectively sidesteps the problem in my build environment - the Microsoft.Bcl.Build steps are skipped, and it no longer breaks my CI builds.
Note that since it appears that this package manages binding redirects in your app.config, and ensures that transitive dependencies are included in your projects, it's important to leave in for development. But I'm not currently aware of a need for it in a build server environment.

MSBuild overwriting dependencies

Ok, so I've got a somewhat complicated problem with my build environment that I'm trying to deal with.
I have a solution file that contains multiple C# projects which is built by a NAnt script calling MSBuild - passing MSBuild the name of the solution file and a path to copy the binaries to. This is because I want my automated build environment (CruiseControl.Net) to create a folder named after the revision of each build - this way I can easily go back to previous binaries for any reason.
So idealy I have a folder layout like this
c:\build\nightly\rev1
c:\build\nightly\rev2
c:\build\nightly\rev3
...
c:\build\nightly\rev10
etc.
The problem that's arisen is I recently added the latest version of the Unity IoC container to my project, checking it directly out of MS's online SVN repository. What's happening is I have a Silverlight 3 project that references the Silverlight version of Unity but I also have other projects (namely my Unit testing project) that reference the standard (non-Silverlight) version of Unity.
So what happens is since MSBuild is dumping everything into one single folder the Silverlight version of the Unity assembly is overwriting the non-Silverlight version because they have the exact same assembly file name.
Then when CruistControl runs my unit tests they fail because they don't have the proper dependencies available anymore (they try to load the Silverlight specific Unity assembly which obviously doesn't work).
So what I want to do is:
keep my desired output directory
structure (folder\revision)
I don't want to have to manually edit
every single proj file I have as this
is error prone when adding new
projects to the solution
Idealy I would like MSBuild to put everything into a folder structure similar to this:
nightly\revision1\project1
nightly\revision1\project2
nightly\revision1\project3
...
nightly\revision2\project1
nightly\revision2\project2
nightly\revision2\project3
etc
I can't modify the Unity project to give it a different file name because it comes from another SVN repository I cannot commit changes to. I found a similar question posted here and the suggested solution was to use a "master" MSBuild file that used a custom task to extract all the project file names out of the solution then loop over each one building them. I tried that but it doesn't build them in the order of their dependencies, so it fails for my project.
Help?
Firstly I would always have the build server delete the old working copy and check out a fresh copy to avoid any problems with stale artifacts from the previous build.
Next I would have nant or msbuild build the solutions as before with the artifacts from each build going to their local working output folders.
After that I'd move the artifacts from their working paths to their output paths, this shouldn't require digging through the project files since you can just tell msbuild/nant to copy working\project1\bin\release\**\*.* to artifacts\project1\.
The script that does this should ideally be stored along with the source with the main file, e.g. build.nant or build.proj in top level of the trunk.
For third party libraries I would simple include the DLLs directory in your repository. Nothing worse than writing some code and having a third party dependency break your build because of changes on their end.
Simply document the versions of the libraries you are using, and if you must update them, you'll have a better sense of what breaks the build before you even check it in.
Also, doesn't CC.Net automatically handle the providing of releases based on revision? I'm using TeamCity and it keeps a copy of the artifacts of every build.
I highly recommend reading JP Boodhoo's Automating Builds with NAnt blog series. That's been my starting point and have made lots of changes for my own taste. I also highly recommend checking out the builds of many open sources projects for examples. I've learned a lot from the builds of the Castle/Nhibernate/Rhino-Tools stack.