Search code examples
c#powershell

In C# How can we determine if a caller is using Windows PowerShell 5.1 or a newer version?


From PowerShell we can easily check if a caller is using Windows PowerShell 5.1 or a newer version using the $PSVersionTable automatic variable:

if ($PSVersionTable.PSVersion -ge '7.0') {
    # do 7+ stuff here
    return
}

# do 5.1 stuff here

Or we could even use $IsCoreCLR:

if ($IsCoreCLR) {
    # do 7+ stuff here
    return
}

# do 5.1 stuff here

How could we do the same from C# if targeting netstandard2.0?


Solution

  • One way we can determine this is by checking the value of the PSVersionInfo.PSVersion Property, this method requires reflection as the PSVersionInfo class was not exposed in Windows PowerShell 5.1.

    using System;
    using System.Management.Automation;
    using System.Reflection;
    
    namespace Testing;
    
    internal static class PSVersion
    {
        private static bool? s_isCore;
    
        // internal assuming we don't want to expose this
        internal static bool IsCoreCLR { get => s_isCore ??= IsCore(); }
    
        private static bool IsCore()
        {
            PropertyInfo property = typeof(PowerShell)
                .Assembly
                .GetType("System.Management.Automation.PSVersionInfo")
                .GetProperty(
                    "PSVersion",
                    BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
    
            return (Version)property.GetValue(property) is not { Major: 5, Minor: 1 };
        }
    }
    

    Another way to do it if we're leveraging PSCmdlet is by getting the value of IsCoreCLR through the cmdlet's SessionState:

    using System.Management.Automation;
    
    namespace Testing;
    
    [Cmdlet(VerbsDiagnostic.Test, "PSVersion")]
    public sealed class TestPSVersionCommand : PSCmdlet
    {
        private static bool? s_isCore;
    
        private bool IsCoreCLR { get => s_isCore ??= IsCore(); }
    
        protected override void EndProcessing()
        {
            if (IsCoreCLR)
            {
                // call 7+ method here
                return;
            }
    
            // call 5.1 method here
        }
    
        private bool IsCore() =>
            (bool?)SessionState.PSVariable.GetValue("IsCoreCLR") is true;
    }