Exchange major/minor versions not passed remotely

Hi, I am troubleshooting an Exchange script for migrating public folders. The script is failing to pass the minimum version check of the Exchange servers. I noticed that running (Get-ExchangeServer EX01).AdminDisplayVersion.Major returns a valid value when run from within EMS on an Exchange server, but does not return any value at all when run using remote PowerShell.

I have also noticed that (Get-ExchangeServer EX01).AdminDisplayVersion will work using remote PowerShell, its only when I try to append .Major, .Minor, or .Build that the commands seem to require local execution or from within EMS as opposed to using Import-PSSession.

Is there anyway to get this command to work using remote PowerShell?


I should add that when I run (Get-ExchangeServer EX01).AdminDisplayVersion from EMS on an Exchange server, I get this output:

Major : 15
Minor : 0
Build : 1263
Revision : 5
FilePatchLevelDescription :

But, when I run it from a remote PowerShell session, I get this output:

(Get-ExchangeServer -Identity EX01).AdminDisplayVersion
Version 15.0 (Build 1263.5)

I see the same thing you do. I’m not sure eactly why there is that difference, but I can tell you a few things.

  1. The EMS runs in PowerShell. If you look at the properties of the EMS you’ll see, in the Target field, that powershell.exe is being run.

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -command ". ‘C:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1’; Connect-ExchangeServer -auto -ClientApplication:ManagementShell "

  1. As you can also see above, it runs a script, in PowerShell, and then a command called Connect-ExchangeServer. This causes additional configuration to be done beyond what you’d see just doing a PSSession to an Exchange server from Windows PowerShell.
  2. If you pipe the results of the Get-ExchangeServer cmdlet to Get-Member, like below, you’ll see that in a PSSession, it comes back as a deserialized object, so it’s just text. When you do it from the EMS, it comes back as an ExchangeServer object.

–From: RPSSession in Windows PowerShell (Connect to Exchange servers using remote PowerShell)

Get-ExchangeServer Server1 | Get-Member

TypeName: Deserialized.Microsoft.Exchange.Data.Directory.Management.ExchangeServer

–From EMS:

Get-ExchangeServer Server1 | Get-Member

TypeName: Microsoft.Exchange.Data.Directory.Management.ExchangeServer

I’ve not yet figured if/how you can use Invoke-Command to get the same data back that the EMS gets you locally, but I did figure out a way for you to get the Major version in another way.

$AdminDisplayVersion = (Get-ExchangeServer Server1).AdminDisplayVersion
$MajorVersion = ($AdminDisplayVersion -split " ")[1].Substring(0,2)

Thanks, Kevyn, for confirming the problem I was reporting, and for the suggested workaround. I think I should be able to get by with this, but in addition to the Major version, I also need the Minor version and the Build.

I am trying to decipher what you provided and re-write it to provide these other two values, but if you could assist, I’d really appreciate it, or point me to an article that explains the method for doing it. Thanks again!

You could try the following to get the complete version info

Get-ExchangeServer |
ForEach-Object {
Invoke-Command -ComputerName _.Name {Get-Command Exsetup.exe | ForEach{_.FileVersionInfo}}

In order to get the Minor version:

$MinorVersion = ($AdminDisplayVersion -split " ")[1].Substring(3)

In order to get the Build:

$Build = ($AdminDisplayVersion -split " ")[3].Trim(")")

So, now let me break down the whole thing and how I got the pieces.

  1. How I got the Major version:

–First, I got the AdminDisplayVersion, where everything else starts from. I get the string back.

$AdminDisplayVersion = (Get-ExchangeServer Server1).AdminDisplayVersion

Version 15.0 (Build 1320.4) <--String I'm starting with.

–Next, I use the -split operator to split/cut up the string above into multiple pieces (i.e. an array of strings). I’m splitting the string up using the space character.

$AdminDisplayVersion -split " ")


–Next I’m telling PowerShell that I want the second string in the array, which will be at index 1 (since array indexes always start at 0)

($AdminDisplayVersion -split " ")[1]


–Not sure why, but I couldn’t split that string (i.e. “15.0”) into two strings using the period (.) as the character to split the string on, so I told PowerShell that I wanted a substring of the string that started at position 0 (i.e. where the “1” is in the “15.0” string and that I wanted the substring to be 2 characters in length.

$MajorVersion = ($AdminDisplayVersion -split " ")[1].Substring(0,2)

  1. How I got the Minor version.

–Getting the Minor version works the same as getting the Major version except that this time I told PowerShell that the substring that I wanted (i.e. from the “15.0” string) started at an index of 3 (i.e. where the “0” in the “15.0” string is). By not specifying how long (i.e. how many characters) I wanted the substring to be, it gave me everything from the “0” till the end of the string, which in this case is just the “0”. However, if the original string was “15.1234” (w/o the quotes of course), then the below code would have given me a result of “1234”.

$MinorVersion = ($AdminDisplayVersion -split " ")[1].Substring(3)

  1. How I got the Build.

–From the split of the string in the $AdminDisplayVersion, this time I told PowerShell that I wanted the 4th entry that is at index of 3.

($AdminDisplayVersion -split " ")[3]


–Then I just told PowerShell to trim the closing parenthesis off the end.

$Build = ($AdminDisplayVersion -split " ")[3].Trim(")")


So, to put it all together:

$AdminDisplayVersion = (Get-ExchangeServer Server1).AdminDisplayVersion
$MajorVersion = ($AdminDisplayVersion -split " ")[1].Substring(0,2)
$MinorVersion = ($AdminDisplayVersion -split " ")[1].Substring(3)
$Build = ($AdminDisplayVersion -split " ")[3].Trim(")")

Hope that helps and that my explanation makes sense.

I figured how to split on a period (.). The period is a special character in a RegEx expression. The backslash () causes PowerShell to “escape” on the period so that it’s not used as a special character.

$Version = (($AdminDisplayVersion -split " ")[1]
$MajorVersion = ($Version -Split "\.")[0]
$MinorVersion = ($Version -Split "\.")[1]

So, the “new” whole thing is:

$AdminDisplayVersion = (Get-ExchangeServer Server1).AdminDisplayVersion
$Version = (($AdminDisplayVersion -split " ")[1]
$MajorVersion = ($Version -Split "\.")[0]
$MinorVersion = ($Version -Split "\.")[1]
$Build = ($AdminDisplayVersion -split " ")[3].Trim(")")

Yes, that makes perfect sense. And, wow, this was a really great lesson for me. Thanks a lot of taking the time to explain it! Now, I can continue with my project :slight_smile:

Did you try the solution I posted up there? You wouldn’t have to deal with string / regex operations!!

Hi Olaf, thanks for the post. I had actually tried that prior to my original post here yesterday, but I receive “Access is denied” when I try to run Invoke-Command.

Hey Adam. Glad I could help.

A slight tweak on the code to get the Build. I accidentally included the Revision piece (i.e. the “4” in the “1320.4” I was showing earlier). The Build is just the “1320” piece.

$Build = (($AdminDisplayVersion -split " ")[3] -split "\.")[0]

So, the (hopefully) final “new” thing:

$AdminDisplayVersion = (Get-ExchangeServer Server1).AdminDisplayVersion
$Version = (($AdminDisplayVersion -split " ")[1]
$MajorVersion = ($Version -split "\.")[0]
$MinorVersion = ($Version -split "\.")[1]
$Build = (($AdminDisplayVersion -split " ")[3] -split "\.")[0]

Of course you need to run this with in elevated powershell console with the right account with access to the Exchange server.

And … another version of your approach could be this:

(Get-ExchangeServer ).admindisplayversion -match ‘Version\s+(?<>\d*).{1}(?<>\d*)\s+(Build\s+(?<>\d*).{1}(?<>\d*))’
[VERSION]$ExchangeVersion = $Matches.Major + ‘.’ + $Matches.Minor + ‘.’ + $Matches.Build + ‘.’ + $Matches.REvision

Unfortunately the named regex will not show up here in the code box. So you have to put Major, Minor, Build an Revision in this order between the <>