I'm trying to write a Python script to extract data from messages in Outlook 2013 folders. The method described everywhere to access Outlook is to first run:
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
This works fine if Outlook is NOT running. But if it is, this throws an error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program Files\Python27\lib\site-packages\win32com\client\__init__.py", line 95, in Dispatch
dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
File "C:\Program Files\Python27\lib\site-packages\win32com\client\dynamic.py", line 114, in _GetGoodDispatchAndUserName
return (_GetGoodDispatch(IDispatch, clsctx), userName)
File "C:\Program Files\Python27\lib\site-packages\win32com\client\dynamic.py", line 91, in _GetGoodDispatch
IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
pywintypes.com_error: (-2146959355, 'Server execution failed', None, None)
Based on a similar issue reported for another application which does not support running multiple instances at the same time either, I tried adapting their solution:
try:
app = win32com.client.Dispatch('Outlook.Application')
except:
app = win32com.client.GetActiveObject('Outlook.Application')
But this does not work either. GetActiveObject now fails with error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Program Files\Python27\lib\site-packages\win32com\client\__init__.py", line 79, in GetActiveObject
dispatch = pythoncom.GetActiveObject(resultCLSID)
pywintypes.com_error: (-2147221021, 'Operation unavailable', None, None)
So what would be the correct way to connect to a running instance of Outlook?
Answering my own question:
The root cause was that I was running Python in a command window running as Administrator.
If I start cmd.exe as a normal user, things work without error.
I wish GetActiveObject() would return a more meaningful error message in this case!
Side note: Reversing the two alternatives works faster:
try:
outlook = win32com.client.GetActiveObject('Outlook.Application')
except:
outlook = win32com.client.Dispatch('Outlook.Application')
Outlook is a singleton, so no matter what you do, it will always connect to the running instance. The only problem (as you have discovered) is that if is already running under a different security context, COM system will refuse to marshal COM objects between the two processes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With