ChatGPT解决这个技术问题 Extra ChatGPT

Determine installed PowerShell version

How can I determine what version of PowerShell is installed on a computer, and indeed if it is installed at all?

pwsh --version should work fine. I checked on windows 11.
@Kapil please post that as an answer so it can be voted on along with the rest of the answers. Anyway, it didn't work for me on Windows 10.
@Kapil pwsh only works as a command if a newer PowerShell version is installed. For older versions, such as the PowerShell 5 that comes with Windows 10, the executable is called PowerShell.exe. (And there's no --version either in older versions.)

1
14 revs, 12 users 69% user156862

Use $PSVersionTable.PSVersion to determine the engine version. If the variable does not exist, it is safe to assume the engine is version 1.0.

Note that $Host.Version and (Get-Host).Version are not reliable - they reflect the version of the host only, not the engine. PowerGUI, PowerShellPLUS, etc. are all hosting applications, and they will set the host's version to reflect their product version — which is entirely correct, but not what you're looking for.

PS C:\> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1

@DanielCassidy - two years late to the party, but "some features are unaccountably unavailable" might be caused by only having the .Net 3.5 Compact framework installed instead of the full thing.
$PSVersionTable is more reliable and returns $PSVersion. You can also use $PSVersionTable.PSVersion. Even if you are connected remotely to the machine running different version (invoke-command -computername myRemotePC -Credential foo {$host}), it looks like $host will just show the lowest version they agreed upon for serializing. While $PSVersionTable will show the true version. Hope it would help someone..
Seems $host.Version isn't a good choice... If you remote to a machine running PowerShell 3, you get back 1.0, as the RemotingHost seems to be v1. Using $PSVersionTable correctly returns 3.
@Starfish The command shown launches Powershell using Command Prompt. Wouldn't the command just error out with "powershell not found" if it's not installed?
So tired of coming back here for this that I just ran notepad $profile and dumped function psver { $PSVersionTable; $PSVersionTable.PSVersion } in it. A reload with . $profile and I can just type psver any time to get the detailed version info and other details.
X
Xantium

I would use either Get-Host or $PSVersionTable. As Andy Schneider points out, $PSVersionTable doesn't work in version 1; it was introduced in version 2.

get-host

Name             : ConsoleHost
Version          : 2.0
InstanceId       : d730016e-2875-4b57-9cd6-d32c8b71e18a
UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture   : en-GB
CurrentUICulture : en-US
PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
IsRunspacePushed : False
Runspace         : System.Management.Automation.Runspaces.LocalRunspace

$PSVersionTable

Name                           Value
----                           -----
CLRVersion                     2.0.50727.4200
BuildVersion                   6.0.6002.18111
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1

thank you! NB: On my XP where I manually upgraded from v1 Powershell, the actual folder and registry paths (misleadingly?!) reference v1 NOT v2. This is as others here specify, but it was the reason why I was so worried whether I had installed it. My path is ; C:\WINDOWS\system32\windowspowershell\v1.0
If $psversiontable does not exist, it's entirely safe to assume you're on v1.0 - and hey presto, that also answers your question. $host.version is not reliable - for example in powergui, it returns the powergui host version which is not the same as the powershell engine version (which is what is desired.)
The accepted answer states "... $Host.Version and (Get-Host).Version are not reliable - they reflect the version of the host only, not the engine".
X
Xantium

You can look at the built in variable, $psversiontable. If it doesn't exist, you have V1. If it does exist, it will give you all the info you need.

1 >  $psversiontable

Name                           Value                                           
----                           -----                                           
CLRVersion                     2.0.50727.4927                                  
BuildVersion                   6.1.7600.16385                                  
PSVersion                      2.0                                             
WSManStackVersion              2.0                                             
PSCompatibleVersions           {1.0, 2.0}                                      
SerializationVersion           1.1.0.1                                         
PSRemotingProtocolVersion      2.1    

h
hichris123

To determine if PowerShell is installed, you can check the registry for the existence of

HKEY_LOCAL_MACHINE\Software\Microsoft\PowerShell\1\Install

and

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3

and, if it exists, whether the value is 1 (for installed), as detailed in the blog post Check if PowerShell installed and version.

To determine the version of PowerShell that is installed, you can check the registry keys

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine\PowerShellVersion

and

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine\PowerShellVersion

To determine the version of PowerShell that is installed from a .ps1 script, you can use the following one-liner, as detailed on PowerShell.com in Which PowerShell Version Am I Running.

$isV2 = test-path variable:\psversiontable

The same site also gives a function to return the version:

function Get-PSVersion {
    if (test-path variable:psversiontable) {$psversiontable.psversion} else {[version]"1.0.0.0"}
}

Useful because on a Windows 2003 server I couldn't find the start menu entry for PowerShell (it was there but not obvious), but the registry key answered my question.
For PowerScript 3.0 there seems to be a new entry, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3 (in addition to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1). The proper place in this case for getting the version appears to be HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine\PowerShellVersion (sample value is "3.0").
P
Peter Mortensen

You can directly check the version with one line only by invoking PowerShell externally, such as from Command Prompt

powershell -Command "$PSVersionTable.PSVersion"

According to @psaul you can actually have one command that is agnostic from where it came (CMD, PowerShell or Pwsh). Thank you for that.

powershell -command "(Get-Variable PSVersionTable -ValueOnly).PSVersion"

I've tested and it worked flawlessly on both CMD and PowerShell.

https://i.stack.imgur.com/WN2dY.png


I get this horrible error with that try: "System.Collections.Hashtable.PSVersion : The term 'System.Collections.Hashtable.PSVersion' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.". So not always works
I'm glad that you pointed that out since it's good to know the corner cases, but I guess it still works for the majority of people.
@Gonmator one would think PowerShell would behave the same way with this command, but it unfortunately does not. I made attempt to fix the syntax to work agnostically between cmd and powershell to no avail. I would have expected the same behavior as well. :)
@tresf (and @Gonmator) you CAN run this agnostically from CMD, PowerShell, or even Pwsh (PS 6.0) but you need to use this form: powershell -command "(Get-Variable PSVersionTable -ValueOnly).PSVersion" (that will work in all cases)
Tested on mac too. pwsh -Command "(Get-Variable PSVersionTable -ValueOnly).PSVersion" works great.
T
TylerH

You can verify that Windows PowerShell version installed by completing the following check:

Click Start, click All Programs, click Accessories, click Windows PowerShell, and then click Windows PowerShell. In the Windows PowerShell console, type the following command at the command prompt and then press ENTER: Get-Host | Select-Object Version

You will see output that looks like this:

Version
-------
3.0

http://www.myerrorsandmysolutions.com/how-to-verify-the-windows-powershell-version-installed/


You assume that powershell was installed with default options and that the shortcuts were not removed from the Start Menu. Better to use the registry test.
I think that if you need to use PowerShell first you try to run it as standard it should be installed, then if you don't find the icon your try to search it, then maybe you try to run it from the Command Prompt. I don't think you start from the registry.
The accepted answer states "... $Host.Version and (Get-Host).Version are not reliable - they reflect the version of the host only, not the engine".
S
Starfish

Microsoft's recommended forward compatible method for checking if PowerShell is installed and determining the installed version is to look at two specific registry keys. I've reproduced the details here in case the link breaks.

According to the linked page:

Depending on any other registry key(s), or version of PowerShell.exe or the location of PowerShell.exe is not guaranteed to work in the long term.

To check if any version of PowerShell is installed, check for the following value in the registry:

Key Location: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1

Value Name: Install

Value Type: REG_DWORD

Value Data: 0x00000001 (1

To check whether version 1.0 or 2.0 of PowerShell is installed, check for the following value in the registry:

Key Location: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine

Value Name: PowerShellVersion

Value Type: REG_SZ

Value Data: <1.0 | 2.0>


For PowerShell 3.0, there appears to be a new one, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3.
The link is dead; it says "403 Forbidden".
S
SharpC

I found the easiest way to check if installed was to:

run a command prompt (Start, Run, cmd, then OK)

type powershell then hit return. You should then get the PowerShell PS prompt:

C:\Users\MyUser>powershell

Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\MyUser>

You can then check the version from the PowerShell prompt by typing $PSVersionTable.PSVersion:

PS C:\Users\MyUser> $PSVersionTable.PSVersion

Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1

PS C:\Users\MyUser>

Type exit if you want to go back to the command prompt (exit again if you want to also close the command prompt).

To run scripts, see http://ss64.com/ps/syntax-run.html.


Like for the accepted answer this doesn't return anything for PowerShell 1.0. The registry method is more explicit.
If powershell was not in the path, this version will give a false impression that it is not installed. The Registry method gives full information. Presence and version.
P
Peter Mortensen

$host.version is just plain wrong/unreliable. This gives you the version of the hosting executable (powershell.exe, powergui.exe, powershell_ise.exe, powershellplus.exe etc) and not the version of the engine itself.

The engine version is contained in $psversiontable.psversion. For PowerShell 1.0, this variable does not exist, so obviously if this variable is not available it is entirely safe to assume the engine is 1.0, obviously.


P
Peter Mortensen

Use:

$psVersion = $PSVersionTable.PSVersion
If ($psVersion)
{
    #PowerShell Version Mapping
    $psVersionMappings = @()
    $psVersionMappings += New-Object PSObject -Property @{Name='5.1.14393.0';FriendlyName='Windows PowerShell 5.1 Preview';ApplicableOS='Windows 10 Anniversary Update'}
    $psVersionMappings += New-Object PSObject -Property @{Name='5.1.14300.1000';FriendlyName='Windows PowerShell 5.1 Preview';ApplicableOS='Windows Server 2016 Technical Preview 5'}
    $psVersionMappings += New-Object PSObject -Property @{Name='5.0.10586.494';FriendlyName='Windows PowerShell 5 RTM';ApplicableOS='Windows 10 1511 + KB3172985 1607'}
    $psVersionMappings += New-Object PSObject -Property @{Name='5.0.10586.122';FriendlyName='Windows PowerShell 5 RTM';ApplicableOS='Windows 10 1511 + KB3140743 1603'}
    $psVersionMappings += New-Object PSObject -Property @{Name='5.0.10586.117';FriendlyName='Windows PowerShell 5 RTM 1602';ApplicableOS='Windows Server 2012 R2, Windows Server 2012, Windows Server 2008 R2 SP1, Windows 8.1, and Windows 7 SP1'}
    $psVersionMappings += New-Object PSObject -Property @{Name='5.0.10586.63';FriendlyName='Windows PowerShell 5 RTM';ApplicableOS='Windows 10 1511 + KB3135173 1602'}
    $psVersionMappings += New-Object PSObject -Property @{Name='5.0.10586.51';FriendlyName='Windows PowerShell 5 RTM 1512';ApplicableOS='Windows Server 2012 R2, Windows Server 2012, Windows Server 2008 R2 SP1, Windows 8.1, and Windows 7 SP1'}
    $psVersionMappings += New-Object PSObject -Property @{Name='5.0.10514.6';FriendlyName='Windows PowerShell 5 Production Preview 1508';ApplicableOS='Windows Server 2012 R2'}
    $psVersionMappings += New-Object PSObject -Property @{Name='5.0.10018.0';FriendlyName='Windows PowerShell 5 Preview 1502';ApplicableOS='Windows Server 2012 R2'}
    $psVersionMappings += New-Object PSObject -Property @{Name='5.0.9883.0';FriendlyName='Windows PowerShell 5 Preview November 2014';ApplicableOS='Windows Server 2012 R2, Windows Server 2012, Windows 8.1'}
    $psVersionMappings += New-Object PSObject -Property @{Name='4.0';FriendlyName='Windows PowerShell 4 RTM';ApplicableOS='Windows Server 2012 R2, Windows Server 2012, Windows Server 2008 R2 SP1, Windows 8.1, and Windows 7 SP1'}
    $psVersionMappings += New-Object PSObject -Property @{Name='3.0';FriendlyName='Windows PowerShell 3 RTM';ApplicableOS='Windows Server 2012, Windows Server 2008 R2 SP1, Windows 8, and Windows 7 SP1'}
    $psVersionMappings += New-Object PSObject -Property @{Name='2.0';FriendlyName='Windows PowerShell 2 RTM';ApplicableOS='Windows Server 2008 R2 SP1 and Windows 7'}
    foreach ($psVersionMapping in $psVersionMappings)
    {
        If ($psVersion -ge $psVersionMapping.Name) {
            @{CurrentVersion=$psVersion;FriendlyName=$psVersionMapping.FriendlyName;ApplicableOS=$psVersionMapping.ApplicableOS}
            Break
        }
    }
}
Else{
    @{CurrentVersion='1.0';FriendlyName='Windows PowerShell 1 RTM';ApplicableOS='Windows Server 2008, Windows Server 2003, Windows Vista, Windows XP'}
}

You can download the detailed script from How to determine installed PowerShell version.


This breaks as soon as a version is not explicitly present in the hash table.
R
Roman Pokrovskij

The easiest way to forget this page and never return to it is to learn the Get-Variable:

Get-Variable | where {$_.Name -Like '*version*'} | %{$_[0].Value}

There is no need to remember every variable. Just Get-Variable is enough (and "There should be something about version").


Which is same as $PSVersionTable
Looking for the PS version? type $PSVersion [tab] [enter]. Done. Don't need to remember anything :)
this really only is useful if one is very familiar with the piping tricks that are used. No way a beginner is going to be able to remember that all that syntax easier than just remembering $PSVersionTable
Guys, Get-Variable works well alone (if all what you need just to get the version), piping there is just a joke :) I do not remember piping syntax either.
P
Peter Mortensen

Since the most helpful answer didn't address the if exists portion, I thought I'd give one take on it via a quick-and-dirty solution. It relies on PowerShell being in the path environment variable which is likely what you want. (Hat tip to the top answer as I didn't know that.) Paste this into a text file and name it

Test Powershell Version.cmd

or similar.

@echo off
echo Checking powershell version...
del "%temp%\PSVers.txt" 2>nul
powershell -command "[string]$PSVersionTable.PSVersion.Major +'.'+ [string]$PSVersionTable.PSVersion.Minor | Out-File ([string](cat env:\temp) + '\PSVers.txt')" 2>nul
if errorlevel 1 (
 echo Powershell is not installed. Please install it from download.Microsoft.com; thanks.
) else (
 echo You have installed Powershell version:
 type "%temp%\PSVers.txt"
 del "%temp%\PSVers.txt" 2>nul
)
timeout 15

A
Aliaksandr Belik

To check if PowerShell is installed use:

HKLM\Software\Microsoft\PowerShell\1 Install ( = 1 )

To check if RC2 or RTM is installed use:

HKLM\Software\Microsoft\PowerShell\1 PID (=89393-100-0001260-00301) -- For RC2
HKLM\Software\Microsoft\PowerShell\1 PID (=89393-100-0001260-04309) -- For RTM

Source: this website.


P
Peter Mortensen

I needed to check the version of PowerShell and then run the appropriate code. Some of our servers run v5, and others v4. This means that some functions, like compress, may or may not be available.

This is my solution:

if ($PSVersionTable.PSVersion.Major -eq 5) {
    #Execute code available in PowerShell 5, like Compress
    Write-Host "You are running PowerShell version 5"
}
else {
    #Use a different process
    Write-Host "This is version $PSVersionTable.PSVersion.Major"
}

M
Martin Prikryl

PowerShell 7

The accepted answer is only appropriate if one version of PowerShell is installed on a computer. With the advent of PowerShell 7, this scenario becomes increasingly unlikely.

Microsoft's documentation states that additional registry keys are created when PowerShell 7 is installed:

Beginning in PowerShell 7.1, the [installer] package creates registry keys that store the installation location and version of PowerShell. These values are located in HKLM\Software\Microsoft\PowerShellCore\InstalledVersions\. The value of is unique for each build type (release or preview), major version, and architecture.

Exploring the registry in the aforementioned location reveals the following registry value: SemanticVersion. This value contains the information we seek.

On my computer it appears like the following:

Path                                                                                           Name              Type Data
----                                                                                           ----              ---- ----
HKLM:\SOFTWARE\Microsoft\PowerShellCore\InstalledVersions\31ab5147-9a97-4452-8443-d9709f0516e1 SemanticVersion String 7.1.3

https://i.stack.imgur.com/uRpmX.png

As you can see, the version of PowerShell 7 installed on my computer is 7.1.3. If PowerShell 7 is not installed on the target computer, the key in its entirety should not exist.

As mentioned in the Microsoft documentation, the registry path will be slightly different dependent on installed PowerShell version.

Part of the key path changing could pose a challenge in some scenarios, but for those interested in a command line-based solution, PowerShell itself can handle this problem easily.

The PowerShell cmdlet used to query the data in this registry value is the Get-ItemPropertyValue cmdlet. Observe its use and output as follows (note the asterisk wildcard character used in place of the part of the key path that is likely to change):

PS> Get-ItemPropertyValue -Path "HKLM:\SOFTWARE\Microsoft\PowerShellCore\InstalledVersions\*" -Name "SemanticVersion"

7.1.3

Just a simple one-liner.


P
Peter Mortensen

The below cmdlet will return the PowerShell version.

$PSVersionTable.PSVersion.Major

$PSVersionTable is an automatic variable; an object. It is not a cmdlet.
M
Martin Prikryl

This is the top search result for "Batch file get powershell version", so I'd like to provide a basic example of how to do conditional flow in a batch file depending on the powershell version

Generic example

powershell "exit $PSVersionTable.PSVersion.Major"
if %errorlevel% GEQ 5 (
    echo Do some fancy stuff that only powershell v5 or higher supports
) else (
    echo Functionality not support by current powershell version.
)

Real world example

powershell "exit $PSVersionTable.PSVersion.Major"
if %errorlevel% GEQ 5 (
    rem Unzip archive automatically
    powershell Expand-Archive Compressed.zip
) else (
    rem Make the user unzip, because lazy
    echo Please unzip Compressed.zip prior to continuing...
    pause
)

I love the premise of this. I never thought to return a "non-error" value in this way as an exit code. The only thing I'd worry about here is what %errorlevel% could be when anything unexpected goes wrong, like powershell is not on the path, or $PSVersionTable.PSVersion.Major can't be resolve (which would happen on PS v1), etc.?
Yes, good point. This solution is certainly naive in that aspect. In our organization, we were certain that only v4 and v5 were in play.
P
Peter Mortensen

You can also call the "host" command from the PowerShell commandline. It should give you the value of the $host variable.


This is semi-wrong. host resolves to Get-Host. Regardless, it is not a reliable way to get the version.
D
Dut A.

I tried this on version 7.1.0 and it worked:

$PSVersionTable | Select-Object PSVersion

Output

PSVersion
---------
7.1.0

It doesn't work on version 5.1 though, so rather go for this on versions below 7:

$PSVersionTable.PSVersion

Output

Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      18362  1171

EDIT

As of PowerShell 7.2.5, you can now do:

pwsh -v

Or

pwsh --version

Output

PowerShell 7.2.5

This appears to just repeat information already shared in multiple answers. Please only add new answers when there is new information.
@TylerH, would you mind pointing me to an answer with PowerShell 7? Scanning around, the last answer before mine was in 2016 and v7.1 is pretty new.
Your first solution essentially duplicates the answer from March 2014 by @Eclipses, and your second solution duplicates the accepted answer. If you wish to highlight that they do or don't work for PowerShell 7, perhaps add a comment to those answers instead.
@Bren0man, the command wording in @Eclipses' version (Get-Host | Select-Object Version) alone is enough to make it different. Plus I don't know whether there was Powershell 7 in 2014. Second version may be a duplicate just to keep alternatives in one place but my main point is in the first version.
P
Peter Mortensen

Extending the answer with a select operator:

Get-Host | select {$_.Version}

The accepted answer states "... $Host.Version and (Get-Host).Version are not reliable - they reflect the version of the host only, not the engine".
@PeterMortensen looks like my answer was before accepted answer
@HaBo What are you looking at? The accepted answer is from 2009.
@TylerH so what? I am not following your question. my answer clearly says its a extension to the accepted answer. its a simplified version.
@HaBo Your previous comment reads like you're justifying your answer by the fact that it was posted before the accepted answer, which is not at all the case. Your answer was posted 7 years after the accepted answer, and 6 years after the answer yours actually 'extends'; speaking of which, your answer does not clearly say it's an extension of the accepted answer (which doesn't even use Get-Host).
T
TylerH

I have made a small batch script that can determine PowerShell version:

@echo off
for /f "tokens=2 delims=:" %%a in ('powershell -Command Get-Host ^| findstr /c:Version') do (echo %%a)

This simply extracts the version of PowerShell using Get-Host and searches the string Version

When the line with the version is found, it uses the for command to extract the version. In this case we are saying that the delimiter is a colon and search next the first colon, resulting in my case 5.1.18362.752.