Jump to content
Zedna

How to get version of installed MS Office

Recommended Posts

Zedna

I need to get name/version of installed Microsoft Office in form similar to that one in About window:

Microsoft Office Professional Plus 2010 (14.0.4763.1000)

I searched internet/this forum for some simple examples but not much luck

because all found examples use registry uninstall keys which are not exact.

Here are related examples:

http://support.microsoft.com/kb/2186281

Here is my derived improved example, syntax is in PowerBuilder - similar to VB/AU3

function uf_get_office_ver()
 
string ls_key, ls_return, ls_pom, ls_name, ls_ver1, ls_ver2, ls_ver3, ls_subkeylist[], ls_valuearray[]
long i,j
ulong ul_pom
integer li_rtn

// 1) first quick check if Office installed and get approximate version
ls_key = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office"
li_rtn = RegistryKeys(ls_key, ls_subkeylist)
if li_rtn = -1 then return ''

ls_key += "\"
j = UpperBound(ls_subkeylist)
for i=1 to j
    li_rtn = RegistryValues(ls_key + ls_subkeylist[i] + "\Registration", ls_valuearray)
    if li_rtn = 1 then
        ls_ver1 = ls_subkeylist[i] // 14.0
        ls_return = 'Microsoft Office ' + ls_subkeylist[i]
        exit
    end if
next

if ls_return = '' then return '' // isn't Office

// 2) check exact name/version from Uninstall
ls_key = "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall"
li_rtn = RegistryKeys(ls_key, ls_subkeylist)
if li_rtn = -1 then return ''

ls_key += "\"
j = UpperBound(ls_subkeylist)
for i=1 to j
    li_rtn = RegistryGet(ls_key + ls_subkeylist[i], "DisplayName", RegString!, ls_name)
    if li_rtn = -1 then continue
    
    // skip other applications than Office and also Office components
    if not(Pos(ls_name, 'Microsoft Office') > 0 and Pos(ls_name, 'Web Components') = 0) then continue
    
    li_rtn = RegistryGet(ls_key + ls_subkeylist[i], "ParentKeyName", RegString!, ls_pom)
    if li_rtn = 1 then continue // skip those with Parent
    
    li_rtn = RegistryGet(ls_key + ls_subkeylist[i], "SystemComponent", ReguLong!, ul_pom)
    if li_rtn = 1 and ul_pom = 1 then continue // skip SystemComponents=1 --> MUI (Czech), ...

    li_rtn = RegistryGet(ls_key + ls_subkeylist[i], "DisplayVersion", RegString!, ls_ver2)
    if li_rtn = -1 then continue // skip those without version

    // note: base version number must be the same with the one from first step
    // Microsoft Office Professional Plus 2010 (14.0.4763.1000)
    if Left(ls_ver2, Len(ls_ver1)) = ls_ver1 then
        // 3) beware: in registry there isn't version included service packs, therefore check exact version from EXE? (14.0.6106.5005) - SP1
        // InstallLocation - C:\Program Files (x86)\Microsoft Office\
//        ls_ver3 = ...

        return ls_name + ' (' + ls_ver2 + ')'
    end if
next

// if not found exact version from Uninstall, then return at least approximate version from first step
return ls_return

Problems:

- I can get Microsoft Office Professional Plus 2010 (14.0.4763.1000) as result by this

but in About window of my Word is (14.0.6106.5005) - because I have got SP1 and its version isn't in registry

- I wanted to get get file version of MSO.DLL

"C:\Program Files (x86)\Common Files\microsoft shared\OFFICE14\MSO.DLL"

but there is problem how to get correct full path from registry

- maybe there could be another way using COM but I don't know exact syntax for some general office COM object

and its properties with product name/version

http://msdn.microsoft.com/en-us/library/aa217200%28v=office.10%29.aspx

Please give me some advise how to get exact version of installed Microsoft Office (included service packs)

in some elegant/simple way.

Share this post


Link to post
Share on other sites
Zedna

Here is my previous example translated from PowerBuilder to Autoit syntax:

MsgBox(0, '', uf_get_office_ver())
 
Func uf_get_office_ver()
 
    Dim $ls_key, $ls_return, $ls_pom, $ls_name, $ls_ver1, $ls_ver2, $ls_ver3, $ls_subkey, $ls_value
    Dim $n, $ul_pom
 
    ; 1) first quick check if Office installed and get approximate version
    $ls_key = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office"
    $n = 1
 
    While 1
        $ls_subkey = RegEnumKey($ls_key, $n)
        If @error Then ExitLoop
 
        $ls_value = RegEnumKey($ls_key & "\" & $ls_subkey & "\Registration", 1)
        If Not @error Then
            $ls_ver1 = $ls_subkey ; 14.0
            $ls_return = 'Microsoft Office ' + $ls_subkey
            ExitLoop
        EndIf
 
        $n += 1
    WEnd
 
    If $ls_return = '' Then Return '' ; isn't Office
 
    ; 2) check exact name/version from Uninstall
    $ls_key = "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall"
    $n = 0
 
    While 1
        $n += 1
 
        $ls_subkey = RegEnumKey($ls_key, $n)
        If @error Then ExitLoop
 
        $ls_name = RegRead($ls_key & "\" & $ls_subkey, "DisplayName")
        If @error Then ContinueLoop
 
        ; skip other applications than Office and also Office components
        If Not (StringInStr($ls_name, 'Microsoft Office') > 0 And StringInStr($ls_name, 'Web Components') = 0) Then ContinueLoop
 
        $ls_pom = RegRead($ls_key & "\" & $ls_subkey, "ParentKeyName")
        If Not @error Then ContinueLoop ; skip those With Parent
 
        $ul_pom = RegRead($ls_key & "\" & $ls_subkey, "SystemComponent")
        If Not @error And $ul_pom = 1 Then ContinueLoop ; skip SystemComponents = 1 - - > MUI(Czech), ...
 
        $ls_ver2 = RegRead($ls_key & "\" & $ls_subkey, "DisplayVersion")
        If @error Then ContinueLoop ; skip those without version
 
        ; note: base version number must be the same with the one from first step
        ; Microsoft Office Professional Plus 2010 (14.0.4763.1000)
        If StringLeft($ls_ver2, StringLen($ls_ver1)) = $ls_ver1 Then
            ; 3) beware: in registry there isn't version included service packs, therefore check exact version from EXE? (14.0.6106.5005) - SP1
            ; InstallLocation - C:\Program Files (x86)\Microsoft Office\
            ;       ls_ver3 = ...
 
            Return $ls_name & ' (' & $ls_ver2 & ')'
        EndIf
    WEnd
 
    ; if not found exact version from Uninstall, then return at least approximate version from first step
    Return $ls_return
EndFunc   ;==>uf_get_office_ver

EDIT: Return value on my system is

Microsoft Office Professional Plus 2010 (14.0.4763.1000)

Edited by Zedna

Share this post


Link to post
Share on other sites
Zedna

In further testing on other computers with diferent configuration I discovered it can't trust information in

"HKEY_LOCAL_MACHINESOFTWAREMicrosoftOfficeVersionRegistration"

because on some machines it's not stored in this way so only

"HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionUninstall"

can be used but there must be skipped also other applications with Office in its name like "Microsoft Office Viewer" for example.

So problem remains, how to get Office version by elegant way without any side effects.

Share this post


Link to post
Share on other sites
GEOSoft

Did You look at The uninstall keys for

{90110409-6000-11D3-8CFE-0150048383C9}

It should contain a value for "Readme"

and you can extract the path from there.

EDIT:

Sorry; this is probably a better key if you want to read the version of MSO.dll

HKEY_CLASSES_ROOTCLSID{000C0114-0000-0000-C000-000000000046}InprocServer32

The way it's written you will have to do a bit of manipulation though.

Edited by GEOSoft

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites
GEOSoft

Just tested it with this code and no manipulation was required.

Local $sKey = "HKCR64CLSID{000C0114-0000-0000-C000-000000000046}InprocServer32"
Local $sVer = FileGetVersion(RegRead($sKey, ""))
MsgBox(0, "Result", $sVer)

Another key you couls use is

HKLM64SOFTWAREMicrosoftOffice<ver>CommonFilesPaths

RegEnum the HKLM64SOFTWAREMicrosoftOffice key until you can get a regread from CommonFilesPaths and the value that you will look at is mso.dll

Local $sKey = "HKLM64SoftwareMicrosoftOffice", $sVer, $sPath
$iKey = 1
While 1
$sVer = RegEnumKey($sKey, $iKey)
If @Error Then
  MsgBox(0, $iKey, "Oooops")
  Exit
EndIf
$sPath =  RegRead($sKey & $sVer & "CommonFilesPaths", "mso.dll")
If @Error Then
  MsgBox(0, "Error", @Error)
  $iKey += 1
  ContinueLoop
Else
  ExitLoop
EndIf
WEnd
MsgBox(0, "Result", FileGetVersion($sPath))
Edited by GEOSoft

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites
Zedna

Did You look at The uninstall keys for

{90110409-6000-11D3-8CFE-0150048383C9}

It should contain a value for "Readme"

and you can extract the path from there.

EDIT:

Sorry; this is probably a better key if you want to read the version of MSO.dll

HKEY_CLASSES_ROOTCLSID{000C0114-0000-0000-C000-000000000046}InprocServer32

The way it's written you will have to do a bit of manipulation though.

How did you discover these values?

Are these values the same on ALL computers/ ALL versions of Windows/Office?

Just tested it with this code and no manipulation was required.

Local $sKey = "HKCR64CLSID{000C0114-0000-0000-C000-000000000046}InprocServer32"
Local $sVer = FileGetVersion(RegRead($sKey, ""))
MsgBox(0, "Result", $sVer)

Another key you couls use is

HKLM64SOFTWAREMicrosoftOffice<ver>CommonFilesPaths

RegEnum the HKLM64SOFTWAREMicrosoftOffice key until you can get a regread from CommonFilesPaths and the value that you will look at is mso.dll

Local $sKey = "HKLM64SoftwareMicrosoftOffice", $sVer, $sPath
$iKey = 1
While 1
$sVer = RegEnumKey($sKey, $iKey)
If @Error Then
  MsgBox(0, $iKey, "Oooops")
  Exit
EndIf
$sPath =  RegRead($sKey & $sVer & "CommonFilesPaths", "mso.dll")
If @Error Then
  MsgBox(0, "Error", @Error)
  $iKey += 1
  ContinueLoop
Else
  ExitLoop
EndIf
WEnd
MsgBox(0, "Result", FileGetVersion($sPath))

Local $sKey = "HKLM64SoftwareMicrosoftOffice", $sVer, $sPath

On computer of my friend was valid subkey under this key more than once because he installed also Microsoft Office Viewer.

That's why it's not 100% accurate because you can't programatically distinguish among all installed MS Office products.

If the above CLSID keys are the same in all situation then it can be the best solution how to get full path to mso.dll and then use FileGetVersion(mso.dll).

But I'm not experienced with all that messy CLSID stuff.

Share this post


Link to post
Share on other sites
GEOSoft

Are these values the same on ALL computers/ ALL versions of Windows/Office?

As far as I'm aware they are.

Search the registry for MSO.DLL

There are several places to get it from and If you take a look at

HKLM64SoftwareMicrosoftOffice<Ver> You should be able to find a value that you can use to verify with like

HKLM64SoftwareMicrosoftOffice<Ver>WordInstallRoot and read the "Path" value If it's not there then Word is not installed and in all likelihood neither is Office. You may also want to check the version of that file against the version of MSO.DLL

Also in the last code I posted you could do a StringRegExp() check to make sure it is returning only a valid version in $sVer

If NOT StringRegExp($sVer, "^d+.d$") Then
   $iKey += 1
  ContinueLoop
EndIf

EDIT:

MSO.DLL will always be in the same location so if all you want is that file version number then you shouldn't really need to worry about what Office components are installed.

Edited by GEOSoft

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites
Zedna

EDIT:

MSO.DLL will always be in the same location so if all you want is that file version number then you shouldn't really need to worry about what Office components are installed.

Yes I want to get FileGetVersion from mso.dll because it's base part of MS Office no matter which Office components were installed.

User can choose diferent (other than default) install directory.

Path of mso.dll can probably differ also on WinXP/Vista/7/32/64bit.

Share this post


Link to post
Share on other sites
GEOSoft

If NOT FileExists(@ProgramFilesDir & "Microsoft OfficeOffice" & StringRegExpReplace($sVer, "^(d+)D.*$", "$1") & "WinWord.exe") Then
Office probably isn't installed.

You couls also loop through an array containg all of the main exe files for the components in case they didn't install word but did install some other components. That's a highly unlikely scenario though.

I also wouldn't depend on the path @ProgramFilesDir & "Microsoft Office" and instead get it from registry.


George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites
GEOSoft

Yes I want to get FileGetVersion from mso.dll because it's base part of MS Office no matter which Office components were installed.

User can choose diferent (other than default) install directory.

Path of mso.dll can probably differ also on WinXP/Vista/7/32/64bit.

the path may differ but the keys I gave you should return the correct path to that file.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites
mlazovjp

I need to get name/version of installed Microsoft Office in form similar to that one in About window:

Microsoft Office Professional Plus 2010 (14.0.4763.1000)

 

This is a snippet of AutoIt code I use to activate Office 2010 and Office 2013 via script.

#include <Constants.au3>

Local $Office2010ProdctKey = 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'
Local $Office2013ProdctKey = 'XXXXX-XXXXX-XXXXX-XXXXX-XXXXX'

Local $OfficeCaption, $OfficeVersion, $ospp_path
getOfficeVersion($OfficeCaption, $OfficeVersion)

If $OfficeCaption = 'Unknown' Then
    MsgBox(0, $Title, 'Could not determine which version of MS Office is installed!  Please activate MS Office manually!' )
    Exit
EndIf

If StringInStr( $OfficeCaption, '2010' ) Then
    $ospp_path = getOSPP_Path($OfficeCaption)
    installNewOfficeProductKey($ospp_path, $Office2010ProdctKey)
    ActivateOffice($ospp_path)
ElseIf StringInStr( $OfficeCaption, '2013' ) Then
    $ospp_path = getOSPP_Path($OfficeCaption)
    installNewOfficeProductKey($ospp_path, $Office2013ProdctKey)
    ActivateOffice($ospp_path)
EndIf

Exit
;******************************************************************************


;******************************************************************************
Func getOfficeVersion(ByRef $OfficeCaption, ByRef $OfficeVersion)

    SplashTextOn( $Title, 'Determining which version of' & @CRLF & 'MS Office is installed ...', 400, 100, -1, -1, 16)
    ;ported code from http://support.moonpoint.com/os/windows/office/office_versions.php

    Local $strComputer = "."
    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")

    $colApps = $objWMIService.ExecQuery _
        ("Select * from Win32_Product Where Caption Like '%Microsoft Office Professional%'")
    For $objApp in $colApps
        $OfficeCaption = $objApp.Caption
        $OfficeVersion = $objApp.Version
        SplashOff()
        ;MsgBox ( 0, 'Debug', $OfficeVersion & $OfficeCaption)
        Return
    Next
    SplashOff()

    $OfficeCaption = 'Unknown'
    $OfficeVersion = 'Unknown'

EndFunc
;******************************************************************************


;******************************************************************************
Func getOSPP_Path(Const $OfficeCaption)

    Local $path

    If StringInStr( $OfficeCaption, '2010' ) Then

        If FileExists( 'C:\Program Files (x86)\Microsoft Office\Office14\ospp.vbs' ) Then
            return FileGetShortName( 'C:\Program Files (x86)\Microsoft Office\Office14\ospp.vbs' )

        ElseIf FileExists( 'C:\Program Files\Microsoft Office\Office14\ospp.vbs' ) Then
            return FileGetShortName( 'C:\Program Files\Microsoft Office\Office14\ospp.vbs' )

        EndIf

    ElseIf StringInStr( $OfficeCaption, '2013' ) Then

        If FileExists( 'C:\Program Files (x86)\Microsoft Office\Office15\ospp.vbs' ) Then
            return FileGetShortName( 'C:\Program Files (x86)\Microsoft Office\Office15\ospp.vbs' )

        ElseIf FileExists( 'C:\Program Files\Microsoft Office\Office15\ospp.vbs' ) Then
            return FileGetShortName( 'C:\Program Files\Microsoft Office\Office15\ospp.vbs' )

        EndIf

    EndIf

    return 'Unknown'

EndFunc
;******************************************************************************


;******************************************************************************
Func installNewOfficeProductKey(Const $ospp_path, Const $OfficeProdctKey)

    SplashTextOn( $Title, 'Installing Office Product Key ...', 400, 100, -1, -1, 16)

    Local $stdout = Run (@ComSpec & " /c cscript.exe " & $ospp_path & " /inpkey:" & $OfficeProdctKey, '', '', $STDERR_CHILD + $STDOUT_CHILD )
    Local $line
    While 1
        $line = $line & StdoutRead($stdout)
        If @error Then ExitLoop
    WEnd

    If StringInStr ( $line, 'ERROR CODE: 0xC004F050' ) Then
        SplashOff()
        MsgBox( 0, $Title, 'The product key is invalid!')
        Exit

    ElseIf StringInStr ( $line, '<Product key installation successful>' ) Then
        SplashTextOn( $Title, 'Product key installation was successful!', 400, 75, -1, -1, 16 )
        Sleep ( 2500 )
        SplashOff ( )
        return
    EndIf

    While 1
        $line = StderrRead($stdout)
        If @error Then Exit 1
        MsgBox(0, "STDERR read:", $line)
    Wend

    SplashOff()

EndFunc
;******************************************************************************



;******************************************************************************
Func ActivateOffice(Const $ospp_path)

    SplashTextOn( $Title, 'Activating Office ...', 400, 100, -1, -1, 16)

    Local $stdout = Run (@ComSpec & " /c cscript.exe " & $ospp_path & " /act", '', '', $STDERR_CHILD + $STDOUT_CHILD )
    Local $line
    While 1
        $line = $line & StdoutRead($stdout)
        If @error Then ExitLoop
    WEnd

    If StringInStr ( $line, '<Product activation successful>' ) Then
        SplashTextOn( $Title, 'Office Activation was successful!', 400, 75, -1, -1, 16 )
        Sleep ( 2500 )
        SplashOff ( )
        return
    Else
        SplashOff ( )
        MsgBox( 0, $Title, 'Office Activation failed!')
        Exit
    EndIf

    While 1
        $line = StderrRead($stdout)
        If @error Then Exit 1
        MsgBox(0, "STDERR read:", $line)
    Wend
    SplashOff ( )

EndFunc
;******************************************************************************

Share this post


Link to post
Share on other sites
Zedna

@mlazovjp

Thanks.

Good idea to use

$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")
    $colApps = $objWMIService.ExecQuery ("Select * from Win32_Product Where Caption Like '%Microsoft Office%'")

    For $objApp in $colApps
        ConsoleWrite($objApp.Caption & ' - ' & $objApp.Version & @CRLF)
    Next

Tested and it works fine.


 

Share this post


Link to post
Share on other sites
SnArF

Just for reference, this is how I do it.

$objWord = ObjCreate("Word.Application")
If IsObj($objWord) Then
    $OfficeVersion = $objWord.Version
    $objWord.Quit
Else
    $OfficeVersion = "N/A"
EndIf
Switch $OfficeVersion
    Case "7.0"
        $OfficeVersion = "97"
    Case "8.0"
        $OfficeVersion = "98"
    Case "9.0"
        $OfficeVersion = "2000"
    Case "10.0"
        $OfficeVersion = "2002"
    Case "11.0"
        $OfficeVersion = "2003"
    Case "12.0"
        $OfficeVersion = "2007"
    Case "14.0"
        $OfficeVersion = "2010"
    Case "15.0"
        $OfficeVersion = "2013"
    Case "16.0"
        $OfficeVersion = "2016"
    Case "N/A"
        $OfficeVersion = "Not Available"
    Case Else
        $OfficeVersion = "Unknown!"
EndSwitch

MSGBOX(64,"Office Info","Microsoft Office Version:"&@LF&$OfficeVersion)

 


My scripts: _ConsoleWriteLog | _FileArray2D

 

 

 

Share this post


Link to post
Share on other sites
JLogan3o13

@SnArF Please stop resurrecting old posts, especially when they've already been answered (3 years ago) to the OP's satisfaction.


√-1 2^3 ∑ π, and it was delicious!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×