C#を用いたアプリケーション開発において、動作している環境のランタイムバージョンや実行プログラム自身のアセンブリバージョンを正確に取得することは、デバッグ、ログ出力、あるいは互換性の維持において極めて重要です。
特に現代の.NET(旧.NET Core以降のモダンな.NET)では、複数のバージョンが共存しやすく、意図したランタイムで動作しているかを確認するコードの実装は欠かせません。
本記事では、C#を使用して「.NETランタイムのバージョン」「実行中のアセンブリのバージョン」「OSなどの環境情報」を取得する方法について、初心者から中級者までが実戦で活用できるよう、詳細なコード例とともに解説します。
.NETランタイムのバージョンを取得する方法
アプリケーションが現在どの.NETランタイム上で動作しているかを知ることは、特定のフレームワーク機能に依存した処理を行う際の判断基準となります。
C#では、主に2つのアプローチでこれを取得できます。
Environment.Versionによる取得
System.Environment.Versionプロパティを使用すると、現在のプロセスを実行している共通言語ランタイム(CLR)のバージョンを取得できます。
using System;
class Program
{
static void Main()
{
// Environment.Versionを使用してCLRのバージョンを取得
Version clrVersion = Environment.Version;
Console.WriteLine("--- Environment.Version による出力 ---");
Console.WriteLine($"Full Version: {clrVersion}");
Console.WriteLine($"Major: {clrVersion.Major}");
Console.WriteLine($"Minor: {clrVersion.Minor}");
Console.WriteLine($"Build: {clrVersion.Build}");
Console.WriteLine($"Revision: {clrVersion.Revision}");
}
}
実行結果の例(.NET 8環境の場合):
--- Environment.Version による出力 ---
Full Version: 8.0.0
Major: 8
Minor: 0
Build: 0
Revision: -1
ただし、注意点として、このプロパティが返すのは「CLR(共通言語ランタイム)」のバージョンです。
.NET Framework時代はフレームワークのバージョンとCLRのバージョンが必ずしも一致しない(例:.NET Framework 4.5から4.8まではCLR 4.0を使用)という現象がありましたが、モダンな.NET(5以降)では製品バージョンに近い値が返されるようになっています。
RuntimeInformationによる詳細な名称取得
より人間が読みやすい形式、あるいは「.NET 8.0.1」といったパッチバージョンを含む正確な製品名を取得したい場合は、System.Runtime.InteropServices.RuntimeInformationクラスを使用します。
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
// 実行中の.NETの名称とバージョンを取得
string frameworkDescription = RuntimeInformation.FrameworkDescription;
Console.WriteLine("--- RuntimeInformation による出力 ---");
Console.WriteLine($"Description: {frameworkDescription}");
}
}
--- RuntimeInformation による出力 ---
Description: .NET 8.0.1
このメソッドは、「.NET」という名称も含めた文字列を返すため、ログファイルへの出力や、診断画面の表示に最適です。
アセンブリのバージョンを取得する方法
「作成したアプリケーション自体のバージョン」を取得する方法はいくつかあり、それぞれ取得できる情報の種類が異なります。
C#プロジェクトには主に3つのバージョン属性が存在します。
- AssemblyVersion:.NETのランタイムがアセンブリの識別(バインディング)に使用するバージョン。
- AssemblyFileVersion:Windowsのエクスプローラーなどでファイルプロパティとして表示されるバージョン。
- AssemblyInformationalVersion:製品バージョンとして定義される文字列。セマンティックバージョニング(例:1.0.0-beta)なども含めることが可能。
実行中のアセンブリから取得する
現在実行されているメソッドが含まれるアセンブリ(通常は自身のプログラム)のバージョンを取得するには、System.Reflection.Assemblyクラスを使用します。
using System;
using System.Reflection;
class Program
{
static void Main()
{
// 実行中のアセンブリ情報を取得
Assembly assembly = Assembly.GetExecutingAssembly();
// AssemblyNameオブジェクトからバージョンを取得
Version version = assembly.GetName().Version;
Console.WriteLine("--- アセンブリバージョンの取得 ---");
Console.WriteLine($"Assembly Name: {assembly.GetName().Name}");
Console.WriteLine($"Version: {version}");
}
}
--- アセンブリバージョンの取得 ---
Assembly Name: MyApp
Version: 1.0.0.0
エントリアセンブリ(起動元)から取得する
ライブラリ(DLL)側から、そのライブラリを呼び出しているメインの実行ファイル(EXE)のバージョンを知りたい場合は、GetEntryAssembly()を使用します。
Assembly entryAssembly = Assembly.GetEntryAssembly();
if (entryAssembly != null)
{
Console.WriteLine($"Entry Assembly Version: {entryAssembly.GetName().Version}");
}
注意: 単体テスト実行時や、アンマネージドコードから呼び出された場合、GetEntryAssembly()はnullを返す可能性があるため、必ずヌルチェックを行ってください。
FileVersionInfoによる詳細な属性取得
アセンブリのメタデータに記録されている「ファイルバージョン」や「製品バージョン」を取得するには、System.Diagnostics.FileVersionInfoクラスが便利です。
これはエクスプローラーの「詳細」タブに表示される情報と一致します。
using System;
using System.Diagnostics;
using System.Reflection;
class Program
{
static void Main()
{
// 実行ファイルのパスを取得
string location = Assembly.GetExecutingAssembly().Location;
// パスが空(Single File起動など)の場合はプロセスのメインモジュールから取得
if (string.IsNullOrEmpty(location))
{
location = Process.GetCurrentProcess().MainModule.FileName;
}
// ファイルバージョン情報を取得
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(location);
Console.WriteLine("--- FileVersionInfo による詳細情報 ---");
Console.WriteLine($"ファイルバージョン: {fvi.FileVersion}");
Console.WriteLine($"製品バージョン: {fvi.ProductVersion}");
Console.WriteLine($"会社名: {fvi.CompanyName}");
Console.WriteLine($"製品名: {fvi.ProductName}");
Console.WriteLine($"著作権: {fvi.LegalCopyright}");
}
}
--- FileVersionInfo による詳細情報 ---
ファイルバージョン: 1.0.0.0
製品バージョン: 1.0.0-alpha+commit12345
会社名: MyCompany Corp.
製品名: MyGreatApp
著作権: Copyright (C) 2024
FileVersionInfoを使用するメリットは、アセンブリロードを行わずにファイルパスから直接情報を読み取れる点、および文字列ベースの「製品バージョン(Informational Version)」を取得できる点にあります。
プロジェクトファイル(.csproj)でのバージョン定義
モダンなC#開発では、AssemblyInfo.csを直接編集するのではなく、.csprojファイル内にバージョン情報を記述するのが一般的です。
以下の表は、プロジェクトファイル内のタグと、C#コードで取得される値の対応関係をまとめたものです。
| .csproj内のタグ | C#での取得方法(プロパティ) | 役割 |
|---|---|---|
<Version> | fvi.ProductVersion | 製品全体のバージョン(デフォルト) |
<AssemblyVersion> | assembly.GetName().Version | アセンブリの論理的な識別用 |
<FileVersion> | fvi.FileVersion | Win32ファイルシステム上のバージョン |
<Description> | fvi.FileDescription | ファイルの説明 |
設定例:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- バージョン情報の設定 -->
<Version>1.2.3-beta</Version>
<AssemblyVersion>1.2.0.0</AssemblyVersion>
<FileVersion>1.2.3.4</FileVersion>
<Authors>Technical Writer</Authors>
<Company>Sample Tech</Company>
<Copyright>Copyright © 2024</Copyright>
</PropertyGroup>
</Project>
このように、Versionタグに文字列を指定すると、それが自動的にAssemblyInformationalVersionとして扱われます。
ターゲットフレームワークの判定
プログラムがコンパイルされたターゲットフレームワーク(.NET 8なのか、.NET Standard 2.0なのか等)を動的に取得したい場合は、AppContext.TargetFrameworkNameを使用します。
using System;
class Program
{
static void Main()
{
string? targetFramework = AppContext.TargetFrameworkName;
Console.WriteLine($"Target Framework: {targetFramework}");
}
}
Target Framework: .NETCoreApp,Version=v8.0
これは「どのランタイムで動いているか」ではなく、「どのターゲットに対してビルドされたか」を示すため、条件分岐で特定のフレームワーク向けに最適化されたロジックを切り替える際に非常に有用です。
実践的な実装例:バージョン情報のサマリー表示
実際のアプリケーション開発では、これら複数の手法を組み合わせて、起動時にシステム情報をログへ出力する「ヘルパークラス」を作成するのが効率的です。
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Diagnostics;
public static class AppDiagnostics
{
public static void PrintSystemInfo()
{
var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
var fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
Console.WriteLine("========================================");
Console.WriteLine($"アプリケーション名: {fvi.ProductName}");
Console.WriteLine($"アセンブリバージョン: {assembly.GetName().Version}");
Console.WriteLine($"ファイルバージョン: {fvi.FileVersion}");
Console.WriteLine($"製品バージョン: {fvi.ProductVersion}");
Console.WriteLine("----------------------------------------");
Console.WriteLine($"OS: {RuntimeInformation.OSDescription} ({RuntimeInformation.OSArchitecture})");
Console.WriteLine($"ランタイム: {RuntimeInformation.FrameworkDescription}");
Console.WriteLine($"ターゲット: {AppContext.TargetFrameworkName}");
Console.WriteLine("========================================");
}
}
class Program
{
static void Main()
{
AppDiagnostics.PrintSystemInfo();
}
}
========================================
アプリケーション名: VersionMaster
アセンブリバージョン: 1.0.0.0
ファイルバージョン: 1.0.0.0
製品バージョン: 1.0.0-rc1
----------------------------------------
OS: Microsoft Windows 10.0.22631 (X64)
ランタイム: .NET 8.0.2
ターゲット: .NETCoreApp,Version=v8.0
========================================
このように情報をまとめておくことで、ユーザーからの不具合報告を受けた際に、「どのバージョンのアプリが、どのOS上の、どのランタイムで動いていたのか」を一目で特定できるようになります。
OSのバージョンの取得
環境依存の不具合を調査する場合、.NETのバージョンだけでなくOSのバージョンも重要です。
Environment.OSVersionは古くからある手法ですが、最近の.NETでは前述のRuntimeInformation.OSDescriptionの方がより具体的な名称(Windows 11など)を取得しやすい傾向にあります。
// 伝統的なOSVersion取得
OperatingSystem os = Environment.OSVersion;
Console.WriteLine($"Platform: {os.Platform}");
Console.WriteLine($"Version: {os.Version}");
Windows 10と11の判別など、OSのマイナーな差異を特定する必要がある場合は、レジストリや特定のAPIを叩く必要がありますが、一般的なログ目的であればRuntimeInformationで十分です。
まとめ
C#でバージョン情報を取得する方法は多岐にわたりますが、用途に応じて適切なメソッドを選択することが重要です。
- ランタイムの情報を知りたい場合は、
RuntimeInformation.FrameworkDescription。 - アセンブリの論理バージョンを扱いたい場合は、
Assembly.GetName().Version。 - 製品名やコピーライト、詳細な製品バージョンを表示したい場合は、
FileVersionInfo。 - ビルド時のターゲットを確認したい場合は、
AppContext.TargetFrameworkName。
これらの情報を適切に取得し、ログやUIに表示させることで、アプリケーションの保守性は格段に向上します。
特に昨今の高速な.NETのアップデートサイクルにおいては、実行環境の正確な把握はトラブルシューティングの第一歩となります。
ぜひ、自身のプロジェクトに最適なバージョン取得ロジックを組み込んでみてください。






