Создание программного проекта msbuild 15 программно
Я пытаюсь создать простой проект библиотеки классов С# 7, созданный с помощью VS2017.
MSBuild из сборки сборки устарел, поэтому я ссылаюсь на Microsoft.Build
, Microsoft.Build.Engine
и Microsoft.Build.Framework
из папки MSBuild в visual studio (C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin
).
Тем не менее, когда я это делаю:
using (var collection = new ProjectCollection())
{
var proj = collection.LoadProject(@"c:\projects\Sample\Sample.csproj"); // <-- exception
proj.Build(new[] {new ConsoleLogger()});
}
Я получаю InvalidProjectFileException: The tools version "15.0" is unrecognized. Available tools versions are "4.0", "2.0".
InvalidProjectFileException: The tools version "15.0" is unrecognized. Available tools versions are "4.0", "2.0".
Есть ли программный способ для вызова сборки с использованием новейших инструментов сборки и компилятора С# 7?
Ответы
Ответ 1
У меня были аналогичные потребности для моей команды, и я написал библиотеку Builder для С#, которая поддерживает несколько версий Visual Studio. Я не мог заставить функцию Project.Build работать правильно, поэтому я пошел на выполнение MsBuild.exe напрямую.
Как я его построил:
Используйте Microsoft.Build.Framework из NuGet
Создайте новый объект проекта с 1 целью, называемой Build
Определите правильный инструмент ToolsVersion
Из проекта в соответствии с версией Visual Studio:
- 2010, 2012 => 4.0
- 2013 => 12.0
- 2015 => 14.0
- 2017 => 15,0
Добавьте новую задачу типа MsBuild
Свойство Projects, содержащее весь проект, мне нужно построить
Определить ToolsVersion
задачи MsBuild с тем же значением, что и для проекта
Сериализовать проект во временный файл
Найти MsBuild.exe в соответствии с ToolsVersion
4,0, 12,0, 14,0
Найдено в реестре:
Registry.LocalMachine.OpenSubKey([email protected]"SOFTWARE\Microsoft\MSBuild\ToolsVersions\{msBuildVersion}")
15,0
Не больше в реестре, вам нужно использовать пакет Nuget Microsoft.VisualStudio.Setup.Configuration.Interop
var query = new SetupConfiguration();
var query2 = (ISetupConfiguration2)query;
var e = query2.EnumAllInstances();
var helper = (ISetupHelper)query;
int fetched;
var instances = new ISetupInstance[1];
do
{
e.Next(1, instances, out fetched);
if (fetched > 0)
{
var instance = instances[0];
var instance2 = (ISetupInstance2)instance;
var state = instance2.GetState();
// Skip non-complete instance, I guess?
// Skip non-local instance, I guess?
// Skip unregistered products?
if (state != InstanceState.Complete
|| (state & InstanceState.Local) != InstanceState.Local
|| (state & InstanceState.Registered) != InstanceState.Registered)
{
continue;
}
var msBuildComponent =
instance2.GetPackages()
.FirstOrDefault(
p =>
p.GetId()
.Equals("Microsoft.Component.MSBuild",
StringComparison.InvariantCultureIgnoreCase));
if (msBuildComponent == null)
{
continue;
}
var instanceRootDirectory = instance2.GetInstallationPath();
var msbuildPathInInstance = Path.Combine(instanceRootDirectory, "MSBuild", msBuildVersion, "Bin", "msbuild.exe");
if (File.Exists(msbuildPathInInstance))
{
return msbuildPathInInstance;
}
}
} while (fetched > 0);
Выполнить MsBuild.exe
И постройте сериализованный проект с помощью специального XML Logger - вы можете использовать тот, который предоставляется MsBuildExtensionPack
Прочтите итоговое резюме
Отсоедините итоговое резюме от Xml и используйте его, чтобы определить, произошла ли сбой сборки или нет, какие ошибки и предупреждения произошли и т.д.
Ответ 2
Если вам нужен только путь к последнему файлу MSBuild.exe, используйте Microsoft.Build.Utilities.Core от Nuget и используйте следующий код:
ToolLocationHelper.GetPathToBuildToolsFile("msbuild.exe", ToolLocationHelper.CurrentToolsVersion);
Это работает независимо от того, установлены ли только средства сборки или полная установка Visual Studio.
Ответ 3
У меня были точно такие же проблемы в моем проекте.
В моем случае я хочу программно разработать проект SSDT, но я также пробовал другие типы проектов.
Интересно, что он отлично работал в сборке 26228.04 VS2017 (которая была сборкой Release) и перестала работать в сборке 26228.09.
Вчера был выпущен сборник 26228.10, поэтому я решил отправить его еще раз.
Удивительно, но для меня это работало:
- Обновите последнюю версию VS2017 build 26228.10 с помощью установщика Visual Studio.
-
Я никогда не мог получить collection.LoadProject(...)
чтобы работать, не получая какую-то странную ошибку, но вы можете использовать этот код для сборки:
BuildResult result = null;
using (var pc = new ProjectCollection())
result = BuildManager.DefaultBuildManager.Build(
new BuildParameters(pc) { Loggers = new[] { new ConsoleLogger() } },
// Change this path to your .sln file instead of the .csproj.
// (It won't work with the .csproj.)
new BuildRequestData(@"c:\projects\Sample.sln",
// Change the parameters as you need them,
// e.g. if you want to just Build the Debug (not Rebuild the Release).
new Dictionary<string, string>
{
{ "Configuration", "Release" },
{ "Platform", "Any CPU" }
}, null, new[] { "Rebuild" }, null));
if (result.OverallResult == BuildResultCode.Failure)
// Something bad happened...
-
Убедитесь, что вы скопировали все перенаправления привязки сборки MSBuild к файлу .config
.
Если вы еще этого не сделали, откройте файл C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\MSBuild.exe.config
и скопируйте весь элемент <runtime>
в <configuration>
вашего собственного файла .config
в проекте, который программно использует MSBuild.
Если вы не перенаправляете версии сборки MSBuild, вы получите некоторые довольно странные сообщения об ошибках от MSBuild, которые будут варьироваться в зависимости от версии MSBuild.
Но он обязательно скажет: он, безусловно, не будет работать без перенаправления сборок сборки.
-
Еще один шаг, если вы хотите построить проект SSDT:
Измените следующие две строки в файле .sqlproj
из
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
<VisualStudioVersion Condition="'$(SSDTExists)' == ''">11.0</VisualStudioVersion>
в
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VisualStudioVersion Condition="'$(SSDTExists)' == ''">15.0</VisualStudioVersion>
Я не на 100% уверен, почему, но эти шаги работали отлично для меня!
Но поскольку MSBuild немного "сложно" использовать программно (по моему мнению, он иногда стабилен, как прогноз погоды), скорее всего, мой подход не будет работать в вашем случае.
Ответ 4
Это уже разрешено в версии PreRelease (15.5.0-preview-000072-0942130) msbuild, см. Проблему MsBuild # 2369: пакет msbuild nuget не может открыть файлы csproj vs2017. Поэтому в будущем дальнейшие хаки не нужны