VS2017で作成した簡単なC#7クラスライブラリプロジェクトを構築しようとしています。
フレームワークアセンブリからのMSBuildは古くなっているので、ビジュアルスタジオ(C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin
)内のMSBuildフォルダーからMicrosoft.Build
、Microsoft.Build.Engine
およびMicrosoft.Build.Framework
を参照しています。
それでも、私がこれをするとき:
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".
を取得しています
最新のビルドツールとC#7コンパイラを使用してビルドを呼び出すプログラム的な方法はありますか?
私のチームにも同様のニーズがあり、いくつかのバージョンのVisual StudioをサポートするC#のビルダーライブラリを作成しました。 Project.Build関数を正しく機能させることができなかったため、MsBuild.exeを直接実行しました。
私がそれを構築した方法:
Visual Studioのバージョンに応じたプロジェクト:
ビルドする必要があるすべてのプロジェクトを含むProjectsプロパティ
プロジェクトと同じ値を持つMsBuildタスクの例
レジストリで見つかりました:
Registry.LocalMachine.OpenSubKey($@"SOFTWARE\Microsoft\MSBuild\ToolsVersions\{msBuildVersion}")
レジストリにはもうないので、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);
そして、カスタムXMLロガーを使用して、シリアル化されたプロジェクトをビルドします。 MsBuildExtensionPack によって提供されるものを使用できます。
Xmlから結果の概要を逆シリアル化し、それを使用して、ビルドが失敗したかどうか、どのエラーや警告が発生したかなどを判断します。
最新のMSBuild.exeへのパスが必要なだけの場合は、NugetのMicrosoft.Build.Utilities.Coreを使用し、次のコードを使用します。
ToolLocationHelper.GetPathToBuildToolsFile("msbuild.exe", ToolLocationHelper.CurrentToolsVersion);
これは、ビルドツールがインストールされている場合でも、完全なVisual Studioインストールの場合でも機能します。
私のプロジェクトでもまったく同じ問題がありました。
私の場合、SSDTプロジェクトをプログラムで構築したいのですが、他の種類のプロジェクトも試しました。
興味深いことに、VS2017のビルド26228.04(これはリリースビルドでした)では完全に正常に動作し、ビルド26228.09では動作しなくなりました。
昨日ビルド26228.10がリリースされたので、もう一度試すことにしました。
驚いたことに、次のことがうまくいきました:
奇妙なエラーが発生することなく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プロジェクトをビルドする場合のもう1つのステップ:
_.sqlproj
_ファイルの次の2行を
_<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はプログラムで使用するのが少し "難しい"(私の意見では、天気予報のように安定している場合がある)ため、私のアプローチはあなたのケースでは機能しない可能性があります。
これは、msbuildのプレリリースバージョン( 15.5.0-preview-000072-0942130 )ですでに解決されています。MsBuildの問題 を参照してください=)#2369:msbuild nugetパッケージがvs2017 csprojファイルを開くことができません 。したがって、将来的には、これ以上ハッキングする必要はありません。