如何以编程方式区分 Excel 2019 和 2016?
How to programmatically distinguish Excel 2019 from 2016?
我维护一个诊断程序,它以编程方式确定 MS Office 应用程序的版本,包括 Excel 和 Word。它适用于 MS Office 版本 2003、2007、2010、2013 和 2016。但现在我发现它错误地将 MS Office 2019 应用程序报告为 MS Office 2016。
八年前,M. A. Hanin post提出了一个类似的问题:
Identifying Excel version programmatically
mathieu 的回复,接受的答案,用于在注册表中识别 MS Office 与产品版本的相关数字。例如,数字 14.0 对应于 Office 2010。Doug Glancy 直接用 VB 打印 Excel 应用程序对象的 属性 版本的代码解决了这个问题:
https://docs.microsoft.com/en-us/office/vba/api/excel.application.version
这是一个 VB 脚本,用于诊断 Excel 的哪个版本(如果有)安装到系统中:
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
诊断忠实地报告 MS Office 版本与 2011 年的 post 一致。从那时起,它报告 Office 2013 为 15.0,Office 2016 为 16.0。不过最近,我惊讶地发现它还报告了 Office 2019 的 16.0。那是不对的! 2016 年和 2019 年的特征集明显不同,因此不应将它们混为一谈:
是否有其他方法以编程方式区分 Office 2016 和 Office 2019?
解决方法是使用 /dstatus 选项从 MS Office 客户端软件许可证管理工具 OSPP.VBS、运行 的输出中解析版本号。这是一个演示解决方法的示例 CMD 脚本:
:: 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.
您可以尝试解析excelApp.Path找出安装路径。
如果新办公室安装在 C:* \Office 19\Excel.exe
中,这将起作用
是的,v16 可以是 2016 或 2019
这适用于我的版本。
: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
为了扩展已经给出的答案,遗憾的是,看起来 OSPP.VBS
是获取我们需要区分 Office 2016、2019 和 365 的信息的最明智的方式。
不是执行 cscript OSPP.VBS /dstatus
,而是可以通过实现 OSPP.VBS 我们自己使用的 WMI 查询(此处在 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`
}
我维护一个诊断程序,它以编程方式确定 MS Office 应用程序的版本,包括 Excel 和 Word。它适用于 MS Office 版本 2003、2007、2010、2013 和 2016。但现在我发现它错误地将 MS Office 2019 应用程序报告为 MS Office 2016。
八年前,M. A. Hanin post提出了一个类似的问题:
Identifying Excel version programmatically
mathieu 的回复,接受的答案,用于在注册表中识别 MS Office 与产品版本的相关数字。例如,数字 14.0 对应于 Office 2010。Doug Glancy 直接用 VB 打印 Excel 应用程序对象的 属性 版本的代码解决了这个问题:
https://docs.microsoft.com/en-us/office/vba/api/excel.application.version
这是一个 VB 脚本,用于诊断 Excel 的哪个版本(如果有)安装到系统中:
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
诊断忠实地报告 MS Office 版本与 2011 年的 post 一致。从那时起,它报告 Office 2013 为 15.0,Office 2016 为 16.0。不过最近,我惊讶地发现它还报告了 Office 2019 的 16.0。那是不对的! 2016 年和 2019 年的特征集明显不同,因此不应将它们混为一谈:
是否有其他方法以编程方式区分 Office 2016 和 Office 2019?
解决方法是使用 /dstatus 选项从 MS Office 客户端软件许可证管理工具 OSPP.VBS、运行 的输出中解析版本号。这是一个演示解决方法的示例 CMD 脚本:
:: 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.
您可以尝试解析excelApp.Path找出安装路径。 如果新办公室安装在 C:* \Office 19\Excel.exe
中,这将起作用是的,v16 可以是 2016 或 2019
这适用于我的版本。
: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
为了扩展已经给出的答案,遗憾的是,看起来 OSPP.VBS
是获取我们需要区分 Office 2016、2019 和 365 的信息的最明智的方式。
不是执行 cscript OSPP.VBS /dstatus
,而是可以通过实现 OSPP.VBS 我们自己使用的 WMI 查询(此处在 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`
}