Cake: MSBuild support for Visual Studio 2017 (aka "15")

Created on 22 Nov 2016  ยท  33Comments  ยท  Source: cake-build/cake

There are changes as to how msbuild is installed with Visual Studio 2017. The path is not predictable like previous versions.

See https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studio-15-setup/ for more info. Basically you'll need to make use of the Microsoft.VisualStudio.Setup.Configuration.Interop NuGet package to help locate where msbuild is located.

Feature

Most helpful comment

Just approved the Chocolatey package.

On 4 March 2017 at 19:20, Mattias Karlsson notifications@github.com wrote:

Excellent NuGet package now avail & Chocolatey package in moderation queue.

https://www.nuget.org/packages/vswhere

https://chocolatey.org/packages/vswhere

So a Cake alias would be neat ๐Ÿ˜‰
@phillipsj https://github.com/phillipsj if your up for it, raise an
issue and I'll assign it to you.

โ€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/cake-build/cake/issues/1369#issuecomment-284138025,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAXe6y8Cpv3PBxLWdAGTqce1-NgA-Ke1ks5riSXsgaJpZM4K4zke
.

All 33 comments

@flcdrg Good that you bring this up, but I'm not sure that we want to take this dependency in Cake since it's a Windows only tool and since we (so far) avoided dependencies in Cake.Common and Cake.Core (which made it super easy to port to .NET Core).

Maybe it would be better with a Cake addin for VS2017 that wraps/uses the underlying MSBuildRunner so it becomes opt-in for those who would want to use it.

Yeah, it's something that will need to be considered. A separate addin might make sense to isolate that dependency. Not sure how this plays out with cross-platform .NET Core-based MSBuild either.

Here's some sample code (pasted with permission from @jmarolf)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio.Setup.Configuration;

namespace LocateMSBuild
{
    public class Instance
    {

        private static ISetupConfiguration GetSetupConfiguration()
        {
            ISetupConfiguration setupConfiguration;

            try
            {
                setupConfiguration = new SetupConfiguration();
            }
            catch (COMException comException) when (comException.HResult == unchecked((int)0x80040154))
            {
                Console.WriteLine("COM registration is missing, Visual Studio may not be installed correctly");
                throw;
            }

            return setupConfiguration;
        }

        private static IEnumerable<ISetupInstance> EnumerateVisualStudioInstances()
        {
            var setupConfiguration = GetSetupConfiguration() as ISetupConfiguration2;

            var instanceEnumerator = setupConfiguration.EnumAllInstances();
            var instances = new ISetupInstance[3];

            var instancesFetched = 0;
            instanceEnumerator.Next(instances.Length, instances, out instancesFetched);

            if (instancesFetched == 0)
            {
                throw new Exception("There were no instances of Visual Studio 15.0 or later found.");
            }

            do
            {
                for (var index = 0; index < instancesFetched; index++)
                {
                    yield return instances[index];
                }

                instanceEnumerator.Next(instances.Length, instances, out instancesFetched);
            }
            while (instancesFetched != 0);
        }

        private static ISetupInstance LocateVisualStudioInstance(string vsProductVersion, HashSet<string> requiredPackageIds)
        {
            var instances = EnumerateVisualStudioInstances().Where((instance) => instance.GetInstallationVersion().StartsWith(vsProductVersion));

            var instanceFoundWithInvalidState = false;

            foreach (ISetupInstance2 instance in instances.OrderByDescending(i => i.GetInstallationVersion()))
            {
                var packages = instance.GetPackages()
                                        .Where((package) => requiredPackageIds.Contains(package.GetId()));

                if (packages.Count() != requiredPackageIds.Count)
                {
                    continue;
                }

                const InstanceState minimumRequiredState = InstanceState.Local | InstanceState.Registered;

                var state = instance.GetState();

                if ((state & minimumRequiredState) == minimumRequiredState)
                {
                    return instance;
                }

                Console.WriteLine($"An instance matching the specified requirements but had an invalid state. (State: {state})");
                instanceFoundWithInvalidState = true;
            }

            throw new Exception(instanceFoundWithInvalidState ?
                                "An instance matching the specified requirements was found but it was in an invalid state." :
                                "There were no instances of Visual Studio 15.0 or later found that match the specified requirements.");
        }

        public static string GetMsBuildInstallPath()
        {
            var instance = LocateVisualStudioInstance("15.0", new HashSet<string>(new[] { "Microsoft.Component.MSBuild" })) as ISetupInstance2;
            var installationPath = instance.GetInstallationPath();
            return Path.Combine(installationPath, "MSBuild", "15.0");
        }
    }
}

and consume this like so (PowerShell, but you get the idea)

function Locate-MsBuildInstallPath {
  $locateVsApi = Locate-LocateMsBuildApi
  Add-Type -path $locateVsApi
  $vsInstallPath = [LocateMSBuild.Instance]::GetMsBuildInstallPath()
  return Resolve-Path -path $vsInstallPath
}

@flcdrg Awesome with sample code ๐Ÿ‘

Another option we should consider is to only support the default installation path (when it comes to automagic MSBuild resolving) and let the user override MSBuildSettings.ToolPath if the location is something else.

Issue created in MSBuild repo to track this Microsoft/msbuild#1377

Using a combination of @flcdrg code and what is the examples MS provided, I made a wrapper around MSBuild for MSBuild15, https://github.com/phillipsj/Cake.MsBuild15, thoughts?

@phillipsj An approach we could take is to add everything we can in Cake.Common and point the tool location to the default location where it gets installed:

  • C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild15.0\Bin
  • C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild15.0\Bin

We could then have an extension to Cake that gets the proper tool location if it doesn't work (like the one you've written).

MSBuild("./src/Cake.sln", new MSBuildSettings {
    ToolVersion = MSBuildToolVersion.VS2017,
    Configuration = "Release",
    ToolPath = ResolveMSBuild2017ToolPath()
});

@patriksvensson That sounds pretty good to me, so you want me to just wrap the interop assembly in an alias that can be used?

@phillipsj It's your addin, so I can't tell you what to do ๐Ÿ˜„. However, I think it would be valuable of having VS2017 support out of the box and this would be the best of two worlds (in my opinion).

@patriksvensson I will wrap it in an addin and then you can use it as you suggest. Do you have anyone doing the Cake side of it by adding enum? If not I will do it.

@phillipsj If you want to make the change, then it would be perfect :smile:

@patriksvensson Pull request submitted https://github.com/cake-build/cake/pull/1419

I think it will need some work, but wanted to get it up for you all to review.

Addressed by #1419

What are the plans to get this released? I could really use this right about now. Is there a way in Cake to download pre-release versions of Cake.Common?

Will this work with just MSBuild tools and not the full fat Visual Studio? (I'm not installing VS on my build agents).

image

  1. The default install directory is not the same as any of the VS2017 editions.
    C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin\MSBuild.exe
    C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe
  2. One can chose their own directory.

To get vs_BuildTools.exe go to https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=BuildTools&rel=15

@devlead I think this issue need to be re-opened.

You can always set the build tool path in the settings.

On Mar 2, 2017 12:41 PM, "Damian Hickey" notifications@github.com wrote:

[image: image]
https://cloud.githubusercontent.com/assets/57436/23519330/c55687bc-ff76-11e6-818e-34221367b20f.png

  1. The default install directory is not the same as any of the VS2017
    editions.
    C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\
    MSBuild15.0\Bin\MSBuild.exe
    C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
    MSBuild15.0\Bin\MSBuild.exe
  2. One can chose their own directory.

To get vs_BuildTools.exe go to https://www.visualstudio.com/
thank-you-downloading-visual-studio/?sku=BuildTools&rel=15

@devlead https://github.com/devlead I think this issue need to be
re-opened.

โ€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/cake-build/cake/issues/1369#issuecomment-283724693,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABfthf4L6O-TcqsL2juQYEZMc7RUqDjpks5rhv9XgaJpZM4K4zke
.

@RehanSaeed @damianh You all should be able to use this nuget package from myget with Cake 0.17 to handle it for now. https://github.com/phillipsj/Cake.MsBuild15/tree/develop

@damianh If you use the addin I created then it should find the build tools. I will submit a pull request and get it added to cake as a default location. As far as custom locations, you will need to either define it yourself in the tool settings or use the new addin I will be creating that uses the MS interop locater.

You can see the "build tools" directory is included https://github.com/Microsoft/vswhere/wiki/Examples

https://github.com/Microsoft/vssetup.powershell

Ah good stuff Jamie; thanks for posting!

On 2 Mar 2017 7:23 p.m., "Jamie Phillips" notifications@github.com wrote:

@damianh https://github.com/damianh If you use the addin I created then
it should find the build tools. I will submit a pull request and get it
added to cake as a default location. As far as custom locations, you will
need to either define it yourself in the tool settings or use the new addin
I will be creating that uses the MS interop locater.

You can see the "build tools" directory is included
https://github.com/Microsoft/vswhere/wiki/Examples

โ€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/cake-build/cake/issues/1369#issuecomment-283735979,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AADgXDAT71HBPCOMQFLqPe-w5kYnZweeks5rhwkGgaJpZM4K4zke
.

Just saw this post with another option for finding where 2017 is installed.
https://blogs.msdn.microsoft.com/heaths/2017/02/25/vswhere-available/

Get Outlook for iOS

On Fri, Mar 3, 2017 at 4:59 AM +1030, "Damian Hickey" notifications@github.com wrote:

Ah good stuff Jamie; thanks for posting!

On 2 Mar 2017 7:23 p.m., "Jamie Phillips" notifications@github.com wrote:

@damianh https://github.com/damianh If you use the addin I created then

it should find the build tools. I will submit a pull request and get it

added to cake as a default location. As far as custom locations, you will

need to either define it yourself in the tool settings or use the new addin

I will be creating that uses the MS interop locater.

>

You can see the "build tools" directory is included

https://github.com/Microsoft/vswhere/wiki/Examples

>

โ€”

You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub

https://github.com/cake-build/cake/issues/1369#issuecomment-283735979,

or mute the thread

https://github.com/notifications/unsubscribe-auth/AADgXDAT71HBPCOMQFLqPe-w5kYnZweeks5rhwkGgaJpZM4K4zke

.

>

โ€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

@flcdrg oh that wswhere tool looks like an excellent option for cake๐Ÿ‘

@devlead what would be the best way to integrate this tool into cake?

I've asked them to create a tools nuget package. https://github.com/Microsoft/vswhere/issues/21

@damianh superb ๐Ÿ‘

@damianh as It's a tool It's a soft dependency we could potentially introduce as an "wswhere" alias in Cake.Common.

@devlead You want me to open a new issue to add build tools to the OTB resolution? I am happy to add the Cake.Common alias if no one else is wants it.

It appears vswhere doesn't find the installed BuildTools MSBuild https://github.com/Microsoft/vswhere/issues/22

@damianh yet?๐Ÿ˜‰

If you are using the fluent style of configuring MSBuild, you don't seem to be able to set a custom tool path using an extension method.

Excellent NuGet package now avail & Chocolatey package in moderation queue.

https://www.nuget.org/packages/vswhere

https://chocolatey.org/packages/vswhere

So a Cake alias would be neat ๐Ÿ˜‰
@phillipsj if your up for it, raise an issue and I'll assign it to you.

Just approved the Chocolatey package.

On 4 March 2017 at 19:20, Mattias Karlsson notifications@github.com wrote:

Excellent NuGet package now avail & Chocolatey package in moderation queue.

https://www.nuget.org/packages/vswhere

https://chocolatey.org/packages/vswhere

So a Cake alias would be neat ๐Ÿ˜‰
@phillipsj https://github.com/phillipsj if your up for it, raise an
issue and I'll assign it to you.

โ€”
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/cake-build/cake/issues/1369#issuecomment-284138025,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAXe6y8Cpv3PBxLWdAGTqce1-NgA-Ke1ks5riSXsgaJpZM4K4zke
.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

coxp picture coxp  ยท  5Comments

jenaewhitmore picture jenaewhitmore  ยท  3Comments

islopma picture islopma  ยท  3Comments

gabrielweyer picture gabrielweyer  ยท  3Comments

gitfool picture gitfool  ยท  4Comments