There might be occasions when you want to determine programmatically whether a Microsoft® Office XP product or specific application is installed on a computer. For example, you might want to check for a successful installation of Office XP, or check whether Microsoft Outlook® is installed before taking different actions in a network logon script. There are two general methods to accomplish such tasks — checking the Windows registry, or using Windows Installer API functions.
Note The Windows Installer API functions mentioned in this article are documented in the Windows Installer Help (Msi.chm) file, which can be downloaded from the Windows Installer SDK (x86) Web site.
Checking for an Office XP product
The registry key HKLM\Software\Microsoft\Office\10.0\Common\InstallRoot is written to the Windows registry by Setup for Office XP family products. This key will indicate whether an Office XP product or specific Office XP application is installed, but it will not identify the product or application. For example, this method returns the same result whether Office XP Professional or stand-alone Word 2002 is installed.
The following Visual Basic code will display the path where any Office XP family products are installed:
Sub CheckOfficeXPInstalled()
InstallRoot = System.PrivateProfileString("", _
"HKEY_LOCAL_MACHINE\Software\Microsoft\Office\10.0\Common\InstallRoot", _
"Path")
If InstallRoot <> "" Then
MsgBox "An Office XP Family Product is installed at " & InstallRoot
End If
End Sub
If you want to determine the specific Office XP product that is installed, you can check the product ID. All Office XP products have unique product IDs (GUIDs) that are stored by Windows Installer in the Windows registry. You can access these GUIDs by calling the Windows Installer API function MSIEnumProducts().
Windows Installer product IDs for Office family products are identical in the lower 24 hexadecimal digits and have a specific structure in the top eight hex digits. These upper digits define the product release type (for example, Beta, RTM, SR-1), SKU (for example, Office Professional), and language ID (for example, English = 1033).
The Office family product ID follows this format:
WXYYZZZZ-6000-11D3-8CFE-0050048383C9
To determine if Office XP is installed, call MsiEnumProducts() successively, checking the last 24 hex digits of the returned GUIDs for the value 6000-11D3-8CFE-0050048383C9.
If you find it, you can check the upper eight digits of the GUID for specific product information. The upper eight hex digits are defined as follows:
W = type of release
0 = Any release before Beta 1
1 = Beta 1
2 = Beta 2
3 = RC0 (preliminary release candidate)
4 = RC1/OEM Preview Release
5-8 = Reserved
9 = RTM (first shipped version)
A = SR1 (unused if the product code is not changed after RTM)
B = SR2 (unused if the product code is not changed after RTM)
C = SR3 (unused if the product code is not changed after RTM)
D-F = Reserved
X = type of SKU
0 = Enterprise
1 = Retail/OEM
2 = Trial
YY = specific SKU
10 = Microsoft Office XP Premium
11 = Microsoft Office XP Professional
12 = Microsoft Office XP Standard
13 = Microsoft Office XP Small Business
14 = Microsoft Office XP Web Server
15 = Microsoft Access 2002
16 = Microsoft Excel 2002
17 = Microsoft FrontPage® 2002
18 = Microsoft PowerPoint® 2002
19 = Microsoft Publisher 2002
1A = Microsoft Outlook 2002
1B = Microsoft Word 2002
1C = Microsoft Access 2002 Runtime
1D = Microsoft FrontPage Server Extensions 2002
1E = Microsoft Office Multilingual User Interface Pack
1F = Microsoft Office Proofing Tools Kit
20 = System Files Update
22 = Microsoft PhotoDraw® 2002
23 = Microsoft Office Multilingual User Interface Pack Wizard
24 = Microsoft Office XP Resource Kit
25 = Microsoft Office XP Resource Kit Tools
26 = Microsoft Office Web Components
27 = Microsoft Project 2002
28 = Microsoft Office XP Professional with FrontPage
29 = Microsoft Office XP Professional Annuity
2A = Microsoft Office XP Small Business Edition Annuity
2B = Microsoft Publisher 2002 Deluxe Edition
2F = Standalone IME (JPN Only)
30 = Microsoft Office XP Media Content
31 = Microsoft Project 2002 Web Client
32 = Microsoft Project 2002 Web Server
33 = Microsoft Office XP PIPC1 (Pre Installed PC) (JPN Only)
34 = Microsoft Office XP PIPC2 (Pre Installed PC) (JPN Only)
35 = Microsoft Office XP Media Content Deluxe
ZZZZ = locale ID (LCID) encoded in hexadecimal; for example, the LCID for English is 1033 decimal which is equivalent to 0409 hex
Checking for an Office XP application
Once you have determined whether an Office XP product is installed, you can further determine which Office applications are installed.
Each Office application has a core component that is always installed when the application is installed. This component is not localized, so the component GUID will be the same across all languages for that component. With the component GUID from the following table, and the Office product ID described in the section above, you can use the Windows Installer API function MsiGetComponentPath to determine whether a particular core component is installed, and, therefore, whether the associated application is installed.
| This Office application… |
Has this core component… |
Which has this component ID |
| Access 2002 |
Global_Access_Core |
{CC29E967-7BC2-11D1-A921-00A0C91E2AA3} |
| Excel 2002 |
Global_Excel_Core |
{5572D282-F5E5-11D3-A8E8-0060083FD8D3} |
| FrontPage 2002 |
Global_FrontPageCore_CoreClient |
{F8119365-D2DA-11D3-8631-00500483860A} |
| Outlook 2002 |
Global_Outlook_Core |
{DE6A97CD-93BF-455C-A45F-7694344B686F} |
| PowerPoint 2002 |
Global_PowerPoint_Core |
{FC780C4C-F066-40E0-B720-DA0F779B81A9} |
| Publisher 2002 |
Global_Publisher_Core |
{CEC0B86F-7548-4BC0-B05C-E7150E4397E3} |
| Word 2002 |
Global_Word_Core |
{8E46FEFA-D973-6294-B305-E968CEDFFCB9} |
Another method for determining whether a specific Office application is installed is to look for keys written to the Windows registry for use by the Office Language Settings application (“setlang”). Using the component ID {F1BD4371-EFFB-11D3-8D33-0050048381D3}, call MsiEnumComponentQualifiers successively, looking for a return value in lpApplicationDataBuf of “setlang.” When you find it, lpQualifierBuf will contain the application name with the LCID appended, as shown in the following table. For example, if the English version of Access 2002 is installed, lpQualifierBuf will return “Access\1033”.
| SzComponent |
LpQualifierBuf |
lpApplicationDataBuf |
| {F1BD4371-EFFB-11D3-8D33-0050048381D3} |
Access\lcid |
setlang |
| {F1BD4371-EFFB-11D3-8D33-0050048381D3} |
Excel\lcid |
setlang |
| {F1BD4371-EFFB-11D3-8D33-0050048381D3} |
FrontPage\lcid |
setlang |
| {F1BD4371-EFFB-11D3-8D33-0050048381D3} |
Outlook\lcid |
setlang |
| {F1BD4371-EFFB-11D3-8D33-0050048381D3} |
PowerPoint\lcid |
setlang |
| {F1BD4371-EFFB-11D3-8D33-0050048381D3} |
Word\lcid |
setlang |
| {F1BD4371-EFFB-11D3-8D33-0050048381D3} |
Publisher\lcid |
setlang |
Sample C code
The following sample code in C includes two procedures that may be used to determine if Office XP is installed:
- FIsOfficeXPInstalled Returns TRUE if any Office XP product is installed.
- FIsOfficeXPProductInstalled(szProductID) Returns TRUE if the specified Office XP product is installed.
The parameter szProductID points to two hex digits containing the Product SKU ID as given in the table earlier in this article. For example, the Product SKU ID for Office XP Standard Edition is hex 12.
Note The header file msi.h and library file msi.lib are included in the Windows Installer Software Development Kit (SDK). You can download the Windows Installer 1.1 SDK from the Windows Installer SDK (x86).
#include <msi.h>
#define GUID_LENGTH 39
/*-----------------------------------------------------------------------
* fIsOfficeXPProductCode
*
* All Office XP family product codes are of the form
*
* {WXYYZZZZ-6000-11D3-8CFE-0050048383C9}
*
* Where the top 8 hex digits vary programatically per product and
* the bottom 24 hex digits are constant.
*
* Parameters
* - szProductCode Windows Installer Product Code
*
* Return Values
* - TRUE if product code is from the Office XP family, FALSE otherwise.
*
* Remarks
* - none
-----------------------------------------------------------------------*/
BOOL fIsOfficeXPProductCode(char *szProductCode)
{
// Are the last 24 digits from an Office XP product code?
return !lstrcmp("6000-11D3-8CFE-0050048383C9}", &szProductCode[10]);
}
/*------------------------------------------------------------------------
* fIsOfficeXPInstalled
*
* Enumerates through products installed by the Windows Installer looking
* for an Office XP family product.
*
* Parameters
* - none
*
* Return Values
* - TRUE if an Office XP family product is installed.
* - FALSE if an Office XP family product isn’t installed or error occurs.
*
* Remarks
* - Masks errors returned from MsiEnumProducts.
-----------------------------------------------------------------------*/
BOOL fIsOfficeXPInstalled()
{
DWORD dwIndex = 0;
char szProductCode[GUID_LENGTH];
while(ERROR_SUCCESS == MsiEnumProducts(dwIndex++, szProductCode))
{
if(fIsOfficeXPProductCode(szProductCode))
return TRUE;
}
return FALSE;
}
/*-----------------------------------------------------------------------
* fIsOfficeXPProductInstalled
*
* Enumerates through products installed by the Windows Installer looking
* for a specific Office XP family product (i.e. Word Standalone).
* All Office XP family product codes are of the form
*
* {WXYYZZZZ-6000-11D3-8CFE-0050048383C9}
*
* Where the top 8 hex digits vary programatically per product and the
* bottom 24 hex digits are constant. The YY digits specify the various
* XP products (i.e. Word Standalone is "1B", Excel Standalone is "16").
*
* Parameters
* - szProductId points to two hex digits between 0x0F and 0x35 that
* identify the Office XP family product to search for.
*
* Return Values
* - TRUE if the specified Office XP family product is installed.
* - FALSE if an Office XP family product isn’t installed or error occurs.
*
* Remarks
* - Masks errors returned from MsiEnumProducts.
-----------------------------------------------------------------------*/
BOOL fIsOfficeXPProductInstalled(char *szProductId)
{
DWORD dwIndex = 0;
char szProductCode[GUID_LENGTH];
while(ERROR_SUCCESS == MsiEnumProducts(dwIndex++, szProductCode))
{
// Is this the Office XP product we are looking for?
if(fIsOfficeXPProductCode(szProductCode) &&
(szProductId[0] == szProductCode[3]) &&
(szProductId[1] == szProductCode[4]))
return TRUE;
}
return FALSE;
}