.NET Core 3.0 リリース記念 C# Tokyoで登壇された@nuits_jpさんの.NET Core 3.0のPublish Single File概要を見て、そういえば.NET Core 3.0の新機能でRuntimeのバージョンをコントロールする機能あったなぁ…と思い、ちょっと調べてみました。
Microsoft Docsでいうと、このあたりの話です。
RollForwardとは?
.NET Coreアプリの実行時に使用するRuntimeバージョンは.runtimeconfig.json
で指定されたFrameworkバージョンを元にフォワードされます。このフォワードされるルールをコントロールするというオプションがRollForwardのようです。
実際に試してみる
インストール済み SDK の確認
下記コマンドでインストール済みのSDKを表示できます。
dotnet --list-sdks
私の環境ではこんな感じでした。
> dotnet --list-sdks 2.1.402 [C:\Program Files\dotnet\sdk] 2.1.602 [C:\Program Files\dotnet\sdk] 2.1.801 [C:\Program Files\dotnet\sdk] 2.2.101 [C:\Program Files\dotnet\sdk] 2.2.105 [C:\Program Files\dotnet\sdk] 2.2.202 [C:\Program Files\dotnet\sdk] 2.2.401 [C:\Program Files\dotnet\sdk] 3.0.100-preview7-012821 [C:\Program Files\dotnet\sdk] 3.0.100 [C:\Program Files\dotnet\sdk]
作成アプリのバージョン指定
.NET Core のプロジェクトを作成します。
使用するSDKのバージョンはあえて古いバージョンで作成します。
mkdir RFSample cd RFSample dotnet new global
生成されたglobal.json
を以下の内容に変更します。
{ "sdk": { "version": "2.1.402" } }
アプリの作成
以下のコマンドでコンソールアプリケーションを作成します。
dotnet new console
コードはこんな感じです
using System; namespace sample { class Program { static void Main (string[] args) { Console.WriteLine(typeof(Object).Assembly.Location); } } }
dotnet run
で実行すると、私の環境ではこんな感じになります。
> cd .\bin\Debug\netcoreapp2.1 > dotnet RFSample.dll C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.13\System.Private.CoreLib.dll
global.json
でSDKのバージョンは2.1.402
を指定しましたが、実行時のRuntimeは2.1.13
を使用しているっぽいですね。
ちなみにインストール済み Runtime の一覧はdotnet --list-runtimes
で確認できます。
> dotnet --list-runtimes Microsoft.AspNetCore.All 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All] ... 途中割愛 ... Microsoft.AspNetCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App] Microsoft.NETCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.1.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 2.2.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.0.0-preview7-27912-14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.NETCore.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] Microsoft.WindowsDesktop.App 3.0.0-preview7-27912-14 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App] Microsoft.WindowsDesktop.App 3.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
--roll-forward を使ってみる
Microsoft Docs によると RollForward の指定は複数の方法でできるようです。
ここでは一番簡単なコマンド引数の--roll-forward
を使用して実行してみます。
まずはLatestMajor
から。
> dotnet --roll-forward LatestMajor .\RFSample.dll C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.0.0\System.Private.CoreLib.dll
使用する Runtime が2.1.13
から3.0.0
に変わりましたね!
色々試してみましょう。
> dotnet --roll-forward LatestPatch .\RFSample.dll C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.13\System.Private.CoreLib.dll > dotnet --roll-forward Minor .\RFSample.dll C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.13\System.Private.CoreLib.dll > dotnet --roll-forward LatestMinor .\RFSample.dll C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.7\System.Private.CoreLib.dll > dotnet --roll-forward Major .\RFSample.dll C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.13\System.Private.CoreLib.dll > dotnet --roll-forward LatestMajor .\RFSample.dll C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.0.0\System.Private.CoreLib.dll > dotnet --roll-forward Disable .\RFSample.dll It was not possible to find any compatible framework version The specified framework 'Microsoft.NETCore.App', version '2.1.0' was not found. - The following frameworks were found: 2.1.4 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] 2.1.9 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] 2.1.12 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] 2.1.13 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] 2.2.0 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] 2.2.3 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] 2.2.5 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] 2.2.6 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] 2.2.7 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] 3.0.0-preview7-27912-14 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] 3.0.0 at [C:\Program Files\dotnet\shared\Microsoft.NETCore.App] You can resolve the problem by installing the specified framework and/or SDK. The .NET Core frameworks can be found at: - https://aka.ms/dotnet-download
変化をちゃんと網羅できていませんが、まぁこんなもんでしょう。
Disable
は2.1.0
のRuntimeがないので怒られてしまいましたね。
※Disable
は一般的な用途としては非推奨なのでテスト用途に使ってね、らしいのです。
.NET Core 2.1で作ったMVCアプリを.NET Core 3.0にRollForwardしたらどうなるのか?
当たり前ですが動作しません。
以下は.NET Core 2.1
で作ったASP.NET Core MVCを--roll-forward LatestMajor
を指定することで強制的に.NET Core 3.0
で環境で動かしたログです。
> dotnet --roll-forward LatestMajor MVCSample.dll Application startup exception: System.InvalidOperationException: Endpoint Routing does not support 'IApplicationBuilder.UseMvc(...)'. To use 'IApplicationBuilder.UseMvc' set 'MvcOptions.EnableEndpointRouting = false' inside 'ConfigureServices(...). at Microsoft.AspNetCore.Builder.MvcApplicationBuilderExtensions.UseMvc(IApplicationBuilder app, Action`1 configureRoutes) at MVCSample.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env) in C:\Users\piyosi\work\RFSample\MVCSample\Startup.cs:line 55 at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder) at Microsoft.AspNetCore.Hosting.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder) at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app) at Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter.<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder) at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app) at Microsoft.AspNetCore.Hosting.WebHost.BuildApplication() crit: Microsoft.AspNetCore.Hosting.WebHost[6] Application startup exception System.InvalidOperationException: Endpoint Routing does not support 'IApplicationBuilder.UseMvc(...)'. To use 'IApplicationBuilder.UseMvc' set 'MvcOptions.EnableEndpointRouting = false' inside 'ConfigureServices(...). at Microsoft.AspNetCore.Builder.MvcApplicationBuilderExtensions.UseMvc(IApplicationBuilder app, Action`1 configureRoutes) at MVCSample.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env) in C:\Users\piyosi\work\RFSample\MVCSample\Startup.cs:line 55 at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder) at Microsoft.AspNetCore.Hosting.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder) at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app) at Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter.<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder) at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app) at Microsoft.AspNetCore.Hosting.WebHost.BuildApplication() Unhandled exception. System.InvalidOperationException: Endpoint Routing does not support 'IApplicationBuilder.UseMvc(...)'. To use 'IApplicationBuilder.UseMvc' set 'MvcOptions.EnableEndpointRouting = false' inside 'ConfigureServices(...). at Microsoft.AspNetCore.Builder.MvcApplicationBuilderExtensions.UseMvc(IApplicationBuilder app, Action`1 configureRoutes) at MVCSample.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env) in C:\Users\piyosi\work\RFSample\MVCSample\Startup.cs:line 55 at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at Microsoft.AspNetCore.Hosting.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder) at Microsoft.AspNetCore.Hosting.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder) at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.Configure(IApplicationBuilder app) at Microsoft.AspNetCore.Mvc.Filters.MiddlewareFilterBuilderStartupFilter.<>c__DisplayClass0_0.<Configure>g__MiddlewareFilterBuilder|0(IApplicationBuilder builder) at Microsoft.AspNetCore.HostFilteringStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder app) at Microsoft.AspNetCore.Hosting.WebHost.BuildApplication() at Microsoft.AspNetCore.Hosting.WebHost.StartAsync(CancellationToken cancellationToken) at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String startupMessage) at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token, String startupMessage) at Microsoft.AspNetCore.Hosting.WebHostExtensions.RunAsync(IWebHost host, CancellationToken token) at Microsoft.AspNetCore.Hosting.WebHostExtensions.Run(IWebHost host) at MVCSample.Program.Main(String[] args) in C:\Users\piyosi\work\RFSample\MVCSample\Program.cs:line 18
ディスコンされた関数を使用している場合もきっと同じでしょう。
おわり
バグ修正された新しいバージョンで動作させたいとか、そんな感じのシチュエーションで使用するのでしょうか?
個人的には--self-contained
やら/p:PublishSingleFile
でRuntimeを同封して配布することが多いので、すぐに使う機会は少ないかなぁ、といった感想です。
以上です。