50

How can I determine the OS type, (Linux, Windows) using Powershell from within a script?

The ResponseUri isn't recognised when this part of my script is ran on a Linux host.

$UrlAuthority = $Request.BaseResponse | Select-Object -ExpandProperty ResponseUri | Select-Object -ExpandProperty Authority

So I want an If statement to determine the OS type that would look similar to this:

If ($OsType -eq "Linux")
{
     $UrlAuthority = ($Request.BaseResponse).RequestMessage | Select-Object -ExpandProperty RequestUri | Select-Object -ExpandProperty host
}
Else
     $UrlAuthority = $Request.BaseResponse | Select-Object -ExpandProperty ResponseUri | Select-Object -ExpandProperty Authority

I could use Get-CimInstance Win32_OperatingSystem but it would fail on Linux as it's not recognised.

Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
boomcubist
  • 770
  • 1
  • 7
  • 15
  • doesn't `get-host` contain that data? – 4c74356b41 Jun 22 '17 at 15:33
  • [This may be useful](http://www.sqlserver-dba.com/2012/06/how-to-check-operating-system-type-with-powershell.html) – G42 Jun 22 '17 at 15:38
  • Not that I can tell. Nor from the documentation [link](https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.utility/get-host) – boomcubist Jun 22 '17 at 15:38

10 Answers10

77

Aren't there environment variables you can view on the other platforms for the OS?

Get-ChildItem -Path Env:

Particularly, on Windows at least, there's an OS environment variable, so you should be able to accomplish this by using $Env:OS.


Since some time has passed and the PowerShell Core (v6) product is GA now (the Core branding has been dropped as of v7), you can more accurately determine your platform based on the following automatic boolean variables:

$IsMacOS
$IsLinux
$IsWindows
Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
  • I tried this initially, and it returned "Windows_NT" on my Windows 8.1 machine... I assume that OP is after more detail. – G42 Jun 22 '17 at 15:37
  • 1
    @gms0ulman It looks like it reports Windows_NT on any Windows box. I think OP is looking for one versus the other since he wasn't asking something along the lines of "Am I on Windows 10 or Ubuntu?" – Maximilian Burszley Jun 22 '17 at 15:41
  • This is perfect. I can do this `If ("$($ENV:OS)" -ne $null)` - it returns null on Linux, so if it's not null it's Windows! Thanks. – boomcubist Jun 22 '17 at 15:46
  • @boomcubist You can simplify that more such as: `If ($env:OS -ne $null)` I would suggest using `GCI ENV:` at the prompt just to see if there's an OS-type environment variable to be more granular in your checking – Maximilian Burszley Jun 22 '17 at 15:49
  • @TheIncorrigible1 Well spotted - I was over-complicating it – G42 Jun 22 '17 at 15:51
  • 2
    @boomcubist I thought of an even simpler check (and was unable to edit my other comment): `If ($env:OS)` since it only has two states – Maximilian Burszley Jun 22 '17 at 15:56
  • @TheIncorrigible1 You're awesome. That's perfect. Thanks again. – boomcubist Jun 22 '17 at 15:59
  • PowerShell 6 on Linux does not have a `Env:OS` variable. `$PSVersionTable` has `OS` and `Platform` attributes. These are also available in PowerShell 6 on Windows. – lit Jun 22 '17 at 21:20
  • 10
    Use `[System.Environment]::OSVersion.Platform`. It is documented on [MSDN for and appears to be present in all .NET versions (1.1, 2.0, 3.0, 3.5, and the current version)](https://msdn.microsoft.com/en-us/library/system.environment.osversion%28v=vs.110%29.aspx). `$PSVersionTable.Platform` [returns that value in PowerShell 6 Core](https://learn.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-core-60?view=powershell-6#engine-updates). It will be `Win32NT` on Windows or `Unix` on Linux and macOS. – Dave F May 04 '18 at 00:56
  • 5
    @DaveF Since PSv6 has gone GA, there are now `$IsMacOS` and `$IsLinux` automatic variables where you can determine your OS. – Maximilian Burszley May 04 '18 at 01:07
  • I had seen the Issues posted on GitHub where there was debate about introducing those variables, but I wasn't aware that they were in the final release. – Dave F May 06 '18 at 03:30
  • 1
    Also, it's worth mentioning that `$IsWindows` can be used to determine if the OS is Windows. However, this variable will evaluate to false on older versions of PowerShell so it should only be used if scripts are intended to be used with newer releases. – Dave F May 06 '18 at 03:35
  • @DaveF Thanks for the clarification. I've edited my answer to be more complete now that the 6.0 version is finalized (seeing as work towards 6.1 GA is happening) – Maximilian Burszley Jul 25 '18 at 13:50
  • The method provided by @DaveF seems to be the most universal across Windows PS, PS Core Linux/Windows/Azure. The other methods are not consistently implemented across all OSes, PS version. For example $IsWindows doesn't work in Windows PS 5.1, nor does $PSVersionTable report an OS property. $env:OS doesn't work in PS Core on linux (or Azure Cloud Shell) – BHall Jun 02 '19 at 04:05
  • @BHall for the purpose of this question, you would branch twice. Check the version for v6+ and then you could use the solutions in my answer. If you're on a version below that, you're on Windows by default. – Maximilian Burszley Jun 02 '19 at 04:40
  • `$Env:` isn't a really viable solution cross-platform because it lacks reliable fields cross-platfrom for the detection. Although to that point, I'd like to recant my downvote (impossible now), since non-Windows platform will most likely have `$IsMacOS` and friends, making the proposed solutions viable when combined. – tresf Jan 19 '23 at 05:11
19

For PowerShell Core (Powershell Version 6.0+), you can use Automatic Variables: $IsLinux, $IsMacOS and $IsWindows.

For example,

if ($IsLinux) {
    Write-Host "Linux"
}
elseif ($IsMacOS) {
    Write-Host "macOS"
}
elseif ($IsWindows) {
    Write-Host "Windows"
}
zwcloud
  • 4,546
  • 3
  • 40
  • 69
15

Since the PowerShell versions 6.1 on Windows/Linux/OSX went to GA you can use the new properties of $PSVersionTable, OS, Platform and GitCommitId

Update In v6.0.0-beta.3 there are some breaking changes:

  • Change positional parameter for powershell.exe from -Command to -File

$PSVersionTable on :

Platform Win32NT OS Microsoft Windows 10.0.15063

PS C:\Users\LotPings> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.1.0
PSEdition                      Core
GitCommitId                    6.1.0
OS                             Microsoft Windows 10.0.17134
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Platform Unix OS Linux (ubuntu)

PS /home/LotPings> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.1.0
PSEdition                      Core
GitCommitId                    6.1.0
OS                             Linux 4.15.0-34-generic #37-Ubuntu SMP Mon Aug 27 15:21:48 UTC 2018
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Platform Unix OS Darwin

PS /Users/LotPings> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.1.0
PSEdition                      Core
GitCommitId                    6.1.0
OS                             Darwin 17.7.0 Darwin Kernel Version 17.7.0: Thu Jun 21 22:53:14 PDT 2018; root:xnu-4570.71.2~1/RE...
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0
  • 2
    This won't help when running on PowerShell before version 6. – lit Jun 22 '17 at 21:22
  • 1
    @lit The absence/presence of `$env:OS` will tell something different as the absence/presence of `$PSVersionTable.Os` or `$PSVersionTable.Platform` –  Jun 23 '17 at 10:00
  • 1
    @LotPings - Yes, it might be possible to decipher the platform from some broad collection of things present and things not. Sounds like temperamental code to write and even more temperamental to maintain. – lit Jun 23 '17 at 13:31
  • 3
    @lit I believe that `[System.Environment]::OSVersion.Platform` works for all versions. See my comment for the accepted answer. – Dave F May 04 '18 at 00:59
  • 1
    @lit, seems like we always have to work backwards anyways... code tries to assume it's on latest-and-greatest, and work backwards to some level of "I can't work in this environment. Please upgrade". On Windows, $PSVersionTable isn't in Powershell 1.0. So, kludgey as it is, checking if $PSVersionTable exists works as a cheap-and-dirty check for Powershell 1.0, which didn't really come with a convenient way to check like $PSVersionTable provides now. – user1390375 Jun 02 '18 at 23:53
9

Prior to PowerShell [Core] version 6, this was only possible by asking .NET directly. This can be done with one line:

[System.Environment]::OSVersion.Platform

This will return either Win32NT for anything descended from Windows NT (all current versions of Windows) or Unix for anything *nix (including Mac, Linux, &c.). If it returns Unix then you're obviously running v6+, so further information can be had from $PSVersionTable.PSEdition, $PSVersionTable.Platform, and $PSVersionTable.OS, and the automatic variables will be available too: $IsLinux, $IsMacOs, and $IsWindows.

Here's what I have in my profile.ps1 to make this easier by setting $IsWindows:

function Get-PSPlatform
{
    return [System.Environment]::OSVersion.Platform
}
switch (Get-PSPlatform)
{
    'Win32NT' { 
        New-Variable -Option Constant -Name IsWindows -Value $True -ErrorAction SilentlyContinue
        New-Variable -Option Constant -Name IsLinux  -Value $false -ErrorAction SilentlyContinue
        New-Variable -Option Constant -Name IsMacOs  -Value $false -ErrorAction SilentlyContinue
     }
}

This works in all versions of PowerShell as this has been available from .NET since version 1.x. See PlatformID documentation for details.

— Please see Dave F's comment; I wrote this answer because that seems how SO works to get an answer promoted from a comment.

gaelicWizard
  • 121
  • 1
  • 5
6

Actually, there should be global variables added by the PowerShell console itself--they're not considered environment variables though, which is why they wouldn't show up when using dir env: to get a list.The OS-specific ones I see for now are $IsLinux, IsMacOS and $IsWindows. This is of at least PowerShell version 6.0.0-rc and above for Mac/Linux.

You can see a list of what's available by using just Get-Variable (in a fresh session without loading your profile, if you just want what comes build-in by default).

areyling
  • 2,181
  • 2
  • 20
  • 25
6

Building on the above, if you only want to detect whether or not you're running under Windows, and you want a script that's forwards and backwards compatible in PowerShell and PowerShell Core, there's this:

if ($IsWindows -or $ENV:OS) {
    Write-Host "Windows"
} else {
    Write-Host "Not Windows"
}
MCattle
  • 2,897
  • 2
  • 38
  • 54
3

When you only have to check if it is windows or linux, maybe you could use this (quick and dirty):

if ([System.Boolean](Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction SilentlyContinue))
{
    #windows
}
else
{
    #Not windows
}
Patrick
  • 2,128
  • 16
  • 24
1

Some more ways for Osx:

sw_vers -productVersion

10.12.6

Or (there's a "key - os_version" right above it, but I don't see how they relate):

[xml]$xml = system_profiler SPSoftwareDataType -xml   
$xml.plist.array.dict.array.dict.string -match 'macos'  

macOS 10.12.6 (16G1510)
js2010
  • 23,033
  • 6
  • 64
  • 66
1

This will work in any version of Powershell for the problems described in the comments on other answers.

$iswin = $PSVersionTable.Platform -match '^($|(Microsoft )?Win)'

With $False being 'nix.

Hashbrown
  • 12,091
  • 8
  • 72
  • 95
  • Something wrong with this one. `$PSVersionTable.Platform` returns $null on Win 11 and `$PSVersionTable.Platform -match '^($|(Microsoft )?Winadfsdfsd)'` returns true. – duct_tape_coder Apr 20 '23 at 20:35
  • Nope, that's working. Returned true and you're on windows. All linux versions have the string populated, and some windows do. I've set it up in a way that it'll work in all three cases – Hashbrown Apr 21 '23 at 01:23
  • @duct_tape_coder – Hashbrown Apr 21 '23 at 01:46
0

I you don't have the latest PowerShell core installed you can use a small scriptblock like:

if ($PSVersionTable.PSVersion.Major -lt 6.0) {
    switch ($([System.Environment]::OSVersion.Platform)) {
        'Win32NT' { 
            New-Variable -Option Constant -Name IsWindows -Value $True -ErrorAction SilentlyContinue
            New-Variable -Option Constant -Name IsLinux -Value $false -ErrorAction SilentlyContinue
            New-Variable -Option Constant -Name IsMacOs -Value $false -ErrorAction SilentlyContinue
        }
    }
}
$script:IsLinuxEnv = (Get-Variable -Name "IsLinux" -ErrorAction Ignore) -and $IsLinux
$script:IsMacOSEnv = (Get-Variable -Name "IsMacOS" -ErrorAction Ignore) -and $IsMacOS
$script:IsWinEnv = !$IsLinuxEnv -and !$IsMacOSEnv
alainQtec
  • 41
  • 5