Построение проекта msbuild 15 программно
Я пытаюсь создать простой проект библиотеки классов C# 7, созданный с помощью VS2017.
MSBuild из сборок framework устарел, поэтому я ссылаюсь на Microsoft.Build
, Microsoft.Build.Engine
и Microsoft.Build.Framework
из папки MSBuild в visual studio (C:Program Files (x86)Microsoft Visual Studio17CommunityMSBuild.0Bin
).
все же, когда я это делаю:
using (var collection = new ProjectCollection())
{
var proj = collection.LoadProject(@"c:projectsSampleSample.csproj"); // <-- exception
proj.Build(new[] {new ConsoleLogger()});
}
Я InvalidProjectFileException: The tools version "15.0" is unrecognized. Available tools versions are "4.0", "2.0".
есть ли программный способ вызова сборки с использованием новейших инструментов сборки и компилятора C# 7?
4 ответов
у меня были аналогичные потребности для моей команды, и я написал библиотеку Builder для C#, которая поддерживает несколько версий Visual Studio. Я не смог сделать проект.Функция сборки работает правильно, поэтому я пошел на выполнение MsBuild.ехе напрямую.
Как я его построил:
Использовать Microsoft.Строить.Рамки от 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($@"SOFTWARE\Microsoft\MSBuild\ToolsVersions\{msBuildVersion}")
15.0
больше нет в реестре, вам нужно использовать пакет Nuget Microsoft.VisualStudio.Установка.Конфигурация.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-регистратора - вы можете использовать тот, который предоставляется MsBuildExtensionPack
прочитайте сводку результатов
Десериализуйте сводку результатов из Xml и используйте ее для определения сбоя сборки или нет,какие ошибки и предупреждения произошли и т. д.
Если вам просто нужен путь к последнему MSBuild.EXE-файл, используйте Microsoft.Строить.Коммунальные услуги.Ядро из Nuget и используйте следующий код:
ToolLocationHelper.GetPathToBuildToolsFile("msbuild.exe", ToolLocationHelper.CurrentToolsVersion);
это работает независимо от того, установлены ли только средства сборки или полная установка Visual Studio.
у меня были точно такие же проблемы в моем проекте.
В моем случае я хочу построить проект SSDT программно, но я пробовал и другие типы проектов.
интересно, что он отлично работал в сборке 26228.04 VS2017 (который был сборкой выпуска) и перестал работать в сборке 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 на ваш .
Если вы еще не сделали этого, откройте файлC:\Program Files (x86)\Microsoft Visual Studio17\Enterprise\MSBuild.0\Bin\MSBuild.exe.config
и скопируйте все<runtime>
элемент в<configuration>
элемент вашего собственного.config
файл в проекте, который использует MSBuild программно.
Если вы не перенаправите версии сборки MSBuild, вы получите довольно странные сообщения об ошибках от MSBuild, которые будут отличаться в зависимости от вашей версии MSBuild.
Но он обязательно скажет: он определенно не будет работать без перенаправления привязки сборки.-
один дополнительный шаг, если вы хотите построить проект SSDT:
Изменить следующие две строки в вашем С<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion> <VisualStudioVersion Condition="'$(SSDTExists)' == ''">11.0</VisualStudioVersion>
to
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion> <VisualStudioVersion Condition="'$(SSDTExists)' == ''">15.0</VisualStudioVersion>
Я не на 100% уверен, почему, но эти шаги работал отлично для меня!
Но поскольку MSBuild немного "сложно" использовать программно (на мой взгляд, он иногда так же стабилен, как прогноз погоды), есть вероятность, что мой подход не будет работать в вашем случае.
Это уже решено в предварительной версии (15.5.0-preview-000072-0942130) msbuild, см. MSBuild issue #2369: пакет msbuild nuget не может открыть файлы VS2017 csproj. Так что в будущем никаких дальнейших хаков не нужно