2

I maintain a diagnostic that programmatically determines the version of MS Office applications, including Excel and Word. It has worked correctly for MS Office versions 2003, 2007, 2010, 2013, and 2016. But now I find that it incorrectly reports MS Office 2019 applications as MS Office 2016.

Eight years ago, M. A. Hanin posted a similar question:

Identifying Excel version programmatically

mathieu's reply, the accepted answer, correlated numbers used to identify MS Office in the registry versus the product versions. For instance, the number 14.0 corresponded to Office 2010. Doug Glancy directly addressed the question with VB code that prints the version property of Excel Application object:

https://learn.microsoft.com/en-us/office/vba/api/excel.application.version

Here is a VB Script that diagnoses which, if any, version of Excel is installed to the system:

On Error Resume Next
Set excelApp = CreateObject("Excel.Application") 
If Err.Number <> 0 Then
    WScript.Echo "Excel is not installed"
Else
    Wscript.Echo "Excel Version: " & excelApp.Version 
End If

The diagnostic faithfully reports MS Office versions consistent with the post from 2011. Since then, it reports 15.0 for Office 2013, and 16.0 for Office 2016. Recently, though, I was surprised to find that it also reports 16.0 for Office 2019. That is just not right! The 2016 and 2019 feature sets are clearly distinct, so they should not be lumped together:

https://support.office.com/en-us/article/what-s-new-in-office-2019-5077cbbe-0d94-44cc-b30e-654e37629b0c?ui=en-US&rs=en-US&ad=US

Is there an alternate way to programmatically distinguish Office 2016 from Office 2019?

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • Not at the moment. https://www.asap-utilities.com/blog/index.php/2018/10/05/application-version-is-the-new-excel-2019-the-same-as-excel-2016/ – Michal Rosa Apr 03 '19 at 01:47
  • https://stackoverflow.com/questions/3266675/how-to-detect-installed-version-of-ms-office – Michal Rosa Apr 03 '19 at 01:47
  • Have you tried to just run one of the new features instead of CreateObject? E.g. Concat instead of Concatenate? If Err.Number <> 0 then, it's not Excel 2019. – TylerH Apr 05 '19 at 20:53
  • @TylerH, I think that would perform nicely as an interim workaround. But wouldn't that break once MSO 2022 is released? – Snaps-a-Lot Apr 05 '19 at 21:23
  • @Snaps-a-Lot Office 2019 is going to be the last standalone version of Office. I remember reading this when they announced 2019's existence, and it sounds pretty likely considering Office 2019 only gets 2 years of extended support instead of the usual 5 years for previous versions. This means Office 2016 and Office 2019 will both "officially" die in 2025, (at which point Office 365 will have been around for **14 years**). If Microsoft changes its mind and release an Office 2022 (and that's a big if), it's unlikely that it, *too*, would still be labeled as major version 16.0. – TylerH Apr 05 '19 at 21:31

4 Answers4

0

A workaround is to parse the version number from output of the MS Office Client Software License Management Tool, OSPP.VBS, run with the /dstatus option. Here is a sample CMD script that demonstrates the workaround:

:: GetOfficeVer.cmd - Print the version of a licensed MS Office package.
::   Prerequisite:
::      Copy this cmd script to a folder including these MS Office files:
::          * OSPP.VBS    - MS Office Software Protection Platform script.
::          * OSPP.HTM    - Help file for OSPP.VBS.
::          * SLERROR.XML - Data file for OSPP.VBS.
::   Syntax:
::      GetOfficeVer [ComputerName[ PackageAbbr]]
::        ComputerName    - Windows system name  (defaults to local system)
::        PackageAbbr     - Package abbreviation (list below is not exhaustive)
::          *  ProPlus    - Office Professional Plus (default)
::          *  VisioPro   - Visio Professional
::          *  InfoPath   - InfoPath Designer
::   Return Values:
::          *  If the package is licensed, print the MS Office package version
::             string using the MS Office Application.Version property format.
::          *  If the package is unlicensed, print an empty line.
@echo off
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
if %2_==_ (set MSO_PKG=ProPlus) else (set MSO_PKG=%2)
set "MSO_PKG_LIC=cscript "%~dp0\OSPP.VBS" /dstatus %1 | findstr /R /C:"^LICENSE NAME:.*%MSO_PKG%""
for /f "tokens=1-4 delims=, " %%G in ('!MSO_PKG_LIC!') do (set MSO_VER=%%J)
if %MSO_VER%_==_ (echo.) else ( echo %MSO_VER%.0)
endlocal

Tips on using OSPP.VBS:

  • It can take a few seconds to execute.
  • It is included in the folder stored in the Application.Path property.
  • It does not require MS Office to be installed to the system it is run from.
  • It does not need to be run as elevated for this purpose.
  • It will fail if the target system is in need of a restart.
  • The versions with 2013, 2016, and 2019 each work versus all three versions.
0

Yes, v16 can be 2016 or 2019

This works for version for me.

:GetOfficeVer
set vbs="%temp%\_.vbs"
if exist %vbs% del /f /q %vbs%
    >%vbs% @echo off
    >>%vbs% echo Option Explicit ' Enforce variable declaration
    >>%vbs% echo Dim oShell
    >>%vbs% echo Dim lOfficeVersion
    >>%vbs% echo Set oShell = CreateObject("WScript.Shell")
    >>%vbs% echo On Error Resume Next
    >>%vbs% echo lOfficeVersion = GetOfficeVersionNumber() 
    >>%vbs% echo MsgBox "OfficeVersion = " ^& lOfficeVersion
    >>%vbs% echo     Function GetOfficeVersionNumber()
    >>%vbs% echo         GetOfficeVersionNumber = "" 
    >>%vbs% echo         Dim sTempValue
    >>%vbs% echo         sTempValue = oShell.RegRead("HKCR\Excel.Application\CurVer\")
    >>%vbs% echo         If Len(sTempValue) ^> 2 Then GetOfficeVersionNumber = Replace(Right(sTempValue, 2), ^".^", ^"^")
    >>%vbs% echo     End Function   
cscript //nologo %vbs%
pause
if exist %vbs% del /f /q %vbs%
endlocal
goto :EOF
shadow2020
  • 1,315
  • 1
  • 8
  • 30
0

To expand the answers already given, it looks like OSPP.VBS is sadly the sanest way to get the info we need to differentiate between Office 2016, 2019, and 365.

Instead of executing cscript OSPP.VBS /dstatus, it's possible to get the same information by implementing the WMI queries used by OSPP.VBS ourselves (here in C#):

// Implementation is based on the OSPP.VBS file in the Office directory,
// when it executes the /dstatus command...
// result examples:
// - Office 16, Office16StandardVL_MAK edition
// - Office 19, Office19Standard2019VL_KMS_Client_AE edition
// - Office 16, Office16O365ProPlusR_Subscription1 edition
// - Office 15, OfficeStandardVL_MAK edition

// This constant is apparently the same for all Office versions:
const string officeAppId = "0ff1ce15-a989-479d-af46-f275c6370663";

// Note: OSPP.VBS uses == instead of <= but it seems wrong...
string productClass;
if (Environment.OSVersion.Version <= new Version(6, 1)) // Windows 7 or below
    productClass = "OfficeSoftwareProtectionProduct";
else
    productClass = "SoftwareLicensingProduct";

// Get the product name for all Office products having a product key:
var query = $"SELECT Name FROM {productClass} where "
+ $"ApplicationID=\"{officeAppId}\" AND PartialProductKey <> NULL AND PartialProductKey <> \"\"";

using (var searcher = new System.Management.ManagementObjectSearcher(query))
{
    var result = new List<string>();
    foreach (var instance in searcher.Get())
    {
        result.Add(instance.Properties["Name"].Value?.ToString() ?? "Null");
    }
    
    // result now contains a list of license names with the same format as `cscript OSPP.VBS /dstatus`
}
Melvyn
  • 622
  • 10
  • 11
-1

You could try to parse excelApp.Path to find out the installation path. This would work if the new office is installed in C:* \Office 19\Excel.exe

Alex M
  • 141
  • 2
  • 6
  • Office 2019 is staying at major version 16.0: https://learn.microsoft.com/en-us/deployoffice/office2019/overview so install paths will likely be the same. – TylerH Apr 05 '19 at 20:52