Description

For information about how to use the ROIScan.vbs script to collect data
about Office installations and to help detect and troubleshoot installation and
updates errors, see Collect data
about Office installations by using Robust Office Inventory Scan
.

 

Changes for version 1.9.1
- Added:   Office 2019 awareness
- Updated: Improved Office license detection
- Fixed:   Handling of Groove (OneDrive sync client) after deprecation
- Updated: New channel names
- Updated: C2R configuration settings detection
- Updated: General code maintenance


Script

VB Script
Edit|Remove
' Name: Robust Office Inventory Scan - Version 1.9.1 
' Author: Microsoft Customer Support Services 
' Copyright (c) Microsoft Corporation. All rights reserved. 
' Script to create an inventory scan of installed Office applications 
' Supported Office Families: 2000, 2002, 2003, 2007 
'                            2010, 2013, 2016, O365 
 
Option Explicit 
On Error Resume Next 
Const SCRIPTBUILD = "1.9.1" 
Dim sPathOutputFolder : sPathOutputFolder = "" 
Dim fQuiet : fQuiet = False 
Dim fLogFeatures : fLogFeatures = False 
Dim fLogFull : fLogFull = False 
dim fBasicMode : fBasicMode = False 
Dim fLogChainedDetails : fLogChainedDetails = False 
Dim fLogVerbose : fLogVerbose = False 
Dim fListNonOfficeProducts : fListNonOfficeProducts = False 
Dim fFileInventory : fFileInventory = False 
Dim fFeatureTree : fFeatureTree = False 
Dim fDisallowCScript : fDisallowCScript = False 
 
'======================================================================================================= 
'[INI] Section for script behavior customizations 
 
'Directory for Log output. 
'Example: "\\<server>\<share>\" 
'Default: sPathOutputFolder = vbNullString -> %temp% directory is used 
sPathOutputFolder = "" 
 
'Quiet switch. 
'Default: False -> Open inventory log when done 
fQuiet = False 
 
 
'Basic Mode 
'Generates a basic list of installed Office products with licensing information only 
'Disables all other extended analysis options 
'Default: False -> Allow extended analysis options 
fBasicMode = False 
 
'Log full (verbose) details. This enables all possible scans for Office products. 
'Default: False -> Only list standard details 
fLogFull = False 
 
'Enables additional logging details 
'like the "FeatureTree" display and 
'the additional individual listing of the chained Office SKU's 
'Default: False -> Do not log additional details 
fLogVerbose = False 
 
'Starting with Office 2007 a SKU can contain several .msi packages 
'The default does not list the details for each chained package 
'This option allows to show the full details for each chained package 
'Default: Comprehensive view - do not show details for chained packages 
fLogChainedDetails = False 
 
'The script filters for products of the Microsoft Office family. 
'Set this option to 'True' to get a list of all Windows Installer products in the inventory log 
'Default: False -> Don't list other products in the log 
fListNonOfficeProducts = False 
 
'File level inventory of installed Office products 
'Depending on the number of installed products this can be an extremely time consuming task! 
'Default: False -> Don't create a file level inventory 
fFileInventory = False 
 
'Detect all features of a product and include a feature tree in the log 
'Default: False -> Don't include the feature detection 
fFeatureTree = False 
 
'DO NOT CUSTOMIZE BELOW THIS LINE! 
'======================================================================================================= 
 
'Measure total scan runtime 
Dim tStart, tEnd 
tStart = Time() 
'Call the command line parser 
ParseCmdLine 
'Definition of non customizable settings 
'Strings  
Dim sComputerName, sTemp, sCurUserSid, sDebugErr, sError, sErrBpa, sProductCodes_C2R 
Dim sStack, sCacheLog, sLogFile, sInstalledProducts, sSystemType, sLogFormat 
Dim sPackageGuid, sUserName, sDomain 
'Arrays 
Dim arrAllProducts(), arrMProducts(), arrUUProducts(), arrUMProducts(), arrMaster(), arrArpProducts() 
Dim arrVirtProducts(), arrVirt2Products(), arrVirt3Products(), arrPatch(), arrAipPatch, arrMspFiles 
Dim arrLog(4), arrLogFormat(), arrUUSids(), arrUMSids(), arrMVProducts(), arrIS(), arrFeature() 
Dim arrProdVer09(), arrProdVer10(), arrProdVer11(), arrProdVer12(), arrProdVer14(), arrProdVer15() 
Dim arrProdVer16(), arrFiles(), arrLicenese() 
'Booleans 
Dim fIsAdmin, fIsElevated, fIsCriticalError, fGuidCaseWarningOnly, f64, fPatchesOk, fPatchesExOk 
Dim fCScript, bOsppInit, fZipError, fInitArrProdVer, fv2SxS  
'Integers 
Dim iWiVersionMajor, iVersionNt, iPCount, iPatchesExError, iVMVirtOverride 
'Dictionaries 
Dim dicFolders, dicAssembly, dicMspIndex, dicProducts, dicArp, dicMissingChild 
Dim dicPatchLevel, dicScenario, dicKeyComponents 
Dim dicPolHKCU, dicPolHKLM 
Dim dicProductCodeC2R, dicActiveC2RVersions, dicMapArpToConfigID 
Dim dicKeyComponentsV2, dicScenarioV2, dicC2RPropV2, dicVirt2Cultures 
Dim dicKeyComponentsV3, dicScenarioV3, dicC2RPropV3, dicVirt3Cultures 
'Other 
Dim oMsi, oShell, oFso, oReg, oWsh, oWMILocal 
Dim TextStream, ShellApp, AppFolder, Ospp, Spp 
 
'Identifier for product family 
Const OFFICE_ALL                      = "78E1-11D2-B60F-006097C998E7}.0001-11D2-92F2-00104BC947F0}.6000-11D3-8CFE-0050048383C9}.6000-11D3-8CFE-0150048383C9}.7000-11D3-8CFE-0150048383C9}.BE5F-4ED1-A0F7-759D40C7622E}.BDCA-11D1-B7AE-00C04FB92F3D}.6D54-11D4-BEE3-00C04F990354}.CFDA-404E-8992-6AF153ED1719}.{9AC08E99-230B-47e8-9721-4577B7F124EA}" 
'Office 2000 -> KB230848; Office XP -> KB302663; Office 2003 -> KB832672 
Const OFFICE_2000                     = "78E1-11D2-B60F-006097C998E7}" 
Const ORK_2000                        = "0001-11D2-92F2-00104BC947F0}" 
Const PRJ_2000                        = "BDCA-11D1-B7AE-00C04FB92F3D}" 
Const VIS_2002                        = "6D54-11D4-BEE3-00C04F990354}" 
Const OFFICE_2002                     = "6000-11D3-8CFE-0050048383C9}" 
Const OFFICE_2003                     = "6000-11D3-8CFE-0150048383C9}" 
Const WSS_2                           = "7000-11D3-8CFE-0150048383C9}" 
Const SPS_2003                        = "BE5F-4ED1-A0F7-759D40C7622E}" 
Const PPS_2007                        = "CFDA-404E-8992-6AF153ED1719}" 'Project Portfolio Server 2007 
Const POWERPIVOT_2010                 = "{72F8ECCE-DAB0-4C23-A471-625FEDABE323}, {A37E1318-29CA-4A9F-9CCA-D9BFDD61D17B}" 'UpgradeCode! 
Const O15_C2R                         = "{9AC08E99-230B-47e8-9721-4577B7F124EA}" 
Const OFFICEID                        = "000-0000000FF1CE}" 'cover O12, O14 with 32 & 64 bit 
Const OREGREFC2R15                    = "Microsoft Office 15" 
 
'SPP AppId 
Const OFFICE14APPID                   = "59a52881-a989-479d-af46-f275c6370663" 
Const OFFICEAPPID                     = "0ff1ce15-a989-479d-af46-f275c6370663" 
 
Const PRODLEN                         = 13 
Const FOR_READING                     = 1 
Const FOR_WRITING                     = 2 
Const FOR_APPENDING                   = 8 
Const TRISTATE_USEDEFAULT             = -2 'Opens the file using the system default.  
Const TRISTATE_TRUE                   = -1 'Opens the file as Unicode.  
Const TRISTATE_FALSE                  = 0  'Opens the file as ASCII.  
 
Const USERSID_EVERYONE                = "s-1-1-0" 
Const MACHINESID                      = "" 
Const PRODUCTCODE_EMPTY               = "" 
Const MSIOPENDATABASEMODE_READONLY    = 0 
Const MSIOPENDATABASEMODE_PATCHFILE   = 32 
Const MSICOLUMNINFONAMES              = 0 
Const MSICOLUMNINFOTYPES              = 1 
'Summary Information fields 
Const PID_TITLE                       = 2 'Type of installer package. E.g. "Installation Database" or "Transform" or "Patch" 
Const PID_SUBJECT                     = 3 'Displayname 
Const PID_TEMPLATE                    = 7 'compatible platform and language versions for .msi / PatchTargets for .msp 
Const PID_REVNUMBER                   = 9 'PackageCode 
Const PID_WORDCOUNT                   = 15'InstallSource type  
Const MSIPATCHSTATE_UNKNOWN           = -1 'Patch is in an unknown state to this product instance.  
Const MSIPATCHSTATE_APPLIED           = 1 'Patch is applied to this product instance.  
Const MSIPATCHSTATE_SUPERSEDED        = 2 'Patch is applied to this product instance but is superseded.   
Const MSIPATCHSTATE_OBSOLETED         = 4 'Patch is applied in this product instance but obsolete.   
Const MSIPATCHSTATE_REGISTERED        = 8 'The enumeration includes patches that are registered but not yet applied. 
Const MSIPATCHSTATE_ALL               = 15 
Const MSIINSTALLCONTEXT_USERMANAGED   = 1 
Const MSIINSTALLCONTEXT_USERUNMANAGED = 2 
Const MSIINSTALLCONTEXT_MACHINE       = 4 
Const MSIINSTALLCONTEXT_ALL           = 7 
Const MSIINSTALLCONTEXT_C2RV2         = 8 'C2r V2 virtualized context 
Const MSIINSTALLCONTEXT_C2RV3         = 15 'C2r V3 virtualized context 
Const MSIINSTALLMODE_DEFAULT          = 0    'Provide the component and perform any installation necessary to provide the component.  
Const MSIINSTALLMODE_EXISTING         = -1   'Provide the component only if the feature exists. This option will verify that the assembly exists. 
Const MSIINSTALLMODE_NODETECTION      = -2   'Provide the component only if the feature exists. This option does not verify that the assembly exists. 
Const MSIINSTALLMODE_NOSOURCERESOLUTION = -3 'Provides the assembly only if the assembly is installed local. 
 Const MSIPROVIDEASSEMBLY_NET         = 0    'A .NET assembly. 
Const MSIPROVIDEASSMBLY_WIN32         = 1    'A Win32 side-by-side assembly. 
Const MSITRANSFORMERROR_ALL           = 319 
'Installstates for products, features, components 
Const INSTALLSTATE_NOTUSED            = -7 ' component disabled 
Const INSTALLSTATE_BADCONFIG          = -6 ' configuration data corrupt 
Const INSTALLSTATE_INCOMPLETE         = -5 ' installation suspended or in progress 
Const INSTALLSTATE_SOURCEABSENT       = -4 ' run from source, source is unavailable 
Const INSTALLSTATE_MOREDATA           = -3 ' return buffer overflow 
Const INSTALLSTATE_INVALIDARG         = -2 ' invalid function argument. The product/feature is neither advertised or installed.  
Const INSTALLSTATE_UNKNOWN            = -1 ' unrecognized product or feature 
Const INSTALLSTATE_BROKEN             =  0 ' broken 
Const INSTALLSTATE_ADVERTISED         =  1 ' The product/feature is advertised but not installed.  
Const INSTALLSTATE_REMOVED            =  1 ' The component is being removed (action state, not settable) 
Const INSTALLSTATE_ABSENT             =  2 ' The product/feature is not installed.  
Const INSTALLSTATE_LOCAL              =  3 ' The product/feature/component is installed.  
Const INSTALLSTATE_SOURCE             =  4 ' The product or feature is installed to run from source, CD, or network.  
Const INSTALLSTATE_DEFAULT            =  5 ' The product or feature will be installed to use the default location: local or source. 
Const INSTALLSTATE_VIRTUALIZED        =  8 ' The product is virtualized (C2R). 
Const VERSIONCOMPARE_LOWER            = -1 ' Left hand file version is lower than right hand  
Const VERSIONCOMPARE_MATCH            =  0 ' File versions are identical 
Const VERSIONCOMPARE_HIGHER           =  1 ' Left hand file versin is higher than right hand 
Const VERSIONCOMPARE_INVALID          =  2 ' Cannot compare. Invalid compare attempt. 
 
Const COPY_OVERWRITE                  = &H10& 
Const COPY_SUPPRESSERROR              = &H400&  
 
Const HKEY_CLASSES_ROOT               = &H80000000 
Const HKEY_CURRENT_USER               = &H80000001 
Const HKEY_LOCAL_MACHINE              = &H80000002 
Const HKEY_USERS                      = &H80000003 
Const HKCR                            = &H80000000 
Const HKCU                            = &H80000001 
Const HKLM                            = &H80000002 
Const HKU                             = &H80000003 
Const KEY_QUERY_VALUE                 = &H0001 
Const KEY_SET_VALUE                   = &H0002 
Const KEY_CREATE_SUB_KEY              = &H0004 
Const DELETE                          = &H00010000 
Const REG_SZ                          = 1 
Const REG_EXPAND_SZ                   = 2 
Const REG_BINARY                      = 3 
Const REG_DWORD                       = 4 
Const REG_MULTI_SZ                    = 7 
Const REG_QWORD                       = 11 
Const REG_GLOBALCONFIG                = "SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\" 
Const REG_CONTEXTMACHINE              = "Installer\" 
Const REG_CONTEXTUSER                 = "Software\Microsoft\Installer\" 
Const REG_CONTEXTUSERMANAGED          = "Software\Microsoft\Windows\CurrentVersion\Installer\Managed\" 
Const REG_ARP                         = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" 
Const REG_OFFICE                      = "SOFTWARE\Microsoft\Office\" 
Const REG_C2RVIRT_HKLM                = "\ClickToRun\REGISTRY\MACHINE\" 
 
Const STR_NOTCONFIGURED             = "<Not Configured>" 
Const STR_NOTCONFIGUREDXML          = "NotConfigured" 
Const STR_PACKAGEGUID               = "PackageGUID" 
Const STR_REGPACKAGEGUID            = "RegPackageGUID" 
Const STR_BUILDNUMBER               = "BuildNumber" 
Const STR_VERSIONTOREPORT           = "BuildVersionToReport" 
Const STR_VERSION                   = "Version" 
Const STR_PLATFORM                  = "Platform" 
Const STR_OFFICEMGMTCOM             = "OfficeMgmtCom" 
Const STR_CDNBASEURL                = "CDNBaseUrl" 
Const STR_LASTUSEDBASEURL           = "Last used InstallSource" 
Const STR_UPDATELOCATION            = "Custom UpdateLocation" 
Const STR_USEDUPDATELOCATION        = "Winning UpdateLocation" 
Const STR_UPDATESENABLED            = "UpdatesEnabled" 
Const STR_UPDATECHANNEL             = "UpdateChannel" 
Const STR_UPDATETOVERSION           = "UpdateToVersion" 
Const STR_UPDATETHROTTLE            = "UpdatesThrottleValue" 
Const STR_POLUPDATESENABLED         = "Policy UpdatesEnabled" 
Const STR_POLUPGRADEENABLED         = "Policy EnableAutomaticUpgrade" 
Const STR_POLUPDATECHANNEL          = "Policy UpdateChannel" 
Const STR_POLUPDATELOCATION         = "Policy UpdateLocation" 
Const STR_POLUPDATETOVERSION        = "Policy UpdateToVersion" 
Const STR_POLUPDATEDEADLINE         = "Policy UpdateDeadline" 
Const STR_POLUPDATENOTIFICATIONS    = "Policy UpdateHideNotifications" 
Const STR_POLHIDEUPDATECFGOPT       = "Policy HideUpdateConfigOptions" 
Const STR_SCA                       = "Shared Computer Licensing" 
Const STR_POLSCACACHEOVERRIDE       = "Policy SCLCacheOverride" 
Const STR_POLSCACACHEOVERRIDEDIR    = "Policy SCLCacheOverrideDirectory" 
Const STR_POLOFFICEMGMTCOM          = "Policy OfficeMgmtCom" 
 
Const GUID_UNCOMPRESSED               = 0 
Const GUID_COMPRESSED                 = 1 
Const GUID_SQUISHED                   = 2 
Const LOGPOS_COMPUTER                 = 0 '    ArrLogPosition 0: "Computer" 
Const LOGPOS_REVITEM                  = 1 '    ArrLogPosition 1: "Review Items" 
Const LOGPOS_PRODUCT                  = 2 '    ArrLogPosition 2: "Products Inventory" 
Const LOGPOS_RAW                      = 3 '    ArrLogPosition 3: "Raw Data" 
Const LOGHEADING_NONE                 = 0 '    Not a heading 
Const LOGHEADING_H1                   = 1 '    Heading 1 '=' 
Const LOGHEADING_H2                   = 2 '    Heading 2 '-' 
Const LOGHEADING_H3                   = 3 '    Heading 3 ' ' 
Const TEXTINDENT                      = "                        " 
Const CATEGORY                        = 1 
Const TAG                             = 2 
 
'Global_Access_Core - msaccess.exe 
Const CID_ACC16_64 = "{27C919A6-3FA5-47F9-A3EC-BC7FF2AAD452}" 
Const CID_ACC16_32 = "{E34AA7C4-8845-4BD7-BAC6-26554B60823B}" 
Const CID_ACC15_64 = "{3CE2B4B3-DA38-4113-8DB2-965847CDE94F}" 
Const CID_ACC15_32 = "{A3E12EF0-7C3B-4493-99A3-F92FCD0AA512}" 
Const CID_ACC14_64 = "{02F5CBEC-E7B5-4FC1-BD72-6043152BD1D4}" 
Const CID_ACC14_32 = "{AE393348-E564-4894-B8C5-EBBC5E72EFC6}" 
Const CID_ACC12    = "{0638C49D-BB8B-4CD1-B191-054E8F325736}" 
Const CID_ACC11    = "{F2D782F8-6B14-4FA4-8FBA-565CDDB9B2A8}" 
'Global_Excel_Core - excel.exe 
Const CID_XL16_64 = "{C4ACE6DB-AA99-401F-8BE6-8784BD09F003}" 
Const CID_XL16_32 = "{C845E028-E091-442E-8202-21F596C559A0}" 
Const CID_XL15_64 = "{58A9998B-6103-436F-85A1-52720802CA0A}" 
Const CID_XL15_32 = "{107E1A9A-03AE-4F2B-ACF7-0CC519E60E7B}" 
Const CID_XL14_64 = "{8B1BF0B4-A1CA-4656-AA46-D11C50BC55A4}" 
Const CID_XL14_32 = "{538F6C89-2AD5-4006-8154-C6670774E980}" 
Const CID_XL12    = "{0638C49D-BB8B-4CD1-B191-052E8F325736}" 
Const CID_XL11    = "{A2B280D4-20FB-4720-99F7-40C09FBCE10A}" 
'WAC_CoreSPD - spdesign.exe (frontpage.exe) 
Const CID_SPD16_64 = "{2FB768AF-8F57-424A-BBDA-81611CFF3ED2}" 
Const CID_SPD16_32 = "{C3F352B2-A43B-4948-AE54-12E265647697}" 
Const CID_SPD15_64 = "{25B4430E-E7D6-406F-8468-D9B65BC240F3}" 
Const CID_SPD15_32 = "{0F0A451D-CB3C-44BE-B8A4-E72C2B89C4A2}" 
Const CID_SPD14_64 = "{6E4D3AA2-2AD9-4DD2-8C2D-8C55B656A5C9}" 
Const CID_SPD14_32 = "{E5344AC3-915E-4655-AF0D-98BC878805DC}" 
Const CID_SPD12    = "{0638C49D-BB8B-4CD1-B191-056E8F325736}" 
Const CID_SPD11    = "{81E9830C-5A6B-436A-BEC9-4FB759282DE3}" ' FrontPage 
'Groove_Core - groove.exe 
Const CID_GRV16_64 = "{EEE31981-E2D9-45AE-B134-FD9276C19588}" 
Const CID_GRV16_32 = "{6C26357C-A2D8-4C68-8BC6-A8091BECDA02}" 
Const CID_GRV15_64 = "{AD8AD7F2-98CB-4257-BE7A-05CBCA1354B4}" 
Const CID_GRV15_32 = "{87E86C36-1368-4841-9152-766F31BC46E8}" 
Const CID_GRV14_64 = "{61CD70FF-C6B7-4F6A-8491-5B8B9B0040F8}" 
Const CID_GRV14_32 = "{EFE67578-E52B-410E-9178-9911443DBF5A}" 
Const CID_GRV12    = "{0A048D77-2DE9-4672-ACF7-12429662397D}" 
'Lync_Corelync - lync.exe 
Const CID_LYN16_64 = "{3CFF5AB2-9B16-4A31-BC3F-FAD761D92780}" 
Const CID_LYN16_32 = "{E1AFBCD9-12F0-4FC0-9177-BFD3148AEC74}" 
Const CID_LYN15_64 = "{D5B16A67-9FA6-4B77-AE2A-3B1F49CE9D3B}" 
Const CID_LYN15_32 = "{F8D36F1C-6196-4FFA-94AA-736644D458E3}" 
'Global_OneNote_Core - onenote.exe 
Const CID_ONE16_64 = "{8265A5EF-46C7-4D46-812C-076F2A28F7CB}" 
Const CID_ONE16_32 = "{2A8FA8D7-B728-4792-AC02-463FD7A423BD}" 
Const CID_ONE15_64 = "{74F233A9-A17A-477C-905F-853F5FCDAD40}" 
Const CID_ONE15_32 = "{DACE5A15-C57C-44DE-9AFF-89B4412485AF}" 
Const CID_ONE14_64 = "{9542A6E5-2FAF-4191-B525-6ED00F2D0127}" 
Const CID_ONE14_32 = "{62F8C897-D359-4D8F-9659-CF1E9E3E6B74}" 
Const CID_ONE12    = "{0638C49D-BB8B-4CD1-B191-057E8F325736}" 
Const CID_ONE11    = "{D2C0E18B-C463-4E90-92AC-CA94EBEC26CE}" 
'Global_Office_Core - mso.dll 
Const CID_MSO16_64 = "{625F5772-C1B3-497E-8ABE-7254EDB00506}" 
Const CID_MSO16_32 = "{68477CB0-662A-48FB-AF2E-9573C92869F7}" 
Const CID_MSO15_64 = "{D01398A1-F26F-4545-A441-567F097A57D7}" 
Const CID_MSO15_32 = "{9CC2CF5E-9A2E-41AC-AF95-432890A9659A}" 
Const CID_MSO14_64 = "{E6AC97ED-6651-4C00-A8FE-790DB0485859}" 
Const CID_MSO14_32 = "{398E906A-826B-48DD-9791-549C649CACE5}" 
Const CID_MSO12    = "{0638C49D-BB8B-4CD1-B191-050E8F325736}" 
Const CID_MSO11    = "{A2B280D4-20FB-4720-99F7-10C09FBCE10A}" 
'Global_Outlook_Core - outlook.exe 
Const CID_OL16_64 = "{7C6D92EF-7B45-46E5-8670-819663220E4E}" 
Const CID_OL16_32 = "{2C6C511D-4542-4E0C-95D0-05D4406032F2}" 
Const CID_OL15_64 = "{3A5F96E7-F51D-4942-98DB-3CD037FB39E5}" 
Const CID_OL15_32 = "{E9E5CFFC-AFFE-4F83-A695-7734FA4775B9}" 
Const CID_OL14_64 = "{ECCC8A38-7855-46CA-88FB-3BAA7CD95E56}" 
Const CID_OL14_32 = "{CFF13DD8-6EF2-49EB-B265-E3BFC6501C1D}" 
Const CID_OL12    = "{0638C49D-BB8B-4CD1-B191-055E8F325736}" 
Const CID_OL11    = "{3CE26368-6322-4ABF-B11B-458F5C450D0F}" 
'Global_PowerPoint_Core - powerpnt.exe 
Const CID_PPT16_64 = "{E0A76492-0FD5-4EC2-8570-AE1BAA61DC88}" 
Const CID_PPT16_32 = "{9E73CEA4-29D0-4D16-8FB9-5AB17387C960}" 
Const CID_PPT15_64 = "{8C1B8825-A280-4657-A7B8-8172C553A4C4}" 
Const CID_PPT15_32 = "{258D5292-6DDA-4B39-B301-58405FA16638}" 
Const CID_PPT14_64 = "{EE8D8E0A-D905-401D-9BC3-0D20156D5E30}" 
Const CID_PPT14_32 = "{E72E0D20-0D63-438B-BC71-92AB9F9E8B54}" 
Const CID_PPT12    = "{0638C49D-BB8B-4CD1-B191-053E8F325736}" 
Const CID_PPT11    = "{C86C0B92-63C0-4E35-8605-281275C21F97}" 
'Global_Project_ClientCore - winproj.exe 
Const CID_PRJ16_64 = "{107BCD9A-F1DC-4004-A444-33706FC10058}" 
Const CID_PRJ16_32 = "{0B6EDA1D-4A15-4F88-8B20-EA6528978E4E}" 
Const CID_PRJ15_64 = "{760CE47D-9512-40D9-8C6D-CF232851B4BB}" 
Const CID_PRJ15_32 = "{5296AE31-2F7D-480C-BFDC-CE0797426395}" 
Const CID_PRJ14_64 = "{64A809BD-6EE9-475C-B4E8-95B0D7FF3B97}" 
Const CID_PRJ14_32 = "{51894540-193D-40AE-83F9-D3FC5DB24D91}" 
Const CID_PRJ12    = "{43C3CF66-AA31-476D-B029-6D274E46F86C}" 
Const CID_PRJ11    = "{C33FFB81-6E54-4541-AFF4-D84DC60460F7}" 
'Global_Publisher_Core - mspub.exe 
Const CID_PUB16_64 = "{7ECBF2AA-14AA-4F89-B9A5-C064274CFA83}" 
Const CID_PUB16_32 = "{81DD86EC-5F1C-4DDE-9211-98AF184EAD47}" 
Const CID_PUB15_64 = "{22299AFF-DC4C-45A8-9A8F-651FB6467057}" 
Const CID_PUB15_32 = "{C9C0167D-3FE0-4078-B47E-83272A4B8B04}" 
Const CID_PUB14_64 = "{A716400F-5D5D-45CF-94B4-05B17A98B901}" 
Const CID_PUB14_32 = "{CD0D7B29-89E7-49C5-8EE1-5D858EFF2593}" 
Const CID_PUB12    = "{CD0D7B29-89E7-49C5-8EE1-5D858EFF2593}" 
Const CID_PUB11    = "{0638C49D-BB8B-4CD1-B191-05CE8F325736}" 
'Global_XDocs_Core - infopath.exe 
Const CID_IP16_64 = "{2774AAC0-1433-46BE-993F-8088018C3B09}" 
Const CID_IP15_64 = "{19AF7201-09A2-4C73-AB50-FCEF94CB2BA9}" 
Const CID_IP15_32 = "{3741355B-72CF-4CEE-948E-CC9FBDBB8E7A}" 
Const CID_IP14_64 = "{28B2FBA8-B95F-47CB-8F8F-0885ACDAC69B}" 
Const CID_IP14_32 = "{E3898C62-6EC3-4491-8194-9C88AD716468}" 
Const CID_IP12    = "{0638C49D-BB8B-4CD1-B191-058E8F325736}" 
Const CID_IP11    = "{1A66B512-C4BE-4347-9F0C-8638F8D1E6E4}" 
'Global_Visio_visioexe - visio.exe 
Const CID_VIS16_64 = "{2D4540EC-2C88-4C28-AE88-2614B5460648}" 
Const CID_VIS16_32 = "{A4C55BC1-B94C-4058-B15C-B9D4AE540AD1}" 
Const CID_VIS15_64 = "{7069FF90-1D63-4F85-A2AB-6F0D01C78D83}" 
Const CID_VIS15_32 = "{5D502092-1543-4D9B-89FE-7B4364417CC6}" 
Const CID_VIS14_64 = "{DB2B19E4-F894-47B1-A6F1-9B391A4AE0A8}" 
Const CID_VIS14_32 = "{4371C2B1-3F27-41F5-A849-9987AB91D990}" 
Const CID_VIS12    = "{0638C49D-BB8B-4CD1-B191-05DE8F325736}" 
Const CID_VIS11    = "{7E5F9F34-8EA7-4EA2-ABFB-CA4E742EFFA1}" 
'Global_Word_Core - winword.exe 
Const CID_WD16_64 = "{DC5CCACD-A7AC-4FD3-9F70-9454B5DE5161}" 
Const CID_WD16_32 = "{30CAC893-3CA4-494C-A5E9-A99141352216}" 
Const CID_WD15_64 = "{6FF09BDF-B087-4E23-A9B9-272DBFD64099}" 
Const CID_WD15_32 = "{09D07EFC-505F-4D9C-BFD5-ACE3217F6654}" 
Const CID_WD14_64 = "{C0AC079D-A84B-4CBD-8DBA-F1BB44146899}" 
Const CID_WD14_32 = "{019C826E-445A-4649-A5B0-0BF08FCC4EEE}" 
Const CID_WD12    = "{0638C49D-BB8B-4CD1-B191-051E8F325736}" 
Const CID_WD11    = "{1EBDE4BC-9A51-4630-B541-2561FA45CCC5}" 
 
'Arrays 
Const UBOUND_LOGARRAYS                = 12 
Const UBOUND_LOGCOLUMNS               = 34 ' Controlled by array with the most columns 
Redim arrLogFormat(UBOUND_LOGARRAYS, UBOUND_LOGCOLUMNS) 
 
Const ARRAY_MASTER                                          = 0 'Master data array id 
    Const UBOUND_MASTER                                     = 34 
    Const COL_PRODUCTCODE                                   = 0 
    Const COL_PRODUCTNAME                                   = 1 ' Msi ProductName 
    Const COL_USERSID                                       = 2 
    Const COL_CONTEXTSTRING                                 = 3 ' ProductContext 
    Const COL_STATESTRING                                   = 4 ' ProductState 
    Const COL_CONTEXT                                       = 5 ' ProductContext 
    Const COL_STATE                                         = 6 ' ProductState 
    Const COL_SYSTEMCOMPONENT                               = 7 ' Arp SystemComponent 
    Const COL_ARPPARENTCOUNT                                = 8 
    Const COL_ARPPARENTS                                    = 9 
    Const COL_ARPPRODUCTNAME                                = 10 
    Const COL_PRODUCTVERSION                                = 11 
    Const COL_SPLEVEL                                       = 12 ' ServicePack Level 
    Const COL_INSTALLDATE                                   = 13 
    Const COL_CACHEDMSI                                     = 14 
    Const COL_ORIGINALMSI                                   = 15 ' Original .msi name 
    Const COL_ORIGIN                                        = 16 ' Build/Origin Property 
    Const COL_PRODUCTID                                     = 17 ' ProductID Property 
    Const COL_PACKAGECODE                                   = 18 
    Const COL_TRANSFORMS                                    = 19 
    Const COL_ARCHITECTURE                                  = 20 
    Const COL_ERROR                                         = 21 
    Const COL_NOTES                                         = 22 
    Const COL_METADATASTATE                                 = 23 
    Const COL_ISOFFICEPRODUCT                               = 24 
    Const COL_PATCHFAMILY                                   = 25 
    Const COL_OSPPLICENSE                                   = 26 
    Const COL_OSPPLICENSEXML                                = 27 
    Const COL_ACIDLIST                                      = 28 
    Const COL_LICENSELIST                                   = 29 
    Const COL_UPGRADECODE                                   = 30 
    Const COL_VIRTUALIZED                                   = 31 
    Const COL_INSTALLTYPE                                   = 32 
    Const COL_KEYCOMPONENTS                                 = 33 
    Const COL_PRIMARYPRODUCTID                              = 34 
    arrLogFormat(ARRAY_MASTER, COL_PRODUCTCODE)             = "ProductCode" 
    arrLogFormat(ARRAY_MASTER, COL_PRODUCTNAME)             = "Msi ProductName" 
    arrLogFormat(ARRAY_MASTER, COL_USERSID)                 = "UserSid" 
    arrLogFormat(ARRAY_MASTER, COL_CONTEXTSTRING)           = "ProductContext" 
    arrLogFormat(ARRAY_MASTER, COL_STATESTRING)             = "ProductState" 
    arrLogFormat(ARRAY_MASTER, COL_CONTEXT)                 = "ProductContext" 
    arrLogFormat(ARRAY_MASTER, COL_STATE)                   = "ProductState" 
    arrLogFormat(ARRAY_MASTER, COL_SYSTEMCOMPONENT)         = "Arp SystemComponent" 
    arrLogFormat(ARRAY_MASTER, COL_ARPPARENTCOUNT)          = "Arp ParentCount" 
    arrLogFormat(ARRAY_MASTER, COL_ARPPARENTS)              = "Configuration SKU" 
    arrLogFormat(ARRAY_MASTER, COL_ARPPRODUCTNAME)          = "ARP ProductName" 
    arrLogFormat(ARRAY_MASTER, COL_PRODUCTVERSION)          = "ProductVersion" 
    arrLogFormat(ARRAY_MASTER, COL_SPLEVEL)                 = "ServicePack Level" 
    arrLogFormat(ARRAY_MASTER, COL_INSTALLDATE)             = "InstallDate" 
    arrLogFormat(ARRAY_MASTER, COL_CACHEDMSI)               = "Cached .msi Package" 
    arrLogFormat(ARRAY_MASTER, COL_ORIGINALMSI)             = "Original .msi Name" 
    arrLogFormat(ARRAY_MASTER, COL_ORIGIN)                  = "Build/Origin" 
    arrLogFormat(ARRAY_MASTER, COL_PRODUCTID)               = "ProductID (MSI)" 
    arrLogFormat(ARRAY_MASTER, COL_PACKAGECODE)             = "Package Code" 
    arrLogFormat(ARRAY_MASTER, COL_TRANSFORMS)              = "Transforms" 
    arrLogFormat(ARRAY_MASTER, COL_ARCHITECTURE)            = "Architecture" 
    arrLogFormat(ARRAY_MASTER, COL_ERROR)                   = "Errors" 
    arrLogFormat(ARRAY_MASTER, COL_NOTES)                   = "Notes" 
    arrLogFormat(ARRAY_MASTER, COL_METADATASTATE)           = "MetadataState" 
    arrLogFormat(ARRAY_MASTER, COL_ISOFFICEPRODUCT)         = "IsOfficeProduct" 
    arrLogFormat(ARRAY_MASTER, COL_PATCHFAMILY)             = "PatchFamily" 
    arrLogFormat(ARRAY_MASTER, COL_OSPPLICENSE)             = "OSPP License" 
    arrLogFormat(ARRAY_MASTER, COL_OSPPLICENSEXML)          = "OSPP License XML" 
    arrLogFormat(ARRAY_MASTER, COL_ACIDLIST)                = "ACIDList" 
    arrLogFormat(ARRAY_MASTER, COL_LICENSELIST)             = "Possible Licenses" 
    arrLogFormat(ARRAY_MASTER, COL_UPGRADECODE)             = "UpgradeCode" 
    arrLogFormat(ARRAY_MASTER, COL_VIRTUALIZED)             = "Virtualized" 
    arrLogFormat(ARRAY_MASTER, COL_INSTALLTYPE)             = "InstallType" 
    arrLogFormat(ARRAY_MASTER, COL_KEYCOMPONENTS)           = "KeyComponents" 
    arrLogFormat(ARRAY_MASTER, COL_PRIMARYPRODUCTID)        = "Primary Product Id" 
 
Const ARRAY_PATCH                                           = 1 'Patch data array id 
    Const PATCH_COLUMNCOUNT                                 = 14 
    Const PATCH_LOGSTART                                    = 1 
    Const PATCH_LOGCHAINEDMAX                               = 8 
    Const PATCH_LOGMAX                                      = 11 
    Const PATCH_PRODUCT                                     = 0 
    Const PATCH_KB                                          = 1 
    Const PATCH_PACKAGE                                     = 3 ' PackageName 
    Const PATCH_PATCHSTATE                                  = 2 
    Const PATCH_SEQUENCE                                    = 4 
    Const PATCH_UNINSTALLABLE                               = 5 
    Const PATCH_INSTALLDATE                                 = 6 
    Const PATCH_PATCHCODE                                   = 7 
    Const PATCH_LOCALPACKAGE                                = 8 
    Const PATCH_TRANSFORM                                   = 9 
    Const PATCH_DISPLAYNAME                                 = 10 
    Const PATCH_MOREINFOURL                                 = 11 
    Const PATCH_CSP                                         = 12 ' Client side patch or patched AIP 
    Const PATCH_CPOK                                        = 13 ' Local .msp package OK/available 
    arrLogFormat(ARRAY_PATCH, PATCH_PRODUCT)                = "Patched Product: " 
    arrLogFormat(ARRAY_PATCH, PATCH_KB)                     = "KB: " 
    arrLogFormat(ARRAY_PATCH, PATCH_PACKAGE)                = "Package: " 
    arrLogFormat(ARRAY_PATCH, PATCH_PATCHSTATE)             = "State: " 
    arrLogFormat(ARRAY_PATCH, PATCH_SEQUENCE)               = "Sequence: " 
    arrLogFormat(ARRAY_PATCH, PATCH_UNINSTALLABLE)          = "Uninstallable: " 
    arrLogFormat(ARRAY_PATCH, PATCH_INSTALLDATE)            = "InstallDate: " 
    arrLogFormat(ARRAY_PATCH, PATCH_PATCHCODE)              = "PatchCode: " 
    arrLogFormat(ARRAY_PATCH, PATCH_LOCALPACKAGE)           = "LocalPackage: " 
    arrLogFormat(ARRAY_PATCH, PATCH_TRANSFORM)              = "PatchTransform: " 
    arrLogFormat(ARRAY_PATCH, PATCH_DISPLAYNAME)            = "DisplayName: " 
    arrLogFormat(ARRAY_PATCH, PATCH_MOREINFOURL)            = "MoreInfoUrl: " 
    arrLogFormat(ARRAY_PATCH, PATCH_CSP)                    = "ClientSidePatch: " 
    arrLogFormat(ARRAY_PATCH, PATCH_CPOK)                   = "CachedMspOK: " 
 
' arrMsp(MSPDEFAULT, MSP_COLUMNCOUNT) 
Const ARRAY_MSPFILES                                        = 10 
    Const MSPFILES_COLUMNCOUNT                              = 18 
    Const MSPFILES_LOGMAX                                   = 9 
    Const MSPFILES_TARGETS                                  = 0 ' Product Targets 
    Const MSPFILES_KB                                       = 1 
    Const MSPFILES_PACKAGE                                  = 2 ' PackageName 
    Const MSPFILES_FAMILY                                   = 3 
    Const MSPFILES_SEQUENCE                                 = 4 
    Const MSPFILES_PATCHSTATE                               = 5 
    Const MSPFILES_UNINSTALLABLE                            = 6 
    Const MSPFILES_INSTALLDATE                              = 7 
    Const MSPFILES_DISPLAYNAME                              = 8 
    Const MSPFILES_MOREINFOURL                              = 9  
    Const MSPFILES_PATCHCODE                                = 10  
    Const MSPFILES_LOCALPACKAGE                             = 11  
    Const MSPFILES_BUCKET                                   = 12  
    Const MSPFILES_ATTRIBUTE                                = 13 ' Attribute msidbPatchSequenceSupersedeEarlier 
    Const MSPFILES_TRANSFORM                                = 14 ' PatchTransform 
    Const MSPFILES_XML                                      = 15 ' PatchXml 
    Const MSPFILES_TABLES                                   = 16 ' PatchTables 
    Const MSPFILES_CPOK                                     = 17 ' Local .msp package OK/available 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_TARGETS)          = "Patch Targets: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_KB)               = "KB: " 
    arrLogFormat(ARRAY_MSPFILES , MSPFILES_PACKAGE)          = "Package: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_FAMILY)           = "Family: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_SEQUENCE)         = "Sequence: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_PATCHSTATE)       = "PatchState: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_UNINSTALLABLE)    = "Uninstallable: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_INSTALLDATE)      = "InstallDate: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_DISPLAYNAME)      = "DisplayName: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_MOREINFOURL)      = "MoreInfoUrl: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_PATCHCODE)        = "PatchCode: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_LOCALPACKAGE)     = "LocalPackage: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_BUCKET)           = "Bucket: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_ATTRIBUTE)        = "msidbPatchSequenceSupersedeEarlier: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_TRANSFORM)        = "PatchTransform: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_XML)              = "PatchXml: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_TABLES)           = "PatchTables: " 
    arrLogFormat(ARRAY_MSPFILES, MSPFILES_CPOK)             = "CachedMspOK: " 
 
Const ARRAY_AIPPATCH                                        = 11 
    Const AIPPATCH_COLUMNCOUNT                              = 3 
    Const AIPPATCH_PRODUCT                                  = 0 
    Const AIPPATCH_PATCHCODE                                = 1 
    Const AIPPATCH_DISPLAYNAME                              = 3 
    arrLogFormat(ARRAY_AIPPATCH, AIPPATCH_PRODUCT)          = "Patched Product: " 
    arrLogFormat(ARRAY_AIPPATCH, AIPPATCH_PATCHCODE)        = "PatchCode: " 
    arrLogFormat(ARRAY_AIPPATCH, AIPPATCH_DISPLAYNAME)      = "DisplayName: " 
 
Const ARRAY_FEATURE                                         = 2 'Feature data array id 
    Const FEATURE_COLUMNCOUNT                               = 1 
    Const FEATURE_PRODUCTCODE                               = 0 
    Const FEATURE_TREE                                      = 1 
 
Const ARRAY_ARP                                             = 4 'Add/remove products data array id 
    Const ARP_CHILDOFFSET                                   = 6 
    Const ARP_CONFIGPRODUCTCODE                             = 0 
    Const COL_CONFIGNAME                                    = 1 
    Const ARP_PRODUCTVERSION                                = 2 
    Const COL_CONFIGINSTALLTYPE                             = 3 
    Const COL_CONFIGPACKAGEID                               = 4 
    Const COL_ARPALLPRODUCTS                                = 5 
    Const COL_LBOUNDCHAINLIST                               = 6 
    arrLogFormat(ARRAY_ARP, ARP_CONFIGPRODUCTCODE)          = "Config ProductCode" 
    arrLogFormat(ARRAY_ARP, COL_CONFIGNAME)                 = "Config ProductName" 
    arrLogFormat(ARRAY_ARP, ARP_PRODUCTVERSION)             = "ProductVersion" 
    arrLogFormat(ARRAY_ARP, COL_CONFIGINSTALLTYPE)          = "Config InstallType" 
    arrLogFormat(ARRAY_ARP, COL_CONFIGPACKAGEID)            = "Config PackageID" 
 
Const ARRAY_IS                                              = 5 ' MSI InstallSource data array id 
    Const UBOUND_IS                                         = 6 
    Const IS_LOG_LBOUND                                     = 2 
    Const IS_LOG_UBOUND                                     = 6 
    Const IS_PRODUCTCODE                                    = 0 
    Const IS_SOURCETYPE                                     = 1 
    Const IS_SOURCETYPESTRING                               = 2 
    Const IS_ORIGINALSOURCE                                 = 3 
    Const IS_LASTUSEDSOURCE                                 = 4 
    Const IS_LISRESILIENCY                                  = 5 
    Const IS_ADDITIONALSOURCES                              = 6 
    arrLogFormat(ARRAY_IS, IS_SOURCETYPESTRING)             = "InstallSource Type" 
    arrLogFormat(ARRAY_IS, IS_ORIGINALSOURCE)               = "Initially Used Source" 
    arrLogFormat(ARRAY_IS, IS_LASTUSEDSOURCE)               = "Last Used Source" 
    arrLogFormat(ARRAY_IS, IS_LISRESILIENCY)                = "LIS Resiliency Sources" 
    arrLogFormat(ARRAY_IS, IS_ADDITIONALSOURCES)            = "Network Sources" 
 
Const ARRAY_VIRTPROD                                        = 6 ' Non MSI based virtualized products 
    Const UBOUND_VIRTPROD                                   = 14 
    Const VIRTPROD_KEYNAME                                  = 2 
    Const VIRTPROD_CONFIGNAME                               = 3 
    Const VIRTPROD_PRODUCTVERSION                           = 4 
    Const VIRTPROD_SPLEVEL                                  = 5 
    Const VIRTPROD_ISPROOFINGTOOLS                          = 6 
    Const VIRTPROD_ISLANGUAGEPACK                           = 7 
    Const VIRTPROD_OSPPLICENSE                              = 8 
    Const VIRTPROD_OSPPLICENSEXML                           = 9 
    Const VIRTPROD_ACIDLIST                                 = 10 
    Const VIRTPROD_LICENSELIST                              = 11 
    Const VIRTPROD_CHILDPACKAGES                            = 12 
    Const VIRTPROD_KEYCOMPONENTS                            = 13 
    Const VIRTPROD_EXCLUDEAPP                               = 14 
    arrLogFormat(ARRAY_VIRTPROD, COL_PRODUCTCODE)           = "ProductCode" 
    arrLogFormat(ARRAY_VIRTPROD, COL_PRODUCTNAME)           = "ProductName" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_KEYNAME)          = "KeyName" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_CONFIGNAME)       = "Config ProductName" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_SPLEVEL)          = "Version" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_PRODUCTVERSION)   = "BuildNumber" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_OSPPLICENSE)      = "(O)SPP License" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_OSPPLICENSEXML)   = "(O)SPP License XML" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_ACIDLIST)         = "ACIDList" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_LICENSELIST)      = "Possible Licenses" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_CHILDPACKAGES)    = "Child Packages" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_KEYCOMPONENTS)    = "KeyComponents" 
    arrLogFormat(ARRAY_VIRTPROD, VIRTPROD_EXCLUDEAPP)       = "Excluded Applications" 
 
'License Data Array 
Const ARRAY_LICENSE                   = 7  
    Const UBOUND_LICENSE              = 10 
    Const LICENSE_ACID          = 0 
    arrLogFormat(ARRAY_LICENSE, LICENSE_ACID) = "ACID" 
 
 
Const CSV                             = ", " 
Const DSV                             = " - " 
Const DOT                             = ". " 
Const ERR_CATEGORYNOTE                = "Note: " 
Const ERR_CATEGORYWARN                = "Warning: " 
Const ERR_CATEGORYERROR               = "Error: " 
Const ERR_NONADMIN                    = "The script appears to run outside administrator context" 
Const ERR_NONELEVATED                 = "The script does not appear to run elevated" 
Const ERR_DATAINTEGRITY               = "A script internal error occurred. The integrity of the logged data might be affected" 
Const ERR_OBJPRODUCTINFO              = "Installer.ProductInfo -> " 
Const ERR_INITSUMINFO                 = "Could not connect to summary information stream" 
Const ERR_NOARRAY                     = "Array check failed" 
Const ERR_UNKNOWNHANDLER              = "Unknown Error Handler: '" 
Const ERR_PRODUCTSEXALL               = "ProductsEx for MSIINSTALLCONTEXT_ALL failed" 
Const ERR_PATCHESEX                   = "PatchesEx failed to get a list of patches for: " 
Const ERR_PATCHES                     = "Installer.Patches failed to get a list of patches" 
Const ERR_MISSINGCHILD                = "A chained product is missing which breaks the ability to maintain or uninstall this product. " 
Const ERR_ORPHANEDITEM                = "Office application without entry point in Add/Remove Programs" 
Const ERR_INVALIDPRODUCTCODE          = "Critical Windows Installer metadata corruption detected 'Invalid ProductCode'" 
Const ERR_INVALIDGUID                 = "GUID validation failed" 
Const ERR_INVALIDGUIDCHAR             = "Guid contains invalid character(s)" 
Const ERR_INVALIDGUIDLENGTH           = "Invalid length for GUID  " 
Const ERR_GUIDCASE                    = "Guid contains lower case character(s)" 
Const ERR_BADARPMETADATA              = "Crititcal ARP metadata corruption detected in key: " 
Const ERR_OFFSCRUB_TERMINATED         = "Bad ARP metadata. This can be caused by an OffScrub run that was terminated before it could complete:" 
Const ERR_ARPENTRYMISSING             = "Expected regkey not present for ARP config parent" 
Const ERR_REGKEYMISSING               = "Regkey does not exist: " 
Const ERR_CUSTOMSTACKCORRUPTION       = "Custom stack list string corrupted" 
Const ERR_BADMSPMETADATA              = "Metadata mismatch for patch registration" 
Const ERR_BADMSINAMEMETADATA          = "Failed to retrieve value for original .msi name" 
Const ERR_BADPACKAGEMETADATA          = "Failed to retrieve value for cached .msi package" 
Const ERR_PACKAGEAPIFAILURE           = "API failed to retrieve value for cached .msi package" 
Const ERR_BADPACKAGECODEMETADATA      = "Failed to retrieve value for Package Code" 
Const ERR_PACKAGECODEMISMATCH         = "PackageCode mismatch between registered value and cached .msi" 
Const ERR_LOCALPACKAGEMISSING         = "Local cached .msi appears to be missing" 
Const ERR_BADTRANSFORMSMETADATA       = "Failed to retrieve value for Transforms" 
Const ERR_SICONNECTFAILED             = "Failed to connect to SummaryInformation stream" 
Const ERR_MSPOPENFAILED               = "OpenDatabase failed to open .msp file " 
Const ERR_MSIOPENFAILED               = "OpenDatabase failed to open .msi file " 
Const ERR_BADFILESTATE                = " has unexpected file state(s). " 
Const ERR_FILEVERSIONLOW              = "Review file versions for product " 
Const BPA_GUID                        = "For details on 'GUID' see https://msdn.microsoft.com/en-us/library/Aa368767.aspx" 
Const BPA_PACKAGECODE                 = "For details on 'Package Codes' see https://msdn.microsoft.com/en-us/library/aa370568.aspx" 
Const BPA_PRODUCTCODE                 = "For details on 'Product Codes' see https://msdn.microsoft.com/en-us/library/aa370860.aspx" 
Const BPA_PACKAGECODEMISMATCH         = "A mismatch of the PackageCode will force the Windows Installer to recache the local .msi from the InstallSource. For details on 'Package Code' see https://msdn.microsoft.com/en-us/library/aa370568.aspx" 
'======================================================================================================= 
 
Main 
 
'======================================================================================================= 
'Module Main 
'======================================================================================================= 
Sub Main 
    Dim fCheckPreReq, FsoLogFile, FsoXmlLogFile 
    On Error Resume Next 
' Check type of scripting host 
    fCScript = (UCase(Mid(Wscript.FullName, Len(Wscript.Path) + 21)) = "C"' Ensure all required objects are available. Prerequisite Checks with inline error handling.  
    fCheckPreReq = CheckPreReq() 
    If fCheckPreReq = False Then Exit Sub 
' Initializations  
    Initialize  
' Get computer specific properties 
    If fCScript AND NOT fQuiet Then wscript.echo "Stage 1 of 11: ComputerProperties" 
    ComputerProperties  
' Build an array with a list of all Windows Installer based products 
' After this point the master array "arrMaster" is instantiated and has the basic product details 
    If fCScript AND NOT fQuiet Then wscript.echo "Stage 2 of 11: Product detection" 
    FindAllProducts  
' Get additional product properties and add them to the master array 
    If fCScript AND NOT fQuiet Then wscript.echo "Stage 3 of 11: ProductProperties" 
    ProductProperties  
' Build an array with data on the InstallSource(s) 
    If fCScript AND NOT fQuiet Then wscript.echo "Stage 4 of 11: InstallSources" 
    ReadMsiInstallSources 
' Build an array with data from Add/Remove Products 
' Only Office >= 2007 products that use a multiple .msi structure will be covered here 
    If fCScript AND NOT fQuiet Then wscript.echo "Stage 5 of 11: Add/Remove Programs analysis" 
    ARPData  
' Add Licensing data 
' Only Office >= 2010 products that use OSPP are covered here 
    If fCScript AND NOT fQuiet Then wscript.echo "Stage 6 of 11: Licensing (OSPP)" 
    OsppCollect  
' Build an array with all patch data. 
    If fCScript AND NOT fQuiet Then wscript.echo "Stage 7 of 11: Patch detection" 
    FindAllPatches 
    If fFeatureTree Then 
    ' Build a tree structure for the Features  
        If fCScript AND NOT fQuiet Then wscript.echo "Stage 8 of 11: FeatureStates" 
        FindFeatureStates 
    Else 
        If fCScript AND NOT fQuiet Then wscript.echo "Skipping stage 8 of 11: (FeatureStates)" 
    End If 'fFeatureTree 
' Create file inventory XML files 
    If fFileInventory Then 
        If fCScript AND NOT fQuiet Then wscript.echo "Stage 9 of 11: FileInventory" 
        FileInventory 
    Else 
        If fCScript AND NOT fQuiet Then wscript.echo "Skipping stage 9 of 11: (FileInventory)" 
    End If 'fFileInventory 
' Prepare the collected data for the output file 
    If fCScript AND NOT fQuiet Then wscript.echo "Stage 10 of 11: Prepare collected data for output" 
    PrepareLog sLogFormat  
' Write the output file 
    If fCScript AND NOT fQuiet Then wscript.echo "Stage 11 of 11: Write log" 
    WriteLog  
    Set FsoLogFile = oFso.GetFile(sLogFile) 
    Set FsoXmlLogFile = oFso.GetFile(sPathOutputFolder & sComputerName & "_ROIScan.xml") 
    If fFileInventory Then  
        If (oFso.FileExists(sPathOutputFolder & sComputerName & "_ROIScan.zip") AND NOT fZipError) Then 
            CopyToZip ShellApp.NameSpace(sPathOutputFolder & sComputerName & "_ROIScan.zip"), FsoLogFile 
            CopyToZip ShellApp.NameSpace(sPathOutputFolder & sComputerName & "_ROIScan.zip"), FsoXmlLogFile 
        End If 
    End If 
    If fCScript AND NOT fQuiet Then wscript.echo "Done!" 
' Open the output file 
    If Not fQuiet Then 
        Set oShell = CreateObject("WScript.Shell") 
        If fFileInventory Then  
            If oFso.FileExists(sPathOutputFolder & sComputerName & "_ROIScan.zip") AND NOT fZipError Then 
                oShell.Run "explorer /e," & chr(34) & sPathOutputFolder & sComputerName & "_ROIScan.zip" & chr(34)  
            Else  
                oShell.Run "explorer /e," & chr(34) & sPathOutputFolder & "ROIScan" & chr(34) 
            End If 
        End If 'fFileInventory 
        oShell.Run chr(34) & sLogFile & chr(34) 
        Set oShell = Nothing 
    End If 'fQuiet 
' Clear up Objects 
    CleanUp 
End Sub 
'======================================================================================================= 
 
'Initialize defaults, setting and collect current user information 
Sub Initialize 
    Dim oApp, Process, Processes 
    Dim sEnvVar, Argument 
    Dim iPopup, iInstanceCnt 
    Dim fPrompt 
    On Error Resume Next 
    'Ensure there's only a single instance running of this script 
    iInstanceCnt = 0 
    wscript.sleep 500 
    Set Processes = oWmiLocal.ExecQuery("Select * From Win32_Process") 
    For Each Process in Processes 
        If LCase(Mid(Process.Name, 26)) = "script" Then  
            If InStr(LCase(Process.CommandLine), "roiscan") > 0 AND NOT InStr(Process.CommandLine, " UAC") > 0 Then iInstanceCnt = iInstanceCnt + 1 
        End If 
    Next 'Process 
    If iInstanceCnt > 1 Then 
        If NOT fQuiet Then wscript.echo ERR_CATEGORYERROR & "Another instance of this script is already running." 
        wscript.quit 
    End If 
    
    'Other defaults 
    Set dicPatchLevel = CreateObject("Scripting.Dictionary") 
    Set dicScenario = CreateObject("Scripting.Dictionary") 
    Set dicC2RPropV2 = CreateObject("Scripting.Dictionary") 
    Set dicScenarioV2 = CreateObject("Scripting.Dictionary") 
    Set dicKeyComponentsV2 = CreateObject("Scripting.Dictionary") 
    Set dicVirt2Cultures = CreateObject("Scripting.Dictionary") 
    Set dicC2RPropV3 = CreateObject("Scripting.Dictionary") 
    Set dicScenarioV3 = CreateObject("Scripting.Dictionary") 
    Set dicKeyComponentsV3 = CreateObject("Scripting.Dictionary") 
    Set dicVirt3Cultures = CreateObject("Scripting.Dictionary") 
    Set dicProductCodeC2R = CreateObject("Scripting.Dictionary") 
    Set dicMapArpToConfigID = CreateObject("Scripting.Dictionary") 
    Set dicArp = CreateObject("Scripting.Dictionary") 
    Set dicPolHKCU = CreateObject("Scripting.Dictionary") 
    Set dicPolHKLM = CreateObject("Scripting.Dictionary") 
    fZipError = False 
    fInitArrProdVer = False 
 
    ' log output folder 
    If sPathOutputFolder = "" Then sPathOutputFolder = "%TEMP%" 
    sPathOutputFolder = oShell.ExpandEnvironmentStrings(sPathOutputFolder) 
    sPathOutputFolder = Replace(sPathOutputFolder, "'","") 
    If sPathOutputFolder = "." OR Left(sPathOutputFolder, 2) = ".\" Then sPathOutputFolder = GetFullPathFromRelative(sPathOutputFolder) 
    sPathOutputFolder = oFso.GetAbsolutePathName(sPathOutputFolder) 
    If Trim(UCase(sPathOutputFolder)) = "DESKTOP" Then 
        Set oApp = CreateObject ("Shell.Application") 
        Const DESKTOP = &H10& 
        sPathOutputFolder = oApp.Namespace(DESKTOP).Self.Path 
        Set oApp = Nothing 
    End If 
    If Not oFso.FolderExists(sPathOutputFolder) Then  
        ' custom log folder location does not exist. 
        ' try to create the folder before falling back to default 
        oFso.CreateFolder sPathOutputFolder 
        If NOT Err = 0 Then 
            sPathOutputFolder = oShell.ExpandEnvironmentStrings("%TEMP%") & "\"  
            Err.Clear 
        End If 
    End If 
    While Right(sPathOutputFolder, 1) = "\"  
        sPathOutputFolder = Left(sPathOutputFolder, Len(sPathOutputFolder) - 1) 
    Wend 
    If Not Right(sPathOutputFolder, 1) = "\" Then sPathOutputFolder = sPathOutputFolder & "\" 
    sLogFile = sPathOutputFolder & sComputerName & "_ROIScan.log" 
 
    CacheLog LOGPOS_COMPUTER, LOGHEADING_H1, Null, "Computer"  
    CacheLog LOGPOS_REVITEM, LOGHEADING_H1, Null, "Review Items"  
    CacheLog LOGPOS_RAW, LOGHEADING_H1, Null, "Raw Data"  
    iPopup = -1 
    fPrompt = True 
    If Wscript.Arguments.Count > 0 Then 
        For Each Argument in Wscript.Arguments 
            If Argument = "UAC" Then fPrompt = False 
        Next 'Argument 
    End If 
'Add warning to log if non-admin was detected 
    If Not fIsAdmin Then  
        Cachelog LOGPOS_REVITEM, LOGHEADING_NONE, ERR_CATEGORYERROR, ERR_NONADMIN 
        If NOT fQuiet AND fPrompt Then RelaunchElevated 
    End If 
    If fIsAdmin AND (NOT fIsElevated) Then  
        Cachelog LOGPOS_REVITEM, LOGHEADING_NONE, ERR_CATEGORYERROR, ERR_NONELEVATED 
        If NOT fQuiet AND fPrompt Then RelaunchElevated 
   End If 
'Ensure CScript as engine 
    If (NOT UCase(Mid(Wscript.FullName, Len(Wscript.Path) + 21)) = "C") AND (NOT fDisallowCScript) Then RelaunchAsCScript 
'Check on 64 bit OS -> see CheckPreReq 
'Init sCurUserSid 
    GetUserSids("Current")  
'Init "arrUUSids" 
    Redim arrUUSids(-1) 
    GetUserSids ("UserUnmanaged")  
'Init "arrUMSids" 
    Redim arrUMSids(-1) 
    GetUserSids("UserManaged")  
'Init KeyComponents dictionary 
    Set dicKeyComponents = CreateObject("Scripting.Dictionary") 
    InitKeyComponents 
    iVMVirtOverride = 0 
'Set defaults for ProductList arrays 
    InitPLArrays  
    Set dicMspIndex = CreateObject("Scripting.Dictionary") 
    bOsppInit = False 
End Sub 'Initialize 
'======================================================================================================= 
'End Of Main Module 
 
'======================================================================================================= 
'Module FileInventory 
'======================================================================================================= 
 
'File inventory for installed applications 
Sub FileInventory 
    Dim sProductCode, sQueryFT, sQueryMst, sQueryCompID, sQueryFC, sMst, sFtk, sCmp 
    Dim sPath, sName, sXmlLine, sAscCheck, sQueryDir, sQueryAssembly, sPatchCode 
    Dim sCurVer, sSqlCreateTable, sTables, sTargetPath 
    Dim iPosMaster, iPosPatch, iFoo, iFile, iMst, iCnt, iAsc, iAscCnt, iCmp 
    Dim iPosArr, iArrMaxCnt, iColCnt, iBaseRefCnt, iIndex 
    Dim bAsc, bMstApplied, bBaseRefFound, bFtkViewComplete, bFtkInScope, bFtkForceOutOfScope, bNeedKeyPathFallback 
    Dim bCreate, bDelete, bDrop, bInsert, bFileNameChanged 
    Dim MsiDb, SessionDb, MspDb, qViewFT, qViewMst, qViewCompID, qViewFC, qViewDir, qViewAssembly, Record, Record2, Record3 
    Dim qViewMspCompId, qViewMspFC, qViewMsiAssembly, AllOfficeFiles, FileStream 
    Dim SessionDir, Table, ViewTables, tbl 
    Dim dicTransforms, dicKeys 
    Dim arrTables 
     
    If fBasicMode Then Exit Sub 
    On Error Resume Next 
    Const FILES_FTK             = 0 'key field for each file 
    Const FILES_SOURCE          = 1 
    Const FILES_ISPATCHED       = 2 
    Const FILES_FILESTATUS      = 3  
    Const FILES_FILE            = 4 
    Const FILES_FOLDER          = 5 
    Const FILES_FULLNAME        = 6 
    Const FILES_LANGUAGE        = 7 
    Const FILES_BASEVERSION     = 8 
    Const FILES_PATCHVERSION    = 9 
    Const FILES_CURRENTVERSION  = 10 
    Const FILES_VERSIONSTATUS   = 11 
    Const FILES_PATCHCODE       = 12 'key field for patch 
    Const FILES_PATCHSTATE      = 13 
    Const FILES_PATCHKB         = 14 
    Const FILES_PATCHPACKAGE    = 15 
    Const FILES_PATCHMOREINFO   = 16 
    Const FILES_DIRECTORY       = 17 
    Const FILES_COMPONENTID     = 18 
    Const FILES_COMPONENTNAME   = 19 
    Const FILES_COMPONENTSTATE  = 20 
    Const FILES_KEYPATH         = 21 
    Const FILES_COMPONENTCLIENTS= 22 
    Const FILES_FEATURENAMES    = 23 
    Const FILES_COLUMNCNT       = 23 
     
    Const SQL_FILETABLE = "SELECT * FROM `_TransformView` WHERE `Table` = 'File' ORDER BY `Row`" 
    Const SQL_PATCHTRANSFORMS = "SELECT `Name` FROM `_Storages` ORDER BY `Name`" 
    Const INSTALLSTATE_ASSEMBLY = 6 
    Const WAITTIME = 500  
 
' Loop all products 
    If fCScript AND NOT fQuiet Then wscript.echo vbTab & "File version scan" 
    For iPosMaster = 0 To UBound(arrMaster) 
        If (arrMaster(iPosMaster, COL_ISOFFICEPRODUCT)) AND (arrMaster(iPosMaster, COL_CONTEXT) = MSIINSTALLCONTEXT_MACHINE) Then 
        ' Cache ProductCode 
            sProductCode = "" : sProductCode = arrMaster(iPosMaster, COL_PRODUCTCODE) 
            If fCScript AND NOT fQuiet Then wscript.echo vbTab & sProductCode  
        ' Reset Files array 
            iPosArr = -1 
            iArrMaxCnt = 5000 
            ReDim arrFiles(FILES_COLUMNCNT, iArrMaxCnt) 
            iBaseRefCnt = 0 
            For iFoo = 1 To 1 
            ' Add fields from msi base 
            ' ------------------------ 
            ' Connect to the local .msi file for reading 
                Err.Clear 
                Set MsiDb = oMsi.OpenDatabase(arrMaster(iPosMaster, COL_CACHEDMSI), MSIOPENDATABASEMODE_READONLY) 
                If Not Err = 0 Then  
                    Exit For 
                End If 'Err = 0 
            ' Check which tables exist in the current .msi 
                sTables = "" 
                Set ViewTables = MsiDb.OpenView("SELECT `Name` FROM `_Tables` ORDER BY `Name`") 
                ViewTables.Execute 
                Do 
                    Set Table = ViewTables.Fetch 
                    If Table Is Nothing then Exit Do 
                    sTables = sTables & Table.StringData(1) & "," 
                    If Not Err = 0 Then Exit Do 
                Loop 
                ViewTables.Close 
                arrTables = Split(RTrimComma(sTables), ",") 
            ' Build an assembly reference dictionary 
                Set dicAssembly = Nothing 
                Set dicAssembly = CreateObject("Scripting.Dictionary") 
                If InStr(sTables, "MsiAssembly,") > 0 Then 
                    sQueryAssembly = "SELECT DISTINCT `Component_` FROM MsiAssembly" 
                    Set qViewAssembly = MsiDb.OpenView(sQueryAssembly) 
                    qViewAssembly.Execute 
                ' If the MsiAssmbly table does not exist it returns an error  
                    If Not Err = 0 Then Err.Clear 
                    Set Record = qViewAssembly.Fetch 
                ' must not enter the loop in case of an error! 
                    If Not Err = 0 Then 
                        Err.Clear 
                    Else  
                        Do Until Record Is Nothing 
                            If Not dicAssembly.Exists(Record.StringData(1)) Then 
                                dicAssembly.Add Record.StringData(1), Record.StringData(1) 
                            End If 
                            Set Record = qViewAssembly.Fetch 
                        Loop 
                    End If 'Not Err = 0 
                    qViewAssembly.Close 
                End If 'InStr(sTables, "MsiAssembly") > 0 
                 
                If InStr(sTables, "SxsMsmGenComponents,") > 0 Then 
                    sQueryAssembly = "SELECT DISTINCT `Component_` FROM SxsMsmGenComponents" 
                    Set qViewAssembly = MsiDb.OpenView(sQueryAssembly) 
                    qViewAssembly.Execute 
                ' If the MsiAssmbly table does not exist it returns an error  
                    If Not Err = 0 Then Err.Clear 
                    Set Record = qViewAssembly.Fetch 
                ' must not enter the loop in case of an error! 
                    If Not Err = 0 Then 
                        Err.Clear 
                    Else  
                        Do Until Record Is Nothing 
                            If Not dicAssembly.Exists(Record.StringData(1)) Then 
                                dicAssembly.Add Record.StringData(1), Record.StringData(1) 
                            End If 
                            Set Record = qViewAssembly.Fetch 
                        Loop 
                    End If 'Not Err = 0 
                    qViewAssembly.Close 
                End If 'InStr(sTables, "MsiAssembly") > 0 
                 
            ' Build directory reference 
                Set SessionDir = Nothing 
                oMsi.UILevel = 2 'None 
                Set SessionDir = oMsi.OpenProduct(sProductCode) 
                SessionDir.DoAction("CostInitialize") 
                SessionDir.DoAction("FileCost") 
                SessionDir.DoAction("CostFinalize") 
                Set dicFolders = Nothing 
                Set dicFolders = CreateObject("Scripting.Dictionary") 
                Err.Clear 
                Set SessionDb = SessionDir.Database 
                sQueryDir = "SELECT DISTINCT `Directory` FROM Directory" 
                Set qViewDir = SessionDb.OpenView(sQueryDir) 
                qViewDir.Execute 
                Set Record = qViewDir.Fetch 
            ' must not enter the loop in case of an error! 
                If Not Err = 0 Then 
                    Err.Clear 
                Else  
                    Do Until Record Is Nothing 
                        If Not dicFolders.Exists(Record.Stringdata(1)) Then 
                            sTargetPath = "" : sTargetPath = SessionDir.TargetPath(Record.Stringdata(1)) 
                            If NOT sTargetPath = "" Then dicFolders.Add Record.Stringdata(1), sTargetPath 
                        End If 
                        Set Record = qViewDir.Fetch 
                    Loop 
                End If 'Not Err = 0 
                qViewDir.Close 
             
            ' .msi file inventory 
            ' ------------------- 
                sQueryFT = "SELECT * FROM File" 
                Set qViewFT = MsiDb.OpenView(sQueryFT) 
                qViewFT.Execute 
                Set Record = qViewFT.Fetch() 
                Do Until Record Is Nothing 
                ' Next Row in Array 
                ' ----------------- 
                    iPosArr = iPosArr + 1 
                    iBaseRefCnt = iPosArr 
                    If iPosArr > iArrMaxCnt Then 
                    ' increase array row buffer 
                        iArrMaxCnt = iArrMaxCnt + 1000 
                        ReDim Preserve arrFiles(FILES_COLUMNCNT, iArrMaxCnt) 
                    End If 'iPosArr > iArrMaxCnt 
                ' add FTK name 
                    arrFiles(FILES_FTK, iPosArr) = Record.StringData(1) 
                ' the FilesSource flag allows to filter the data in the report to exclude patch only entries. 
                    arrFiles(FILES_SOURCE, iPosArr) = "Msi" 
                ' default IsPatched field to 'False' 
                    arrFiles(FILES_ISPATCHED, iPosArr) = False 
                ' add the LFN (long filename) 
                    arrFiles(FILES_FILE, iPosArr) = GetLongFileName(Record.StringData(3)) 
                ' add ComponentName 
                    arrFiles(FILES_COMPONENTNAME, iPosArr) = Record.StringData(2) 
                ' add ComponentID and Directory reference from Component table 
                    sQueryCompID = "SELECT `Component`, `ComponentId`, `Directory_` FROM Component WHERE `Component` = '" & Record.StringData(2) & "'" 
                    Set qViewCompID = MsiDb.OpenView(sQueryCompID) 
                    qViewCompID.Execute 
                    Set Record2 = qViewCompID.Fetch() 
                    arrFiles(FILES_COMPONENTID, iPosArr) = Record2.StringData(2) 
                    arrFiles(FILES_DIRECTORY, iPosArr) = Record2.StringData(3) 
                    Set Record2 = Nothing 
                    qViewCompID.Close 
                    Set qViewCompID = Nothing 
                ' ComponentState 
                    arrFiles(FILES_COMPONENTSTATE, iPosArr) = GetComponentState(sProductCode, arrFiles(FILES_COMPONENTID, iPosArr), iPosMaster) 
                ' add ComponentClients 
                    arrFiles(FILES_COMPONENTCLIENTS, iPosArr) = GetComponentClients(arrFiles(FILES_COMPONENTID, iPosArr), arrFiles(FILES_COMPONENTSTATE, iPosArr)) 
                ' add Features that use the component 
                    sQueryFC = "SELECT * FROM FeatureComponents WHERE `Component_` = '" & Record.StringData(2)  & "'" 
                    Set qViewFC = MsiDb.OpenView(sQueryFC) 
                    qViewFC.Execute 
                    Set Record2 = qViewFC.Fetch() 
                    Do Until Record2 Is Nothing 
                        arrFiles(FILES_FEATURENAMES, iPosArr) = arrFiles(FILES_FEATURENAMES, iPosArr) & Record2.StringData(1) & _ 
                                                               "(" & Translate