5

After reading how to use automation to send a message, I'm unclear of whether it's possible to avoid opening a new instance of Outlook if I already have one opened. If so, I'm unsure of how to search for examples determining whether an existing Outlook instance is open.

-----Including the suggestion--------

I have the following snippet, but I found that I can't create the instance properly. I'm basically following this example. I'm either getting this screenshot, or the error of "User-defined type not defined." Any suggestions?

Sub Example()
    'Dim w As Outlook.Application

    Const ERR_APP_NOTRUNNING As Long = 429
    On Error Resume Next


' Handle Microsoft outlook
    Set w = GetObject(, "Outlook.Application")
    If Err = ERR_APP_NOTRUNNING Then
      'Set w = New Outlook.Application
      Set w = CreateObject("Outlook.Application")
    End If
End Sub
Community
  • 1
  • 1
stanigator
  • 10,768
  • 34
  • 94
  • 129

4 Answers4

11

I know this question has been answered, but I thought I'd add that applications like Outlook (and I believe PowerPoint as well) are single-instance applications -- there is no need to determine if Outlook is already open because you can only have one copy of Outlook running.

http://msdn.microsoft.com/en-us/library/aa164542(v=office.10).aspx

If you need to instantiate Outlook, simply use CreateObject to create the instance; if Outlook is already running, your object reference will point to the existing instance. If not, you will create the class. Binding (late or early) is irrelevant.

For example, let's say Outlook isn't running. We can use this code to create the instance:

Sub testOutlook()

Dim olApp As Object ' Outlook.Application

Set olApp = CreateObject("Outlook.Application")
  MsgBox (olApp2 Is Nothing)

End Sub

This will print "False" because we created the instance.

Let's say Outlook IS running. We can use this code to verify that using GetObject and CreateObject will refer to the existing instance:

Sub testOutlook()

Dim olApp As Object ' Outlook.Application
Dim olApp2 As Object ' Outlook.Application

Set olApp = GetObject(, "Outlook.Application")
  MsgBox (olApp Is Nothing)

Set olApp2 = CreateObject("Outlook.Application")
  MsgBox (olApp2 Is Nothing)
  MsgBox "Same object? " & (olApp Is olApp2)

End Sub

This will print "False" (existing instance), "False" (our alleged "new instance"), but the last message box is "True" because the new instance is actually the same object as the existing instance.

So what do we do if we don't know if Outlook is running or not? As demonstrated above, CreateObject either created a new instance (if one didn't exist, as in the first example) or hooked the existing instance if Outlook was already open (as in the second example).

JimmyPena
  • 8,694
  • 6
  • 43
  • 64
  • It might be single instance, however I have a VB6 application where I let user send an email. So what happens is i have Dim oApp as Outlook.Application. Then I do Set oApp as New Outlook.Application, and this works perfectly fine in Windows 7 (having outlook open), but it does not work in Windows 10 - any idea? – BobSki Jul 13 '17 at 13:54
  • @Jimmy - I know this is an old question but I see you've been active recently... I'm not convinced your answer is correct. Could this have changed in more recent versions? Your first code sample returns FALSE because of a typo: the variable is not declared. Still, when fixed, it still returns FALSE regardless of whether there's an existing instance of Outlook. – ashleedawg Mar 09 '18 at 10:06
  • I confirm that this behavior remains for windows 10 and Office 365 both 64 bits; with CreateObject it gets an already opened instance. – Marcelo Scofano Diniz Aug 18 '19 at 14:48
6

I see in your question that you commented out

'Dim w As Outlook.Application

presumably because this gives you the "User-defined type not defined" error.

This is likely because you have not set a reference to the Outlook library in your Excel-VBA project. This is done as follows: Tools > References > check "Microsoft Outlook xx.x Object Library". Then you can write this

Dim w As Outlook.Application
Set w = New Outlook.Application
' or, 
'Set w = CreateObject("Outlook.Application")

which, by the way, results in compile-time (or "early") binding. And gives you the Outlook object intellisense.

Alternatively, you can omit setting the reference and declare w as a generic object and let it bind at run-time

Dim w As Object
Set w = CreateObject("Outlook.Application")

but runtime (or "late") binding is less efficient.

Do whatever feels best -- I'm going to go ahead and venture that chances are, you won't notice the difference in efficency. I'm a recent convert to the early-binding thing, really just because of the intellisense.

EDIT So you've created a new Outlook application, but you can't see it. If you look in the Windows task manager, you'll see that the process is there, running -- but it's just not showing on the screen. Unfortunately, some brilliant engineer at Microsoft decided that Outlook shouldn't have a Visible property like Word or Excel do, so we have to use an awkward workaround. Open one of the special folders e.g. the Inbox like this:

Dim w As Outlook.Application
Dim wInbox As Outlook.MAPIFolder

Set w = New Outlook.Application
Set wInbox = w.GetNamespace("MAPI").GetDefaultFolder(olFolderInbox)

wInbox.Display 'This makes Outlook visible
Jean-François Corbett
  • 37,420
  • 30
  • 139
  • 188
  • I've made the changes, but I don't see a new Outlook application opened whether Set w = New Outlook.Application or Set w = CreateObject("Outlook.Application") is executed. Is this normal? – stanigator Jun 27 '11 at 00:57
  • @stanigator: If you have many different/successive questions, then please post each as a question individually. I'll answer this last one in an edit to my answer. – Jean-François Corbett Jun 27 '11 at 08:59
  • Francois Corbett: Thanks for the edit. I wasn't sure if my follow-up question was in the same context of the original one, therefore I added it in the comments to avoid making a duplicate. – stanigator Jun 27 '11 at 19:29
  • The edit about visibility was helpful to me today. I found a more generic approach which uses the Parent property that may be helpful to others in some situations, e.g., Set outApp = CreateObject("Outlook.Application") : Set outMail = outApp.CreateItem(olMailItem) : outMail.Parent.Display – Doug Glancy Nov 24 '11 at 17:30
1
    Set w = GetObject(, "Outlook.Application")

this should get running instance, if none is running catch error and do CreateObject

vlscanner
  • 448
  • 5
  • 16
  • Thanks for the suggestion. I have updated my question regarding the attempt. Got any clue of what's wrong with how I'm calling the function? – stanigator Jun 26 '11 at 01:10
  • Did CreateObject ever worked before on Outlook.Application ? It seems like COM registration issue on your machine. I do not know what versions your using but you might need to register Outlook type lib. Please post versions of all involved – vlscanner Jun 26 '11 at 15:52
0

If you like, use this.
This is not a perfect solution, but you can open Outlook App when it's not be opened.

Function OpenOutlookApp(isSend As Boolean) As Boolean

    ' If it has opened, return true.
    ' my office version is 2016.

    Dim oApp As Object

    On Error GoTo ErrorHandle

    On Error Resume Next

    Set oApp = GetObject(, "Outlook.Application")

    On Error GoTo 0

    If oApp Is Nothing Then

        Set oApp = CreateObject("Outlook.Application")

        oApp.GetNamespace("MAPI").GetDefaultFolder(6).Display

    End If

    If isSend Then Call SendAndReceiveOutlookMail(False)

    OpenOutlookApp = True

    GoTo NonErrorHandle

    ErrorHandle:
        
    NonErrorHandle:

    On Error GoTo 0

End Function

Sub SendAndReceiveOutlookMail(isQuit As Boolean)

    Dim oApp As New Outlook.Application

    On Error Resume Next

    Call oApp.Session.LogOn("Outlook", "")

    Call oApp.Session.SendAndReceive(True)

    If isQuit Then oApp.Quit

    Set oApp = Nothing

    On Error GoTo 0

End Sub
Josef
  • 2,869
  • 2
  • 22
  • 23
FaceTowel
  • 19
  • 6