Jul 26, 2007

Is MS Office installed on a computer?

There are more ways to detect if MS Excel, Outlook or Word is installed on a computer. One way is, to look it up in the Window registry.
The following code does exactly that.

* Code that shows if Outlook, Word and Excel are installed:

ckey = "Software\Microsoft\Windows\CurrentVersion\App Paths\outlook.exe"
OutlookExists = readregstring(-2147483646, ckey, "path")

ckey = "Software\Microsoft\Windows\CurrentVersion\App Paths\winword.exe"
WinWordExists = readregstring(-2147483646, ckey, "path")

ckey = "Software\Microsoft\Windows\CurrentVersion\App Paths\excel.exe"
ExcelExists = readregstring(-2147483646, ckey, "path")

? !EMPTY(NVL(OutlookExists,""))
? !EMPTY(NVL(WinWordExists,""))
? !EMPTY(NVL(ExcelExists,""))

The code makes use of a function called 'readregstring' That function is:

***----------------------------------------------------------------------
*** Function: Reads a string value from the registry.
*** Pass: tnHKEY - HKEY value (in CGIServ.h)
*** tcSubkey - The Registry subkey value
*** tcEntry - The actual Key to retrieve
*** Return: Registry String or .NULL. on error
***----------------------------------------------------------------------
LPARAMETERS tnHKey, tcSubkey, tcEntry
LOCAL lnRegHandle, lnResult, lnSize, lcDataBuffer, tnType

tnHKey=IIF(type("tnHKey")="N",tnHKey,This.HKEY_LOCAL_MACHINE)

lnRegHandle=0

DO DeclareInit && Declare WinAPI function. You only have to do this once.

*** Open the registry key
lnResult=RegOpenKey(tnHKey,tcSubKey,@lnRegHandle)
IF lnResult # 0
RETURN .NULL.
ENDIF

*** Need to define here specifically for Return Type
*** for lpdData parameter or VFP will choke.
*** Here it's STRING.
DECLARE INTEGER RegQueryValueEx ;
IN Win32API AS RegQueryString;
INTEGER nHKey,;
STRING lpszValueName,;
INTEGER dwReserved,;
INTEGER @lpdwType,;
STRING @lpbData,;
INTEGER @lpcbData

*** Return buffer to receive value
lcDataBuffer=space(256)
lnSize=LEN(lcDataBuffer)
lnType=0

lnResult=RegQueryString(lnRegHandle,tcEntry,0,@lnType,;
@lcDataBuffer,@lnSize)

=RegCloseKey(lnRegHandle)

IF lnResult # 0
RETURN .NULL.
ENDIF

IF lnSize<2
RETURN ""
ENDIF

*** Return string based on length returned
RETURN SUBSTR(lcDataBuffer,1,lnSize-1)

And the DeclareInit function that is called:

*** Open a registry key
DECLARE INTEGER RegOpenKey ;
IN Win32API ;
INTEGER nHKey,;
STRING cSubKey,;
INTEGER @nHandle

*** Close an open registry key
DECLARE Integer RegCloseKey ;
IN Win32API ;
INTEGER nHKey