Search code examples
excelvbaoutlookpreprocessorpreprocessor-directive

VBA - Detect if an application is installed to use it


I made an Excel file that store a lot of custom industrial parts' informations.
It allows users to send via Outlook a preformatted mail to ask for a new price.

Unfortunately, some users have "light" desktop without Outlook and they get an error :

Can't find Project or Library

Installing Outlook is unfortunately not an option, late biding already done.


I was thinking about preprocessor directives but I can't figure out how to use them in my case...

I know the constants that we can use for Windows and VBA versions : see here

I would have done something like this :

#If Outlook then
    MsgBox "Outlook is installed"
#Else
    MsgBox "Outlook is NOT installed"
#End if

But this will only detect if the code is run from Outlook or not, which is not what I need... :/


So I guess that I could do something this with On Error but it doesn't seem neat, any suggestions?


Solution

  • I tried to find other ways of detecting apps without relying on errors from CreateObject

    This uses the WMI object and it seems to work well but it doesn't distinguish a demo version
    It lists installed apps in registry path Microsoft\Windows\CurrentVersion\App Paths (32 & 64 bit)


    Public Function AppDetected() As Boolean
        Const HKEY_LOCAL_MACHINE = &H80000002   'HKEY_CURRENT_USER = &H80000001
        Const APP_PATH = "\Microsoft\Windows\CurrentVersion\App Paths\"
        Const APP_PATH_32 = "SOFTWARE" & APP_PATH
        Const APP_PATH_64 = "SOFTWARE\Wow6432Node" & APP_PATH
        Const REG_ITM = "!\\.\root\default:StdRegProv"
        Const REG = "winmgmts:{impersonationLevel=impersonate}" & REG_ITM
        Const ID = "Outlook"   '"OUTLOOK.EXE"
    
        Dim wmi As Object, subKeys As Variant, found As Variant
    
        If wmi Is Nothing Then Set wmi = GetObject(REG)
    
        If wmi.EnumKey(HKEY_LOCAL_MACHINE, APP_PATH_32, subKeys) = 0 Then
            If Not IsNull(subKeys) Then found = UBound(Split(Join(subKeys), ID)) > 0
        End If
        If Not found Then
            If wmi.EnumKey(HKEY_LOCAL_MACHINE, APP_PATH_64, subKeys) = 0 Then
                If Not IsNull(subKeys) Then found = UBound(Split(Join(subKeys), ID)) > 0
            End If
        End If
        AppDetected = found
    End Function
    

    Note: I only tested it on a machine without Outlook

    More details about WMI Tasks: Registry from MS


    Another version of WMI using MIME, that shows installed MS apps, in VBScript:

    Set wmi = GetObject("winmgmts:\\.\root\CIMV2")
    Set itms = wmi.ExecQuery("SELECT * FROM Win32_MIMEInfoAction", "WQL", &h10 + &h20)
    
    For Each itm In itms
        WScript.Echo itm.Name
    Next
    

    Detect MS Mail, similar to CreateObject: Application.ActivateMicrosoftApp xlMicrosoftMail


    Determine Outlook user accounts:

    'If Outlook exists, set reference to Microsoft Outlook *
    Public Function ShowOutlookAccount() As Long
        Dim appOutlook As Outlook.Application, i As Long
    
        Set appOutlook = CreateObject("Outlook.Application")
        For i = 1 To appOutlook.Session.Accounts.Count
            Debug.Print appOutlook.Session.Accounts.Item(i) & " : Account number " & i
        Next
    End Function
    

    More Outlook utils from Ron de Bruin