如何检测已安装的MS-Office版本?

71

有没有人知道检测安装的 Office 版本的最佳方法是什么?如果安装了多个版本的 Office,我想知道它们各自的版本。另外,如果能检测安装的特定版本的 Excel,那就更好了。


http://stackoverflow.com/questions/2914643/determine-excel-version-culture-via-microsoft-office-interop-excel - Mandelbrot
@Mandelbrot:那只告诉我我正在引用哪个版本……但这是我正在编写的MSI,所以那里没有这样的引用! - code4life
啊,说得好。我的错。 - Mandelbrot
你想用C#代码还是MSI安装程序来找出这个问题? - Dirk Vollmar
这是一个VS安装项目,而我有一个安装程序项目(C#),我正在尝试在这里完成此操作。 - code4life
11个回答

84

检查已安装的 Office 版本的一种方法是检查感兴趣的 Office 应用程序的 InstallRoot 注册表键。

例如,如果您想检查是否安装了 Word 2007,则应检查以下注册表键是否存在:

HKLM\Software\Microsoft\Office\12.0\Word\InstallRoot::Path

这个条目包含可执行文件的路径。

将12.0(Office 2007)替换为相应的版本号:

Office 97   -  7.0
Office 98   -  8.0
Office 2000 -  9.0
Office XP   - 10.0
Office 2003 - 11.0
Office 2007 - 12.0
Office 2010 - 14.0 (注意,不是15.0!)
Office 2013 - 15.0
Office 2016 - 16.0
Office 2019 - 16.0 (注意,不是17.0!)

其他应用程序的密钥类似:

HKLM\Software\Microsoft\Office\12.0\Excel\InstallRoot::Path
HKLM\Software\Microsoft\Office\12.0\PowerPoint\InstallRoot::Path

或者你可以检查所有应用程序的常见根路径:

HKLM\Software\Microsoft\Office\12.0\Common\InstallRoot::Path

另一个选择,不使用特定的注册表键,可以通过使用MSIEnumProducts API查询MSI数据库来实现,具体描述可以参考这里

顺便提一下,微软官方不支持在同一台计算机上并行安装不同版本的Office。尽管有些情况它们可能能够运作,但你可能会遇到意料之外的问题和不一致性。

更新:Office 2019和Office 365

从Office 2019开始,不再提供基于MSI的安装程序,现在唯一的部署Office的方式是使用Click-To-Run。随着这种变化朝向定期更新的Office 365,Office的主/次版本号也不再更新(至少目前是这样)。这意味着即使对于Office 2019,用于注册表键的值和Application.Version返回的值(例如在Word中)仍然为16.0

目前还没有记录的方法来区分Office 2016和Office 2019。一个提示可能是winword.exe的文件版本;但是,这个版本对于补丁的Office 2016版本也会增加(请参见@antonio的评论)。

如果你需要在Office版本之间进行区分,例如确保某个特定功能存在或已安装Office的最低版本,请查看其中一个主要Office应用程序的文件版本,可能是最好的方法:

// Using the file path to winword.exe
// Retrieve the path e.g. from the InstallRoot Registry key
var fileVersionInfo = FileVersionInfo.GetVersionInfo(@"C:\Program Files (x86)\Microsoft Office\root\Office16\WINWORD.EXE");
var version = new Version(fileVersionInfo.FileVersion);

// On a running instance using the `Process` class
var process = Process.GetProcessesByName("winword").First();
string fileVersionInfo = process.MainModule.FileVersionInfo.FileVersion;
var version = Version(fileVersionInfo);

Office 2019的文件版本为16.0.10730.20102,因此如果您看到任何大于该版本号的版本,您正在处理Office 2019或当前的Office 365版本。


1
我们是否还需要检查HKCU?因为那是我的注册表键所在的位置。谢谢! - Reza S
12
我确信这并不需要说明,作为一条评论有些多余。然而,版本号在12.0和14.0之间缺失的原因与高层建筑中没有类似编号的楼层相同。 - Hamp
1
请注意,如果您使用通用密钥(检查所有办公应用程序的公共根),则在15.0版本中将无法使用。 - Scott Whitlock
5
这是一个“点击运行”安装吗?他们可能会以不同的方式处理这个问题。请注意,在64位系统上,使用regedit时您需要在HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Office中查找。 - Dirk Vollmar
2
你如何检查Office是32位版本还是64位版本? - Benjamin Jones
显示剩余7条评论

30

HKEY_CLASSES_ROOT\Word.Application\CurVer怎么样?


1
这是我的最爱,因为它避免了Wow64问题,并且支持安装多个Office版本的情况,如果是这样,我相信CurVer会设置为最后启动的版本。 - JohnZaj
希望早点看到这个,它在 Inno Setup 中也能很好地工作。我是这样使用它的:RegQueryStringValue(HKEY_CLASSES_ROOT, 'Word.Application\CurVer', '', myString)。 - SlowLearner
这是一个很好的答案,但为了清晰起见,它只返回内部版本,例如Word.Application.15等等。它不会返回文件或注册表路径。你仍然需要单独获取那些信息。 - Chris
1
我在使用这个方法时遇到了问题,当安装了多个版本的Office/Office应用程序时,它似乎只会存储第一个安装的版本,而不是最新的版本。 - Lord Darth Vader
1
Word 2019也显示为Word.Application.16。因此问题是如何区分2016和2019版本。 - Dmitri Kouminov
截至2022年1月(Office 16.0,版本2111),这似乎无法始终正常工作:在一台机器上,Word.Application\CurVer的值为Word.Application.11,也是:PowerPoint.Application.11,但Outlook.Application.16,Excel.Application.16(对于它们的CurVer版本)。 (!!)顺便说一句,我只有一个Office版本。尽管在另一台安装了相同Office版本的机器上,所有Office程序的CurVer都显示为16。 - neilt17

18
如果您在64位机器上安装了32位的Office,您可能需要检查是否存在"SOFTWARE\Wow6432Node\Microsoft\Office\12.0\",将12.0替换为适当的版本。这对于安装在64位Windows 7上的Office 2007肯定是这种情况。
请注意,Office 2010(==14.0)是第一个拥有64位版本的Office。

9
尽管这个问题很久以前就有答案了,但我发现一些有趣的事实可以补充到以上答案中。正如Dirk所提到的,从Office 365 / 2019开始,MS似乎有一种奇怪的版本控制方式。你不能再通过查看可执行路径来区分三个版本(2016、2019、O365)。而且像他所说的那样,通过查看可执行文件的构建版本来判断哪个版本也不是很有效。经过一些研究,我找到了一个可行的解决方案。解决方案在注册表子键 Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Common\Licensing\LicensingNext 下。因此,我的逻辑如下: 情况1:如果计算机安装了MSOffice 2016,则在Licensing下没有子键。 情况2:如果计算机安装了MSOffice 2019,则会显示一个值的名称(即Office产品ID之一)。 (例如Standard2019Volume案例3:如果计算机安装了Office365,则会有一个名为o365bussinessretail(也是产品ID)的值以及其他一些值。
可能的产品ID在此处提供。
为了区分这三个,我只是打开键并查看是否失败。如果打开失败,则是Office 2016。然后我枚举LicensingNext并尝试查看任何名称是否具有前缀o365,如果找到它,则是O365。如果没有,则是Office 2019
坦率地说,我没有足够的时间测试在不同环境下的逻辑。所以请注意这一点。
希望这能帮助任何感兴趣的人。

1
谢谢。你可能为我节省了很多时间! - Samuel Tulach

8
namespace Software_Info_v1._0
{
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Office.Interop;

public class MS_Office
{
    public string GetOfficeVersion()
    {
        string sVersion = string.Empty;
        Microsoft.Office.Interop.Word.Application appVersion = new Microsoft.Office.Interop.Word.Application();
        appVersion.Visible = false;
        switch (appVersion.Version.ToString())
        {
            case "7.0":
                sVersion = "95";
                break;
            case "8.0":
                sVersion = "97";
                break;
            case "9.0":
                sVersion = "2000";
                break;
            case "10.0":
                sVersion = "2002";
                break;
            case "11.0":
                sVersion = "2003";
                break;
            case "12.0":
                sVersion = "2007";
                break;
            case "14.0":
                sVersion = "2010";
                break;
            default:
                sVersion = "Too Old!";
                break;
        }
        Console.WriteLine("MS office version: " + sVersion);
        return null;
    }



}
}

2
这看起来像是Longball27链接的同样提议的解决方案,只不过更新以处理Office 2010。这有两个问题。即使安装了Word,Microsoft.Office.Interop.Word dll也可能没有安装,例如如果在安装.Net之前安装了Word或者只进行了部分安装而不是完整安装。这对于仅安装Outlook的部分安装来说可能是最典型的情况 - 相应的Microsoft.Office.Interop.Outlook dll通常直到用户下载并安装Outlook的“主要互操作程序集”后才安装。 - RenniePet
4
另一个(非常小的)问题是在“switch”语句中,“default”子句对于未知版本会显示“太旧了!”。更可能导致执行该代码的原因是Word(或其他软件)的版本过新。实际上,为了处理Office 2010而进行的更新显示了这一点——在应用此更新之前,该程序的先前版本声称Office 2010过旧! - RenniePet
获取具有CLSID {00024500-0000-0000-C000-000000000046} 的组件的COM类工厂失败,原因是出现以下错误:800702e4。请求的操作需要提升权限。(HRESULT异常: 0x800702E4)。 - Neo
如果机器上没有安装Office,这段代码会失败吗? https://dev59.com/EGw05IYBdhLWcg3wpDRu - Kiquenet
如果您在 VSTO 插件的上下文中,可以通过以下方式快速获取: Globals.ThisAddIn.Application.Version - Fabricio

7

为什么不检查HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\[office.exe],其中[office.exe]代表特定的Office产品exe文件名,例如winword.exeexcel.exe等。

在那里,您可以获得可执行文件路径并检查该文件的版本。

如何检查文件版本:C++ / C#

对这种方法有任何批评吗?


1
这对我非常有效,消除了我在x86与64位之间以及在略微不同的安装设置之间遇到的问题。 - Hanny
1
注意:当您安装两个不同版本(例如Excel 2016和Excel 2007)时,它似乎总是指向最近安装的版本(即它不指向上次启动的版本)。 - TmTron

3

我找到了一种优雅的方法来检测“Microsoft Office版本”,也许在您想要检测是否安装了“Office 2016”或“Office 2019”时也适用。

我只是检测了“Microsoft Office”的安装路径,然后从“Office”应用程序(例如“Word”)的exe文件中声明了一个System.Diagnostics.FileVersionInfo,并从这个FileVersionInfo中获取了我需要的所有内容。

以下是一个非常小的控制台应用程序的完整代码示例:

using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Sandbox_Console
{
    public class Program
    {
        static void Main(string[] args)
        {
            string installpath = GetOfficeInstallPath();
            OfficeVersionInfo info = new OfficeVersionInfo(installpath);
            Console.WriteLine("Full Office Version Number: " + info.FullVersionNumber);
            Console.WriteLine("Full Office Name: " + info.FullOfficeVersionName);
            Console.Write("Press any key to end this program...");
            Console.ReadKey();
        }

        public class OfficeVersionInfo
        {
            private string _FullVersionNumber = "";
            private string _FullOfficeVersionName = "";

            public string FullVersionNumber { get { return _FullVersionNumber; } }
            public string FullOfficeVersionName { get { return _FullOfficeVersionName; } }

            public OfficeVersionInfo(string installPath)
            {
                string filepath = installPath + "\\winword.exe"; //For Excel, PowerPoint or others use the exe-files for them.
                if (File.Exists(filepath))
                {
                    FileVersionInfo info = FileVersionInfo.GetVersionInfo(filepath);
                    _FullVersionNumber = info.ProductVersion;
                    _FullOfficeVersionName = info.ProductName;
                }
            }
        }

        public static string GetOfficeInstallPath()
        {
            string result = "";
            try
            {
                Type appType = Type.GetTypeFromProgID("Word.Application"); //Also works with Excel, PowerPoint or others.
                dynamic appInstance = Activator.CreateInstance(appType);
                result = appInstance.Path;
                appInstance.quit();
                Marshal.ReleaseComObject(appInstance);
            } catch (Exception exc)
            {
                Debug.Print(exc.Message);
            }
            return result;
        }  
    }
}

"OfficeVersionInfo" 里存储的信息是当你右键点击 "winword.exe",然后点击 "属性" 时所得到的信息。请参见: winword.exe 的详细信息


2
很遗憾,这不是一个选项。Click-To-Run (C2R) 安装的 Office 2019(例如 winword.exe)的 Product name 属性仅显示 Microsoft Office,没有关于具体版本的更多信息。 - Unhandled Exception
1
认真吗?现在对我来说,微软似乎不希望你区分Office 2016和Office 2019。非常不幸。无论如何,感谢您的评论。 - GeoMH

2
一个奖励是如果我能检测到安装的Excel具体版本(们)。

我知道这个问题很久以前就被问过和回答了,但是直到我做出以下观察,这个问题才让我忙碌:

要获取构建号(例如15.0.4569.1506),请探查HKLM\SOFTWARE\Microsoft\Office\[VER]\Common\ProductVersion::LastProduct,其中[VER]是主要版本号(Office 2007为12.0,Office 2010为14.0,Office 2013为15.0)。

在64位Windows上,无论Office安装的位数如何,都需要在SOFTWAREMicrosoft之间插入Wow6432Node

在我的机器上,这提供了最初安装版本的版本信息。例如,对于Office 2010,数字与此处列出的数字匹配,并且它们与文件> 帮助中报告的版本不同,后者反映了通过热修复应用的补丁。


1
        public string WinWordVersion
        {
            get
            {
                string _version = string.Empty;
                Word.Application WinWord = new Word.Application();   

                switch (WinWord.Version.ToString())
                {
                    case "7.0":  _version = "95";
                        break;
                    case "8.0": _version = "97";
                        break;
                    case "9.0": _version = "2000";
                        break;
                    case "10.0": _version = "2002";
                        break;
                    case "11.0":  _version = "2003";
                        break;
                    case "12.0": _version = "2007";
                        break;
                    case "14.0": _version = "2010";
                        break;
                    case "15.0":  _version = "2013";
                        break;
                    case "16.0": _version = "2016";
                        break;
                    default:                            
                        break;
                }

                return WinWord.Caption + " " + _version;
            }
        }

0
尝试这个(适用于所有版本的Office):
            ManagementObjectSearcher LicenseSearcher =
                       new ManagementObjectSearcher("root\\CIMV2",
                       "SELECT name, LicenseStatus,Description,PartialProductKey  FROM SoftwareLicensingProduct where name like '%office%'");

            foreach (ManagementObject LSObj in LicenseSearcher.Get())
            {
                String prod_name = LSObj["Name"].ToString();
                String prod_description = LSObj["Description"].ToString();

                String prod_key = "";
                try
                {
                    prod_key = LSObj["PartialProductKey"].ToString();
                }
                catch
                {
                    prod_key = "";
                }
 
                
                String prod_lic_sta= LSObj["LicenseStatus"].ToString();

        
                switch (prod_lic_sta)
                {
                    case "0": 
                        prod_lic_sta = "Unlicensed";
                        break;
                    case "1": 
                        prod_lic_sta = "Licensed";
                        break;
                    case "2": 
                        prod_lic_sta = "OOBGrace";
                        break;
                    case "3":
                        prod_lic_sta = "OOTGrace";
                        break;
                    case "4":
                        prod_lic_sta = "NonGenuineGrace";
                        break;
                    case "5":
                        prod_lic_sta = "Notification";
                        break;
                    case "6":
                        prod_lic_sta = "ExtendedGrace";
                        break;
                }

                
            }
        

输出:

Office 19

Office19HomeBusiness2019R_Retail版

密钥:XXXXX

状态:已授权


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接