programing

설치된 MS-Office 버전을 검색하는 방법은 무엇입니까?

lastcode 2023. 4. 27. 22:29
반응형

설치된 MS-Office 버전을 검색하는 방법은 무엇입니까?

설치된 Office 버전을 검색하는 가장 좋은 방법이 무엇인지 아는 사람이 있습니까?또한 여러 버전의 Office가 설치되어 있다면 어떤 버전인지 알고 싶습니다.설치된 Excel의 특정 버전을 감지할 수 있다면 보너스가 될 것입니다.

하는 한 은 "Office"를 확인하는 것입니다.InstallRoot관심 있는 Office 응용 프로그램에 대한 레지스트리 키.

예를 들어 Word 2007 설치 여부를 확인하려면 다음 레지스트리 키가 있는지 확인해야 합니다.

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

이 항목에는 실행 파일의 경로가 포함되어 있습니다.

12.0(Office 2007의 경우)을 해당 버전 번호로 바꿉니다.

사무실 97 - 7.0오피스 98 - 8.0Office 2000 - 9.0Office XP - 10.0Office 2003 - 11.0Office 2007 - 12.0Office 2010 - 14.0 (sic!)오피스 2013 - 15.0오피스 2016 - 16.0오피스 2019 - 16.0 (sic!)

다른 응용 프로그램의 키는 다음과 같습니다.

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

수 있는 또 옵션은 MSI 데이터베이스를 쿼리하는 입니다.MSIEnumProducts여기에 설명된 API.

다른 Office 버전의 병렬 설치는 Microsoft에서 공식적으로 지원하지 않습니다.어느 정도 효과는 있지만 원치 않는 효과와 불일치가 나타날 수 있습니다.

업데이트: 오피스 2019 및 오피스 365

Office 2019부터는 MSI 기반 설정을 더 이상 사용할 수 없습니다. 이제 Office를 배포하려면 클릭-To-Run이 유일한 방법입니다.정기적으로 업데이트되는 Office 365에 대한 이러한 변경과 함께 Office의 주/부 버전 번호도 더 이상 업데이트되지 않습니다(적어도 당분간은).2019의 과 즉, Office 2019에서 합니다.Application.Version에서) (예: Word에서) 여전히입니다.16.0.

당분간 오피스 2016과 오피스 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 버전을 다루고 있는 것입니다.

HKEY_CLASSES_ROOT\Word는 어떻습니까?응용 프로그램\CurVer?

64비트 시스템에 32비트 Office를 설치한 경우 12.0을 적절한 버전으로 대체하여 "SOFTWOw6432Node\Microsoft\Office\12.0\"이 있는지 확인해야 할 수 있습니다.이것은 64비트 Windows 7에 설치된 Office 2007의 경우입니다.

Office 2010(== 14.0)은 64비트 버전이 존재하는 첫 번째 Office입니다.

이 질문은 오래 전에 답변이 되었음에도 불구하고 위의 답변과 관련된 몇 가지 흥미로운 사실을 추가했습니다.

더크가 언급했듯이, 2019년 오피스 365부터 MS의 버전 관리 방식이 이상한 것 같습니다.실행 경로를 보고 더 이상 세 가지(2016, 2019, O365)를 구분할 수 없습니다.그리고 그가 스스로를 칭찬한 것처럼, 실행 가능한 파일의 빌드를 보는 것은 어떤 것이 무엇인지를 말하는 수단으로, 또한 꽤 효과적이지 않습니다.

몇 가지 조사를 한 후, 저는 실현 가능한 가지런한 해결책을 찾았습니다. 키 루솔레트하키있습다에 .Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Common\Licensing\LicensingNext.

그래서 제 논리는 다음과 같습니다.

사례 1: 컴퓨터에 MS Office 2016이 설치된 경우 아래에 하위 키가 없습니다.Licensing.

사례 2: 컴퓨터에 MSOffice 2019가 설치되어 있는 경우 값의 이름(Office Product ID 중 하나)이 있습니다(예:Standard2019Volume)

사례 3: 컴퓨터에 Office365가 설치되어 있으면 다음과 같은 값이 있습니다.o365bussinessretail(제품 ID이기도 함) 및 기타 일부 값.

가능한 productId는 여기에 제공됩니다.

세 가지를 구분하기 위해 그냥 열쇠를 열고 실패 여부를 확인했습니다.오픈이 실패하면 Office 2016이 됩니다.그러면 열거합니다.LicensingNext그리고 어떤 이름이 접두사를 가지고 있는지 확인해보세요.o365만약 그것이 그것을 발견한다면 그것은 O365입니다.그렇지 않다면, 오피스 2019입니다.

솔직히, 저는 다양한 환경에서 논리를 테스트할 충분한 시간이 없었습니다.그러니 부디, 그것을 주목하세요.

이것이 관심 있는 사람에게 도움이 되기를 바랍니다.

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;
    }



}
}

확인하지 않는 이유HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\[office.exe],어디에[office.exe]특정 사무실 제품 exe-message의 약자입니다.winword.exe,excel.exe여기서 실행 파일의 경로를 확인하고 해당 파일의 버전을 확인할 수 있습니다.

파일 버전 확인 방법: C++에서 / C#에서

그런 접근법에 대한 비판은 없습니까?

저는 "Office 2016" 또는 "Office 2019"가 설치되어 있는지 탐지하고 싶을 때 "Microsoft Office 버전"을 탐지할 수 있는 우아한 방법을 찾았습니다.

방금 "Microsoft Office"의 설치 경로를 감지하고 시스템을 선언했습니다.진단.파일 버전"Office"-Application(예: "Word")의 exe 파일에서 정보를 얻고 이 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"를 마우스 오른쪽 단추로 클릭한 다음 "Properties"를 클릭하면 나타나는 정보입니다.참조:winword 세부사항.exe

설치된 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에서는 다음을 삽입해야 합니다.Wow6432Node사이에SOFTWARE그리고.Microsoft사무실 설치의 쓰라림과는 상관없이 부스러기.

내 컴퓨터에서는 원래 설치된 버전의 버전 정보가 제공됩니다.예를 들어 Office 2010의 경우, 숫자는 여기에 나열된 것과 일치하며, 보고된 버전과 다릅니다.File > Help핫픽스에 의해 적용된 패치를 반영합니다.

        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;
            }
        }

Office 95-2019 및 O365를 확인하는 내 버전은 32비트 시스템과 64비트 시스템 모두에서 MSI 기반 및 ClickAndRun이 지원됩니다(64비트 버전이 설치되지 않은 경우 32비트로 돌아갑니다).

Python 3.5로 작성되었지만 물론 다른 언어로 코드를 작성하기 위해 항상 해당 로직을 사용할 수 있습니다.

from winreg import *
from typing import Tuple, Optional, List

# Let's make sure the dictionnary goes from most recent to oldest
KNOWN_VERSIONS = {
    '16.0': '2016/2019/O365',
    '15.0': '2013',
    '14.0': '2010',
    '12.0': '2007',
    '11.0': '2003',
    '10.0': '2002',
    '9.0': '2000',
    '8.0': '97',
    '7.0': '95',
}


def get_value(hive: int, key: str, value: Optional[str], arch: int = 0) -> str:
    """
    Returns a value from a given registry path

    :param hive: registry hive (windows.registry.HKEY_LOCAL_MACHINE...)
    :param key:  which registry key we're searching for
    :param value: which value we query, may be None if unnamed value is searched
    :param arch: which registry architecture we seek (0 = default, windows.registry.KEY_WOW64_64KEY, windows.registry.KEY_WOW64_32KEY)
                 Giving multiple arches here will return first result
    :return: value
    """

    def _get_value(hive: int, key: str, value: Optional[str], arch: int) -> str:
        try:
            open_reg = ConnectRegistry(None, hive)
            open_key = OpenKey(open_reg, key, 0, KEY_READ | arch)
            value, type = QueryValueEx(open_key, value)
            # Return the first match
            return value
        except (FileNotFoundError, TypeError, OSError) as exc:
            raise FileNotFoundError('Registry key [%s] with value [%s] not found. %s' % (key, value, exc))

    # 768 = 0 | KEY_WOW64_64KEY | KEY_WOW64_32KEY (where 0 = default)
    if arch == 768:
        for _arch in [KEY_WOW64_64KEY, KEY_WOW64_32KEY]:
            try:
                return _get_value(hive, key, value, _arch)
            except FileNotFoundError:
                pass
        raise FileNotFoundError
    else:
        return _get_value(hive, key, value, arch)


def get_keys(hive: int, key: str, arch: int = 0, open_reg: HKEYType = None, recursion_level: int = 1,
             filter_on_names: List[str] = None, combine: bool = False) -> dict:
    """
    :param hive: registry hive (windows.registry.HKEY_LOCAL_MACHINE...)
    :param key: which registry key we're searching for
    :param arch: which registry architecture we seek (0 = default, windows.registry.KEY_WOW64_64KEY, windows.registry.KEY_WOW64_32KEY)
    :param open_reg: (handle) handle to already open reg key (for recursive searches), do not give this in your function call
    :param recursion_level: recursivity level
    :param filter_on_names: list of strings we search, if none given, all value names are returned
    :param combine: shall we combine multiple arch results or return first match
    :return: list of strings
    """
    def _get_keys(hive: int, key: str, arch: int, open_reg: HKEYType, recursion_level: int, filter_on_names: List[str]):
        try:
            if not open_reg:
                open_reg = ConnectRegistry(None, hive)
            open_key = OpenKey(open_reg, key, 0, KEY_READ | arch)
            subkey_count, value_count, _ = QueryInfoKey(open_key)

            output = {}
            values = []
            for index in range(value_count):
                name, value, type = EnumValue(open_key, index)
                if isinstance(filter_on_names, list) and name not in filter_on_names:
                    pass
                else:
                    values.append({'name': name, 'value': value, 'type': type})
            if not values == []:
                output[''] = values

            if recursion_level > 0:
                for subkey_index in range(subkey_count):
                    try:
                        subkey_name = EnumKey(open_key, subkey_index)
                        sub_values = get_keys(hive=0, key=key + '\\' + subkey_name, arch=arch,
                                              open_reg=open_reg, recursion_level=recursion_level - 1,
                                              filter_on_names=filter_on_names)
                        output[subkey_name] = sub_values
                    except FileNotFoundError:
                        pass

            return output

        except (FileNotFoundError, TypeError, OSError) as exc:
            raise FileNotFoundError('Cannot query registry key [%s]. %s' % (key, exc))

    # 768 = 0 | KEY_WOW64_64KEY | KEY_WOW64_32KEY (where 0 = default)
    if arch == 768:
        result = {}
        for _arch in [KEY_WOW64_64KEY, KEY_WOW64_32KEY]:
            try:
                if combine:
                    result.update(_get_keys(hive, key, _arch, open_reg, recursion_level, filter_on_names))
                else:
                    return _get_keys(hive, key, _arch, open_reg, recursion_level, filter_on_names)
            except FileNotFoundError:
                pass
        return result
    else:
        return _get_keys(hive, key, arch, open_reg, recursion_level, filter_on_names)


def get_office_click_and_run_ident():
    # type: () -> Optional[str]
    """
    Try to find the office product via clickandrun productID
    """
    try:
        click_and_run_ident = get_value(HKEY_LOCAL_MACHINE,
                                                 r'Software\Microsoft\Office\ClickToRun\Configuration',
                                                 'ProductReleaseIds',
                                                 arch=KEY_WOW64_64KEY |KEY_WOW64_32KEY,)
    except FileNotFoundError:
        click_and_run_ident = None
    return click_and_run_ident


def _get_used_word_version():
    # type: () -> Optional[int]
    """
    Try do determine which version of Word is used (in case multiple versions are installed)
    """
    try:
        word_ver = get_value(HKEY_CLASSES_ROOT, r'Word.Application\CurVer', None)
    except FileNotFoundError:
        word_ver = None
    try:
        version = int(word_ver.split('.')[2])
    except (IndexError, ValueError, AttributeError):
        version = None
    return version


def _get_installed_office_version():
    # type: () -> Optional[str, bool]
    """
    Try do determine which is the highest current version of Office installed
    """
    for possible_version, _ in KNOWN_VERSIONS.items():
        try:
            office_keys = get_keys(HKEY_LOCAL_MACHINE,
                                               r'SOFTWARE\Microsoft\Office\{}'.format(possible_version),
                                               recursion_level=2,
                                               arch=KEY_WOW64_64KEY |KEY_WOW64_32KEY,
                                               combine=True)

            try:
                is_click_and_run = True if office_keys['ClickToRunStore'] is not None else False
            except:
                is_click_and_run = False

            try:
                is_valid = True if office_keys['Word'] is not None else False
                if is_valid:
                    return possible_version, is_click_and_run
            except KeyError:
                pass
        except FileNotFoundError:
            pass
    return None, None


def get_office_version():
    # type: () -> Tuple[str, Optional[str]]
    """
    It's plain horrible to get the office version installed
    Let's use some tricks, ie detect current Word used
    """

    word_version = _get_used_word_version()
    office_version, is_click_and_run = _get_installed_office_version()

    # Prefer to get used word version instead of installed one
    if word_version is not None:
        office_version = word_version

    version = float(office_version)
    click_and_run_ident = get_office_click_and_run_ident()

    def _get_office_version():
        # type: () -> str
        if version:
            if version < 16:
                try:
                    return KNOWN_VERSIONS['{}.0'.format(version)]
                except KeyError:
                    pass
            # Special hack to determine which of 2016, 2019 or O365 it is
            if version == 16:
                if isinstance(click_and_run_ident, str):
                    if '2016' in click_and_run_ident:
                        return '2016'
                    if '2019' in click_and_run_ident:
                        return '2019'
                    if 'O365' in click_and_run_ident:
                        return 'O365'
                return '2016/2019/O365'
        # Let's return whatever we found out
        return 'Unknown: {}'.format(version, click_and_run_ident)

    if isinstance(click_and_run_ident, str) or is_click_and_run:
        click_and_run_suffix = 'ClickAndRun'
    else:
        click_and_run_suffix = None

    return _get_office_version(), click_and_run_suffix

다음 예제와 같은 코드를 사용할 수 있습니다.

office_version, click_and_run = get_office_version()
print('Office {} {}'.format(office_version, click_and_run))

언급

  • 2010년 사무실에서 테스트하지 않았습니다.
  • pypy/python2가 타이핑을 좋아하지 않는다는 것을 알기 전에 레지스트리 기능을 작성했기 때문에 python 타이핑은 레지스트리 기능과 사무실 기능이 다릅니다...해당 파이썬 인터프리터에서 타이핑을 완전히 제거할 수 있습니다.
  • 어떠한 개선도 환영합니다.

사용해 보십시오(모든 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;
                }

                
            }
        

출력:

오피스 19

오피스19홈비즈니스 2019R_소매판

키: XXXXX

상태: 라이센스 있음

언급URL : https://stackoverflow.com/questions/3266675/how-to-detect-installed-version-of-ms-office

반응형