[c#] .NET Framework 버전을 쉽게 확인할 수있는 방법이 있습니까?

문제는 내가 만약 그것의 버전 3.5 SP 1 알 필요가 있다는 것입니다 Environment.Version()만 반환 2.0.50727.3053.

이 솔루션을 찾았 지만 가치보다 훨씬 더 많은 시간이 걸릴 것이라고 생각하므로 더 간단한 솔루션을 찾고 있습니다. 가능합니까?



답변

이런 식으로해야합니다. 레지스트리에서 값을 가져옵니다.

.NET 1-4의 경우 :

Framework가장 높은 설치된 버전이고 SP해당 버전의 서비스 팩입니다.

RegistryKey installed_versions = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP");
string[] version_names = installed_versions.GetSubKeyNames();
//version names start with 'v', eg, 'v3.5' which needs to be trimmed off before conversion
double Framework = Convert.ToDouble(version_names[version_names.Length - 1].Remove(0, 1), CultureInfo.InvariantCulture);
int SP = Convert.ToInt32(installed_versions.OpenSubKey(version_names[version_names.Length - 1]).GetValue("SP", 0));

.NET 4.5+의 경우 ( 공식 문서에서 ) :

using System;
using Microsoft.Win32;


...


private static void Get45or451FromRegistry()
{
    using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\")) {
        int releaseKey = Convert.ToInt32(ndpKey.GetValue("Release"));
        if (true) {
            Console.WriteLine("Version: " + CheckFor45DotVersion(releaseKey));
        }
    }
}


...


// Checking the version using >= will enable forward compatibility,  
// however you should always compile your code on newer versions of 
// the framework to ensure your app works the same. 
private static string CheckFor45DotVersion(int releaseKey)
{
    if (releaseKey >= 461808) {
        return "4.7.2 or later";
    }
    if (releaseKey >= 461308) {
        return "4.7.1 or later";
    }
    if (releaseKey >= 460798) {
        return "4.7 or later";
    }
    if (releaseKey >= 394802) {
        return "4.6.2 or later";
    }
    if (releaseKey >= 394254) {
        return "4.6.1 or later";
    }
    if (releaseKey >= 393295) {
        return "4.6 or later";
    }
    if (releaseKey >= 393273) {
        return "4.6 RC or later";
    }
    if ((releaseKey >= 379893)) {
        return "4.5.2 or later";
    }
    if ((releaseKey >= 378675)) {
        return "4.5.1 or later";
    }
    if ((releaseKey >= 378389)) {
        return "4.5 or later";
    }
    // This line should never execute. A non-null release key should mean 
    // that 4.5 or later is installed. 
    return "No 4.5 or later version detected";
}


답변

확실하지 아무도 다음과 같은 제안하지 왜 마이크로 소프트의 공식 조언 바로 여기 .

이것이 그들이 권장하는 코드입니다. 물론 추악하지만 작동합니다.

.NET 1-4의 경우

private static void GetVersionFromRegistry()
{
     // Opens the registry key for the .NET Framework entry. 
        using (RegistryKey ndpKey =
            RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "").
            OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
        {
            // As an alternative, if you know the computers you will query are running .NET Framework 4.5  
            // or later, you can use: 
            // using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,  
            // RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
        foreach (string versionKeyName in ndpKey.GetSubKeyNames())
        {
            if (versionKeyName.StartsWith("v"))
            {

                RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName);
                string name = (string)versionKey.GetValue("Version", "");
                string sp = versionKey.GetValue("SP", "").ToString();
                string install = versionKey.GetValue("Install", "").ToString();
                if (install == "") //no install info, must be later.
                    Console.WriteLine(versionKeyName + "  " + name);
                else
                {
                    if (sp != "" && install == "1")
                    {
                        Console.WriteLine(versionKeyName + "  " + name + "  SP" + sp);
                    }

                }
                if (name != "")
                {
                    continue;
                }
                foreach (string subKeyName in versionKey.GetSubKeyNames())
                {
                    RegistryKey subKey = versionKey.OpenSubKey(subKeyName);
                    name = (string)subKey.GetValue("Version", "");
                    if (name != "")
                        sp = subKey.GetValue("SP", "").ToString();
                    install = subKey.GetValue("Install", "").ToString();
                    if (install == "") //no install info, must be later.
                        Console.WriteLine(versionKeyName + "  " + name);
                    else
                    {
                        if (sp != "" && install == "1")
                        {
                            Console.WriteLine("  " + subKeyName + "  " + name + "  SP" + sp);
                        }
                        else if (install == "1")
                        {
                            Console.WriteLine("  " + subKeyName + "  " + name);
                        }

                    }

                }

            }
        }
    }

}

.NET 4.5 이상

// Checking the version using >= will enable forward compatibility, 
// however you should always compile your code on newer versions of
// the framework to ensure your app works the same.
private static string CheckFor45DotVersion(int releaseKey)
{
   if (releaseKey >= 393295) {
      return "4.6 or later";
   }
   if ((releaseKey >= 379893)) {
        return "4.5.2 or later";
    }
    if ((releaseKey >= 378675)) {
        return "4.5.1 or later";
    }
    if ((releaseKey >= 378389)) {
        return "4.5 or later";
    }
    // This line should never execute. A non-null release key should mean
    // that 4.5 or later is installed.
    return "No 4.5 or later version detected";
}

private static void Get45or451FromRegistry()
{
    using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\")) {
        if (ndpKey != null && ndpKey.GetValue("Release") != null) {
            Console.WriteLine("Version: " + CheckFor45DotVersion((int) ndpKey.GetValue("Release")));
        }
      else {
         Console.WriteLine("Version 4.5 or later is not detected.");
      }
    }
}


답변

레지스트리에 대한 액세스 권한이 필요하지 않은 대체 방법은 특정 프레임 워크 업데이트에 도입 된 클래스의 존재를 확인하는 것입니다.

private static bool Is46Installed()
{
    // API changes in 4.6: https://github.com/Microsoft/dotnet/blob/master/releases/net46/dotnet46-api-changes.md
    return Type.GetType("System.AppContext, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", false) != null;
}

private static bool Is461Installed()
{
    // API changes in 4.6.1: https://github.com/Microsoft/dotnet/blob/master/releases/net461/dotnet461-api-changes.md
    return Type.GetType("System.Data.SqlClient.SqlColumnEncryptionCngProvider, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", false) != null;
}

private static bool Is462Installed()
{
    // API changes in 4.6.2: https://github.com/Microsoft/dotnet/blob/master/releases/net462/dotnet462-api-changes.md
    return Type.GetType("System.Security.Cryptography.AesCng, System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", false) != null;
}

private static bool Is47Installed()
{
    // API changes in 4.7: https://github.com/Microsoft/dotnet/blob/master/releases/net47/dotnet47-api-changes.md
    return Type.GetType("System.Web.Caching.CacheInsertOptions, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", false) != null;
}


답변

Environment.Version()다른 질문에 대한 정답을 제공하고 있습니다. 동일한 버전의 CLR이 .NET 2.0, 3 및 3.5에서 사용됩니다. 각 후속 릴리스에 추가 된 라이브러리에 대해 GAC 를 확인할 수 있다고 가정합니다 .


답변

예전에는 쉬웠지만 Microsoft는 큰 변화를 주기로 결정했습니다. 버전 4.5 이전 에는 .NET의 각 버전이 아래의 자체 디렉터리 C:\Windows\Microsoft.NET\Framework(하위 디렉터리 v1.0.3705, v1.1.4322, v2.0.50727, v3.0, v3.5v4.0.30319)에 상주했습니다 .

버전 4.5 이후 로 변경되었습니다. 각 버전의 .NET (예 : 4.5.x, 4.6.x, 4.7.x, 4.8.x, …)이 동일한 하위 디렉토리에 설치되어 v4.0.30319있으므로 더 이상 사용할 수 없습니다. 조사하여 설치된 .NET 버전을 확인하십시오.Microsoft.NET\Framework .

.NET 버전을 확인하기 위해 Microsoft 는 확인중인 .NET 버전에 따라 두 가지 다른 샘플 스크립트를 제공 했지만 이에 대해 두 가지 다른 C # 스크립트를 사용하는 것을 좋아하지 않습니다. 그래서 저는 그것들을 하나로 결합하려고 시도했습니다. 여기 GetDotNetVersion.cs제가 만든 스크립트 가 있습니다 (그리고 4.7.1 프레임 워크 용으로 업데이트했습니다).

using System;
using Microsoft.Win32;
public class GetDotNetVersion
{
    public static void Main(string[] args)
    {
        Console.WriteLine((args != null && args.Length > 0)
                          ? "Command line arguments: " + string.Join(",", args)
                          : "");

        string maxDotNetVersion = GetVersionFromRegistry();
        if (String.Compare(maxDotNetVersion, "4.5") >= 0)
        {
            string v45Plus = GetDotNetVersion.Get45PlusFromRegistry();
            if (v45Plus != "") maxDotNetVersion = v45Plus;
        }
        Console.WriteLine("*** Maximum .NET version number found is: " + maxDotNetVersion + "***");
    }

    private static string Get45PlusFromRegistry()
    {
        String dotNetVersion = "";
        const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
        using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
        {
            if (ndpKey != null && ndpKey.GetValue("Release") != null)
            {
                dotNetVersion = CheckFor45PlusVersion((int)ndpKey.GetValue("Release"));
                Console.WriteLine(".NET Framework Version: " + dotNetVersion);
            }
            else
            {
                Console.WriteLine(".NET Framework Version 4.5 or later is not detected.");
            }
        }
        return dotNetVersion;
    }

    // Checking the version using >= will enable forward compatibility.
    private static string CheckFor45PlusVersion(int releaseKey)
    {
        if (releaseKey >= 528040) return "4.8 or later";
        if (releaseKey >= 461808) return "4.7.2";
        if (releaseKey >= 461308) return "4.7.1";
        if (releaseKey >= 460798) return "4.7";
        if (releaseKey >= 394802) return "4.6.2";
        if (releaseKey >= 394254) return "4.6.1";
        if (releaseKey >= 393295) return "4.6";
        if ((releaseKey >= 379893)) return "4.5.2";
        if ((releaseKey >= 378675)) return "4.5.1";
        if ((releaseKey >= 378389)) return "4.5";

        // This code should never execute. A non-null release key should mean
        // that 4.5 or later is installed.
        return "No 4.5 or later version detected";
    }

    private static string GetVersionFromRegistry()
    {
        String maxDotNetVersion = "";
        // Opens the registry key for the .NET Framework entry.
        using (RegistryKey ndpKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "")
                                        .OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
        {
            // As an alternative, if you know the computers you will query are running .NET Framework 4.5 
            // or later, you can use:
            // using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, 
            // RegistryView.Registry32).OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\"))
            foreach (string versionKeyName in ndpKey.GetSubKeyNames())
            {
                if (versionKeyName.StartsWith("v"))
                {
                    RegistryKey versionKey = ndpKey.OpenSubKey(versionKeyName);
                    string name = (string)versionKey.GetValue("Version", "");
                    string sp = versionKey.GetValue("SP", "").ToString();
                    string install = versionKey.GetValue("Install", "").ToString();
                    if (install == "") //no install info, must be later.
                    {
                        Console.WriteLine(versionKeyName + "  " + name);
                        if (String.Compare(maxDotNetVersion, name) < 0) maxDotNetVersion = name;
                    }
                    else
                    {
                        if (sp != "" && install == "1")
                        {
                            Console.WriteLine(versionKeyName + "  " + name + "  SP" + sp);
                            if (String.Compare(maxDotNetVersion, name) < 0) maxDotNetVersion = name;
                        }

                    }
                    if (name != "")
                    {
                        continue;
                    }
                    foreach (string subKeyName in versionKey.GetSubKeyNames())
                    {
                        RegistryKey subKey = versionKey.OpenSubKey(subKeyName);
                        name = (string)subKey.GetValue("Version", "");
                        if (name != "")
                        {
                            sp = subKey.GetValue("SP", "").ToString();
                        }
                        install = subKey.GetValue("Install", "").ToString();
                        if (install == "")
                        {
                            //no install info, must be later.
                            Console.WriteLine(versionKeyName + "  " + name);
                            if (String.Compare(maxDotNetVersion, name) < 0) maxDotNetVersion = name;
                        }
                        else
                        {
                            if (sp != "" && install == "1")
                            {
                                Console.WriteLine("  " + subKeyName + "  " + name + "  SP" + sp);
                                if (String.Compare(maxDotNetVersion, name) < 0) maxDotNetVersion = name;
                            }
                            else if (install == "1")
                            {
                                Console.WriteLine("  " + subKeyName + "  " + name);
                                if (String.Compare(maxDotNetVersion, name) < 0) maxDotNetVersion = name;
                            } // if
                        } // if
                    } // for
                } // if
            } // foreach
        } // using
        return maxDotNetVersion;
    }

} // class

내 컴퓨터에서 다음을 출력합니다.

v2.0.50727 2.0.50727.4927 SP2
v3.0 3.0.30729.4926 SP2
v3.5 3.5.30729.4926 SP1
v4
클라이언트 4.7.03056
전체 4.7.03056
v4.0
클라이언트 4.0.0.0
.NET Framework 버전 : 4.7.2 이상
*** * 발견 된 최대 .NET 버전 번호 : 4.7.2 이상 ****

시간이 지남에 따라 유지 관리해야하는 유일한 것은 4.7.1 이상의 .NET 버전이 나오면 빌드 번호입니다. 기능을 수정하면 쉽게 수행 할 수 있습니다. CheckFor45PlusVersion . 새 버전의 릴리스 키를 알고 있어야합니다. 추가 할 수 있습니다. 예를 들면 :

if (releaseKey >= 461308) return "4.7.1 or later";

릴리스 키 는 여전히 최신 버전이며 Windows 10의 Fall Creators 업데이트에 유효합니다. 다른 (이전) Windows 버전을 계속 실행중인 경우 Microsoft 의이 설명서에 따라 다른 버전 있습니다.

다른 모든 Windows OS 버전 461310에 설치된 .NET Framework 4.7.1

따라서 필요한 경우 추가해야합니다.

if (releaseKey >= 461310) return "4.7.1 or later";

함수의 맨 위로 CheckFor45PlusVersion. 마찬가지로 최신 버전에서도 작동합니다. 예를 들어 최근에 4.8에 대한 검사를 추가했습니다. 일반적으로 빌드 번호를 찾을 수 있습니다. 으로 Microsoft에서 .


참고 : PowerShell이 ​​아니라 Visual Studio를 설치할 필요가 없습니다 . 여기서csc.exe 설명한 스크립트를 컴파일하고 실행하는 데 사용할 수 있습니다.


업데이트 : 질문은 .NET Framework에 관한 것입니다. 완전성을 위해 .NET Core 버전 을 쿼리하는 방법도 언급하고 싶습니다 . 위와 비교하면 간단합니다. 명령 셸을 열고 다음을 입력합니다.

dotnet --info Enter

그리고 .NET Core 버전 번호, Windows 버전 및 각 관련 런타임 DLL의 버전도 나열됩니다. 샘플 출력 :

.NET Core SDK (global.json 반영) :

  버전 : 2.1.300

  커밋 : adab45bf0c

런타임 환경 :

  OS 이름 : Windows

  OS 버전 : 10.0.15063

  OS 플랫폼 : Windows

  RID : win10-x64

  기본 경로 : C : \ Program Files \ dotnet \ sdk \ 2.1.300

호스트 (지원에 유용) :

  버전 : 2.1.0

  커밋 : caa7b7e2ba

.NET Core SDK 설치 :

  1.1.9 [C : \ Program Files \ dotnet \ sdk]

  2.1.102 [C : \ Program Files \   dotnet \ sdk]

  …

2.1.300 [C : \ Program Files \ dotnet \ sdk]

.NET Core 런타임 설치 :

  Microsoft.AspNetCore.All 2.1.0 [C : \ Program
  Files \ dotnet \ shared \ Microsoft .AspNetCore.All]

  …

  Microsoft.NETCore.App 2.1.0 [C : \ Program Files \ dotnet \ shared \ Microsoft.NETCore.App]

추가 .NET Core 런타임 또는 SDK를 설치하려면 :

  https://aka.ms/dotnet-download

참고

  • 모든 추가 정보없이 버전 번호 만 필요한 경우을 사용할 수 있습니다
    dotnet --version.

  • A의 64 비트 Windows PC , 설치할 수 의 x86 버전 나란히의 x64 .NET 코어 버전. 이 경우 환경 변수에서 첫 번째 버전 만 가져옵니다 PATH. 최신 상태로 유지하고 각 버전을 알고 싶은 경우 특히 중요합니다. 두 버전을 모두 쿼리하려면 다음을 사용하십시오.

C : \ Program Files \ dotnet \ dotnet.exe-버전
3.0.100-preview6-012264
C : \ Program Files (x86) \ dotnet \ dotnet.exe –version
버전 3.0.100-preview6-012264

위의 예에서 둘 다 동일하지만 두 인스턴스를 모두 업데이트하는 것을 잊은 경우 다른 결과를 얻을 수 있습니다! 참고 Program Files을위한 64 비트 버전과 Program Files (x86)는 IS 32 비트 버전.


업데이트 : 빌드 번호를 일련의 if 문 (Microsoft가 제안한대로) 대신 목록에 유지하려는 경우 CheckFor45PlusVersion대신 이 코드를 사용할 수 있습니다 .

private static string CheckFor45PlusVersion(int releaseKey)
{
    var release = new Dictionary<int, string>()
    {
            { 378389, "4.5" },
            { 378675, "4.5.1" }, { 379893, "4.5.2" },
            { 393295, "4.6" },
            { 394254, "4.6.1" }, { 394802, "4.6.2" },
            { 460798, "4.7" },
            { 461308, "4.7.1" }, { 461808, "4.7.2" },
            { 528040, "4.8 or later" }
    };
    int result = -1;
    foreach(var k in release.OrderBy(k=>k.Key))
    {
        if (k.Key <= releaseKey) result = k.Key; else break;
    };
    return (result > 0) ? release[result] : "No 4.5 or later version detected";
}


답변

AFAIK 프레임 워크에는이를 수행 할 수있는 기본 제공 방법이 없습니다. 이 게시물 에서 Windows 레지스트리 값을 읽어 프레임 워크 버전 결정에 대한 제안을 확인할 수 있습니다.


답변

이 클래스를 사용하면 응용 프로그램이 적절한 .NET 버전을 찾을 수없는 경우 충돌 및 굽기 대신 우아한 알림 메시지를 표시 할 수 있습니다. 기본 코드에서 다음과 같이하면됩니다.

[STAThread]
static void Main(string[] args)
{
    if (!DotNetUtils.IsCompatible())
        return;
   . . .
}

기본적으로 4.5.2가 필요하지만 원하는 클래스로 조정할 수 있습니다 (MessageBox를 Console로 자유롭게 대체 할 수 있음).

4.8 업데이트 :

public class DotNetUtils
{
    public enum DotNetRelease
    {
        NOTFOUND,
        NET45,
        NET451,
        NET452,
        NET46,
        NET461,
        NET462,
        NET47,
        NET471,
        NET472,
        NET48,
    }

    public static bool IsCompatible(DotNetRelease req = DotNetRelease.NET452)
    {
        DotNetRelease r = GetRelease();
        if (r < req)
        {
            MessageBox.Show(String.Format("This this application requires {0} or greater.", req.ToString()));
            return false;
        }
        return true;
    }

    public static DotNetRelease GetRelease(int release = default(int))
    {
        int r = release != default(int) ? release : GetVersion();
        if (r >= 528040) return DotNetRelease.NET48;
        if (r >= 461808) return DotNetRelease.NET472;
        if (r >= 461308) return DotNetRelease.NET471;
        if (r >= 460798) return DotNetRelease.NET47;
        if (r >= 394802) return DotNetRelease.NET462;
        if (r >= 394254) return DotNetRelease.NET461;
        if (r >= 393295) return DotNetRelease.NET46;
        if (r >= 379893) return DotNetRelease.NET452;
        if (r >= 378675) return DotNetRelease.NET451;
        if (r >= 378389) return DotNetRelease.NET45;
        return DotNetRelease.NOTFOUND;
    }

    public static int GetVersion()
    {
        int release = 0;
        using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)
                                            .OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\"))
        {
            release = Convert.ToInt32(key.GetValue("Release"));
        }
        return release;
    }
}

나중에 새 버전을 추가 할 때 쉽게 확장 할 수 있습니다. 나는 4.5 이전에 아무것도 신경 쓰지 않았지만 아이디어를 얻었습니다.