As most developers know, when automating MS Office applications you always start by binding to an existing instance, or creating a new instance if one is not already running. As such, you’d commonly use something like:
Dim oExcel As Object
On Error Resume Next
Set oExcel = GetObject(, "Excel.Application") 'Bind to existing instance of Excel
If Err.Number <> 0 Then 'Could not get instance of Excel, so create a new one
Err.Clear
On Error GoTo Error_Handler
Set oExcel = CreateObject("excel.application")
End If
On Error GoTo Error_Handler
Now for Excel, Word, PowerPoint, … this works beautifully. However, if you wish to automate Outlook, you will quickly realize that this approach does not work (anymore)!
Below is my solution to this problem.
'---------------------------------------------------------------------------------------
' Procedure : StartOutlook
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Demonstration of how one can start outlook if it isn't already started
' considering CreateObject("Outlook.Application") not longer works!
' Copyright : The following may be altered and reused as you wish so long as the
' copyright notice is left unchanged (including Author, Website and
' Copyright). It may not be sold/resold or reposted on other sites (links
' back to this site are allowed).
'
' Usage:
' ~~~~~~
'
'
' Revision History:
' Rev Date(yyyy/mm/dd) Description
' **************************************************************************************
' 1 2014-Oct-31 Initial Release
'---------------------------------------------------------------------------------------
Function StartOutlook()
On Error GoTo Error_Handler
Dim oOutlook As Object
Dim sAPPPath As String
If IsAppRunning("Outlook.Application") = True Then 'Outlook was already running
Set oOutlook = GetObject(, "Outlook.Application") 'Bind to existing instance of Outlook
Else 'Could not get instance of Outlook, so create a new one
sAPPPath = GetAppExePath("outlook.exe") 'determine outlook's installation path
Shell (sAPPPath) 'start outlook
Do While Not IsAppRunning("Outlook.Application")
DoEvents
Loop
Set oOutlook = GetObject(, "Outlook.Application") 'Bind to existing instance of Outlook
End If
' MsgBox "Outlook Should be running now, let's do something"
Const olMailItem = 0
Dim oOutlookMsg As Object
Set oOutlookMsg = oOutlook.CreateItem(olMailItem) 'Start a new e-mail message
oOutlookMsg.Display 'Show the message to the user
Error_Handler_Exit:
On Error Resume Next
Set oOutlook = Nothing
Exit Function
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: StartOutlook" & vbCrLf & _
"Error Description: " & Err.Description _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Function
'---------------------------------------------------------------------------------------
' Procedure : IsAppRunning
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Determine is an App is running or not
' Copyright : The following may be altered and reused as you wish so long as the
' copyright notice is left unchanged (including Author, Website and
' Copyright). It may not be sold/resold or reposted on other sites (links
' back to this site are allowed).
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sApp : GetObject Application to verify if it is running or not
'
' Usage:
' ~~~~~~
' IsAppRunning("Outlook.Application")
' IsAppRunning("Excel.Application")
' IsAppRunning("Word.Application")
'
' Revision History:
' Rev Date(yyyy/mm/dd) Description
' **************************************************************************************
' 1 2014-Oct-31 Initial Release
'---------------------------------------------------------------------------------------
Function IsAppRunning(sApp As String) As Boolean
On Error GoTo Error_Handler
Dim oApp As Object
Set oApp = GetObject(, sApp)
IsAppRunning = True
Error_Handler_Exit:
On Error Resume Next
Set oApp = Nothing
Exit Function
Error_Handler:
Resume Error_Handler_Exit
End Function
'---------------------------------------------------------------------------------------
' Procedure : GetAppExePath
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website : http://www.cardaconsultants.com
' Purpose : Determine the path for a given exe installed on the local computer
' Copyright : The following may be altered and reused as you wish so long as the
' copyright notice is left unchanged (including Author, Website and
' Copyright). It may not be sold/resold or reposted on other sites (links
' back to this site are allowed).
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sEXEName : Name of the exe to locate
'
' Usage:
' ~~~~~~
' Call GetAppExePath("msaccess.exe")
' GetAppExePath("firefox.exe")
' GetAppExePath("outlook.exe")
'
' Revision History:
' Rev Date(yyyy/mm/dd) Description
' **************************************************************************************
' 1 2014-Oct-31 Initial Release
'---------------------------------------------------------------------------------------
Function GetAppExePath(ByVal sExeName As String) As String
On Error GoTo Error_Handler
Dim WSHShell As Object
Set WSHShell = CreateObject("Wscript.Shell")
GetAppExePath = WSHShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\" & sExeName & "\")
Error_Handler_Exit:
On Error Resume Next
Set WSHShell = Nothing
Exit Function
Error_Handler:
If Err.Number = -2147024894 Then
'Cannot locate requested exe????
Else
MsgBox "The following error has occurred." & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: GetAppExePath" & vbCrLf & _
"Error Description: " & Err.Description, _
vbCritical, "An Error has Occurred!"
End If
Resume Error_Handler_Exit
End Function
GetObject Not Working Either?!
I have been recently told by some that even GetObject no longer works to detect active applications running. In such cases, perhaps the more reliable approach is to use https://www.devhut.net/vba-wmi-determine-if-a-process-is-running-or-not/
Other Resources:
Ron de Bruin has another solution to this problem, see: Test if Outlook is open and open Outlook with VBA
Thank you for sharing this! It is an absolute godsend and worked exactly as described on my first try. I have been trying to fix this issue for quite some time and your solution is relatively straight forward and 100% pure VBA. I made a donation because this is so useful and hard to find a solution to anywhere on the web. Thank you and keep posting more stuff like this!!!
Like Arman, I was pulling my hair out for a couple days trying to get past the errors:
– 80004023
– createobject(“outlook.application”)
– getObject(“outlok.application”)
– run-time error 429 when trying to make a reference to Outlook.
I tried late binding and early binding, but no luck with either.
My references were set correctly, and the Access DB would open Outlook and send an email on other Windows 7 machines.
It appears as if this specific machine on which the error was being created had Office 2007 and Office 2010 installed prior to me installing Office 2013. I’m guessing the error was more related to the previous version(s) not being COMPLETELY uninstalled, as I do see references to versions 12 and 14 in the registry, along with 15.0.
I uninstalled and reinstalled office several times, and tried tools that claimed to completely remove office. Nothing worked. I was about to re-install Windows, but I found this article. As per your solution, adding the reference to the current Outlook path solved the issue and Access 2013 is now able to open Outook 2013 and send email.
I can’t thank you enough.
Nice work on this Daniel. This problem with Outlook is far more extensive than I realized, but thanks to you it is no longer an issue.
ADezii (UtterAccess.com)
Thank you for this solution,ive been pulling my hairs out trying to fix this error.
prior to upgrading a pc to office 2013 i had to remove office 2010 proffessional
after doing this my application would get a runtime error while calling outlook application.
early binding and lite binding didint work at all!!
So thanks !!!!!!!!!!!!!!!!!!!!!!
Glad I could help. It was a problem I myself faced a while back which was infuriating and took me a little while to come up with this workaround.
may i ask..what if you want to make the outlook run in background and it is not visible..is that possible? thank you very much…
Well, unlike most other MS applications, Outlook does not appear to possess a Visible property so I’m not sure what can be done. There may be some fancy APIs that could be used, but I don’t know of them offhand.
Personally, if I wanted to send e-mails without displaying anything to the user I’d be looking at the SendObject method for primitive e-mail, and CDO Mail for more advanced e-mails.
Okay, so I hate not knowing things, so I did some digging and testing and I was right, using some APIs it is possible. One word of caution though is that if you’re not carefull with what you are doing you can leave hidden processes running on your user’s PC.
So for starters you’ add the following to your Module’s declaration section (top of your module under the Option Explicit
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Declare Function ShowWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal nCmdShow As Long) As LongThen in the code for the StartOutlook function example, you’d add two Dims to your code
Finally, right after the If IsAppRunning(“Outlook.Application”) = True Then If, Else, End If block you’d add
lWnd = FindWindow("rctrl_renwnd32", oOutlook.ActiveWindow.Caption) 'rctrl_renwnd32 -> Outlook's Class Name iRet = ShowWindow(lWnd, 0) '0 = HideAnd that should do it.
See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 for all the possible values you can assign (0=Hide, 5=Show probably should be part of your error handler so you don’t end up with hidden orphan process when something goes wrong)
It’s too bad Outlook doesn’t expose its HWnd like several other applications do making us need to use the FindWindow function, but the ultimate solution isn’t too too bad.
I hope that helps.
Thanks for this, I am trying to setup a button on an Access form that will create an outlook task from that form. While I thought this would be an easy project, apparently it isn’t so easy and thought I could use your info here to make it work. Any ideas?
Have you seen: VBA – Create an Outlook Task
While this works for me when running from a batch file, if I create a scheduled task to run the batch file, the IsAppRunning function returns false even with outlook open. Any ideas?
I’m sorry, but nothing comes to me offhand. Let me think about it. What OS are you running?
Hi Daniel,
I’m also having same issue, now its working fine after using the above code in VBA. but its working in Windows 7 and not working in Windows10. Any ideas?
Sorry, I don’t have/use Windows 10 because of it’s invasive nature, so I can’t say.
I will see about creating a Windows 10 VM to do some testing, but that won’t be until next week at the earliest.
Thank you so much for this code. It is fantastic!
Wondering if you have had a chance to look at it in Windows 10 as like Uma it works perfectly for me in Windows 7 but not Windows 10.
Thank you!
I’ll try to look into the matter.
That said, you are using Outlook installed locally on the PC and not through the web, right?
I did a quick test and can confirm the code works fine in Windows 10, so the question becomes what version of Outlook are you using? I tested with Windows 10 and Office 2013. Are you using the web based Outlook? Are you using Office 365? What bitness are you using (x32 or x64), remember you can automate between mixed bitnesses? If you give me more information I will try to see what is going on.
Well done and thanks for getting back to me many years after starting this thread. Great job!
I am running the code on (main machine) a Windows 10 64bit machine using Access 2003 and Outlook 2010.
I believe the issue is related to Outlook as when I run it on a Windows Server running Outlook 2003 (very old I know) it works fine.
I do have a reference in there for the ‘Microsoft Outlook 14.0 Object Library’ which I believe was added by previous developer to allow the sending of emails.
The code opens Outlook (even though its running) and then gets caught in the ‘Do While Not IsAppRunning(“Outlook.Application”)’ loop.
Thank you for your help
Thanks so much. This is really life saving. I have been research for months and this is the only solution that works perfectly
It’s working for me in Windows 10. Awesome!!
Thank you very much
In my case, I’m doing the following:
– MS Access VBA code checking to see if a report has been deposited in a network folder
– If not, I’m using an apiFindWindow API to see if Outlook is running. If so, it does nothing, otherwise it opens Outlook using a constant path and Shell command
– Wait 30 seconds, then use GetObject to get the current instance of Outlook
– Create and send an email (using Outlook object/item) notifying me that report did not run
The problem is that it seems to work intermittently if I step through the code and not really at all if I let it run on it’s own. Continue to get ActiveX can’t creat object 429 errors. Would your solution fix that based on what I’ve described?
Here are the references I have loaded:
Visual Basic for Applications
Microsoft Access 16.0Object Library
OLE Automation
Microsoft Outlook 16.0 Object Library
Microsoft Scripting Runtme
Here is the code: (the ActiveX error is thrown on the Set o = GetObject(, “Outlook.Application”) line
Dim o As Object
Dim m As Object
Dim retVal As Variant
‘Adjust if necessary
Const conPATH_TO_OUTLOOK As String = “C:\Program Files\Microsoft Office\Office16\OUTLOOK.EXE”
If apiFindWindow(CStr(“rctrl_renwnd32”), 0&) = 0 Then
‘Outlook is not running, let’s open it
retVal = Shell(conPATH_TO_OUTLOOK, vbMaximizedFocus)
WaitForTime (DateAdd(“s”, 60, Now))
Else
‘Outlook is running, I’ll leave the rest up to you!
End If
Set o = GetObject(, “Outlook.Application”)
Set m = o.CreateItem(0)
Associated API:
Option Compare Database
‘Declaration for the API Function
Declare PtrSafe Function apiFindWindow Lib “user32” Alias “FindWindowA” _
(ByVal strClassName As String, ByVal lpWindowName As Any) As Long
My best advice would be to test it and see what the results are. I have had a lot of positive feedback on this approach, but as with most things in life, try it for yourself and see what happens. You have nothing to loose.
Thank you very much!! The code works perfectly!
Hi,
I have ,
Microsoft Access 16.0 Object Library
Microsoft Outlook 14.0 Object Library
references added to my project. Your code works only if I don’t have any outlook instance on my pc already running. Other wise its creating new instance of the outlook “Shell (sAPPPath)” and goes into the never ending loop. I let it run for hours but doesn’t fint the running instance.
In this case if I try CreateObject(“Outlook.Application”) it gives me the vba 429 error.
Do you have any idea about it?
Ignoring my code for a minute, does Set oOutlook = GetObject(, “Outlook.Application”) work? If GetObject doesn’t work then I’d try an Office Repair, check macro/security settings …
Hey Daniel,
Thank you for pulling this together! M$ Word 2016 seems to be an entirely different animal when it comes to using VBScripting. I do a lot of VB in M$ Excel, but I’m a novice when it comes to Word.
I have a form I want our employees to use for onboarding new employees. I contains a series of text boxes, check boxes, and radio buttons. I have simple code to “SaveAsPDF”, which works really well. And, I have another button I want the user to quickly find the recently saved PDF, add it to an email, and send it, without the user having to setup the email.
Private Sub cbSaveAsPDF_Click() With Dialogs(wdDialogFileSaveAs) .Format = wdFormatPDF .Show End With End SubI’ve added your Functions in it’s own Module, but I’m not sure as to how to use the code when I click on a “cbSubmit CommandButton”. I double-clicked the command button and see “Private Sub cbSubmit_Click()” in the Project window, but I’m at a loss as how to proceed.
Please advise, sir.
JD Stewart
I know that’s an old thread and do not want to be unpolite trying to resurrect it. Please do not doubt to delete if you do not find it appropriate.
But i think could be of interest keep trying to find what is the problem here… Because in my case I have been using the “Get/Error/Create Object ” method for years and it has been working without any issue, but suddenly, in 2022, after a recent desktop Pc install, sometimes it works and sometimes it doesn’t, so all code related Outlook keep freezing because of that.
Before, I was using the Captured/Created object to send emails, register, open, edit appointments from Access- And when Outlook was not open, the Create procedure works, making Outlook process to run the ordered task in seconds and in background, without a visible instance.
What i found now, probably all you know, is that if I try to create object (after error and because outlook was closed) an Outlook icon with a yellow gear appears hidden in system area (tooltip: “Another Program is using Outlook. To disconnect…”) which keep hanging and do not obey nor the closing order of his own menu.
The most curious thing is that the same code keeps working perfectly fine in my laptop, having both the same software and config (W10 Pro x64, office 365 32x both up to date) and also the same references (I always use late binding to avoid version crossings).
And that leads me to think that it is some kind of install bug that Office repair do not solve (I doubt) or that it is caused by the Outlook Profile, that sometimes is lazy to start, realizing there was one difference between my systema as the laptop has an PST Outlook Profile with some POP3 accounts, while the Desktop has two OST Profiles.
I’ll keep trying to understand where the problem, because opening Outlook in foreground every now and them is a solution but does not completely suit my work pace.
Thanks for all your efforts in solving so odd problem!
Hey Daniel,
This thread is really interesting as it may help me with my issue…I was hoping that you can help. I’m getting the error when adding in a macro to an excel sheet which creates emails for the selected rows. Please could you advise if there is somthing that I need to change? I’m running office 2016 on a Mac.
Sub EmailAll()
Dim oApp As Object
Dim oMail As Object
Dim SendToName As String
Dim theSubject As String
Dim theBody As String
For Each c In Selection ‘loop through (manually) selected records
”’For each row in selection, collect the key parts of
”’the email message from the Table
SendToName = Range(“C” & c.Row)
theSubject = Range(“H” & c.Row)
theBody = Range(“I” & c.Row)
”’Compose emails for each selected record
”’Set object variables.
Set oApp = CreateObject(“Outlook.Application”)
Set oMail = oApp.CreateItem(0)
”’Compose the customized message
With oMail
.To = SendToName
.Subject = theSubject
.Body = theBody
”’ If you want to send emails automatically, use the Send option.
”’ If you want to generate draft emails and review before sending, use the Display option.
”’ Do not use both!
”’To activate your chosen option: Remove the single quote from the beginning of the code line, then
”’add the single quote back to the option you didn’t choose
.Display
‘.Send
End With
Next c
End Sub
Thanks
Nev
Jf. Ruiz – let me know if you ever found the cause or a solution as we’re having the same issue since we upgraded to O365. It’s very much hit or miss whether the error appears but seems to occur if the code is run consecutively back to back a few times which leaves me to think there’s either a memory leak or becomes slower releasing the previous process as time goes on? Restarting Outlook seems to resolve it but becomes a pain to keep doing this every 4th or 5th email created.
After many months checking every possible cause, I’m completely sure that the problem was due profiles with ost files.
At least in my case, if I have just POP3 mail accounts in a pst file all works perfectly as ever, but as soon I add an outlook.com, exchange or and imap mail account the problem arise.
My solution:
When I open the first form that need to interact with outlook I check if it is open, if not, I launch an outlook instance with the exe method, then I loop until all accounts are in sync and then I bind it to and object (getobject method) that I keep alive all time, recovering it for all functions that need it. That way the problem has gone.
The only downside is that now I have outlook always open, so it is not so clean as before, but it now works.
Very interesting. Thank you for sharing.
3/21/25 – This solution doesn’t work anymore with Office 365. and Windows 11. Using the shell command to open Outlook from Excel VBA sets the Windows focus to Outlook application when it opens and the Excel VBA code stops running until the user manually reactivates (resets Windows focus) back on the calling Excel application.
I’m afraid I’m not setup to perform the necessary validation on this, but if it’s just a question of getting the focus back on Excel that can easily be done with a variety of techniques.
Perhaps as easily as:
or one of the techniques covered in VBA – Find A Window By Its Title and Bring It To The Front