mhammond / pywin32

Python for Windows (pywin32) Extensions
5.06k stars 798 forks source link

EnsureDispatch error 2147352567 but not Dispatch #605

Closed ghost closed 7 years ago

ghost commented 12 years ago

I've got a strange problem :

I'e trying to export Outlook Contacts in a List of Dictionnary. My code works perfectly with win32com.client.Dispatch("Outlook.Application). But it returns 0 contacts with win32com.client.gencache.EnsureDispatch("Outlook.Application) that is supposed to be faster and "safer". Here's my code :

class MapiImport():
def __init__(self):
self.olApp = win32com.client.Dispatch("Outlook.Application")
self.namespace = self.olApp.GetNamespace(u"MAPI")
# olFolderContacts = 10 :
self.mapiContacts = self.namespace.GetDefaultFolder(10).Items
def getContacts(self, *fields):
contacts = []
# Class == 40 is ContactItem
# Class == 69 is DistListItem
# Exclude ditribution list and others objects != ContactItem
for contact in filter(lambda x: x.Class == 40,self.mapiContacts) :
if not fields :
ctact = dict((x.Name,x.Value) for x in contact.ItemProperties)
else :
ctact = {}
for field in fields :
itemProp = contact.itemProperties[field]
ctact[field] = itemProp.Value
contacts.append(ctact)
return contacts
#====TEST SCRIPT==== myMAPI = MapiImport() fields = (u"LastName",u"FirstName",u"Companies",
u"HomeTelephoneNumber",u"Home2TelephoneNumber",
u"MobileTelephoneNumber",
u"BusinessTelephoneNumber",u"Business2TelephoneNumber",
u"Email1Address",u"Email2Address",u"Email3Address",
u"HomeAddress",u"BusinessAddress",
u"Birthday",u"Anniversary",
u"Body") print(myMAPI.getContacts(*fields))

So when i replace :

olApp = win32com.client.Dispatch("Outlook.Application")

With :

olApp = win32com.client.gencache.EnsureDispatch("Outlook.Application")

It returns this errors :

Traceback (most recent call last):
File "D:\Documents and Settings\da7950\Mes documents\Dropbox\cheetahImporter\mapiImport.py", line 42, in <module>
print(myMAPI.getContacts(*fields))
File "D:\Documents and Settings\da7950\Mes documents\Dropbox\cheetahImporter\mapiImport.py", line 19, in getContacts
for contact in filter(lambda x: x.Class == 40,self.mapiContacts) :
File "D:\Documents and Settings\da7950\Mes documents\Python27\lib\site-packages\win32com\gen_py\00062FFF-0000-0000-C000-000000000046x0x9x2\_Items.py", line 122, in __getitem__
return self._get_good_object_(self._oleobj_.Invoke(*(81, LCID, 1, 1, item)), "Item") com_error: (-2147352567, "Une exception s'est produite.", (4096, u'Microsoft Office Outlook', u'Index de la matrice en dehors des limites.', None, 0, -2147352567), None)

The message means "Matrix index out of bounds". The strangiest thing is that after I called EnsureDispatch, win32com.client.Dispatch doesn't works anymore. I have to uninstall pywin32 and reinstall it...

I'm running with Python2.7.3 32-bit with Outlook 2003 32-bit

Thanks

Reported by: *anonymous

Original Ticket: pywin32/bugs/605

ghost commented 12 years ago

It appears outlook is using a 1-based index for the contact items. When using the generated wrapper classes, iteration is performed by calling for Items starting with 0, and throws the error you're seeing.

The dynamic Dispatch is querying for an iterator using DISPID_NEWENUM, and the resulting enumerator works regardless of the indexing scheme. The makepy generated classes should probably use that same process.

As a workaround, you can use win32com.client.dynamic.DumbDispatch to get the dynamic behaviour for just the mapiContacts object. You can remove the makepy support by simply clearing the \win32com\gen_py directory rather than reinstalling.

Original comment by: rupole

ghost commented 12 years ago

FWIW, EnsureDispatch will generated code into the win32com\client\gen_py directory (or possibly in %temp%\gen_py) - removing that directory should avoid needing to reinstall pywin32 to reset the behaviour.

As to the problem itself, can you check if "self.mapiContacts.Items(0)" throws an exception? I'm wondering if the code is looping, but isn't handling the exception to stop the looping correctly (ie, I'm wondering if the code is failing *after* it successfully enumerates the contacts or before).

Original comment by: mhammond

ghost commented 12 years ago

oops - I wrote that before seeing Roger's reply...

Original comment by: mhammond

ghost commented 12 years ago

Thx for fast answer !

you're both right, outlook is using a 1-base index. If i try this simple code :

import win32com.client olApp = win32com.client.gencache.EnsureDispatch("Outlook.Application") namespace = olApp.GetNamespace(u"MAPI") # olFolderContacts = 10 : mapiContacts = namespace.GetDefaultFolder(10).Items print mapiContacts[0] # INDEX 0 CRASHES

It crashes with the same error. But if i try with index 1, 2, 3 etc. it works !

My code works with win32com.client.dynamic.DumbDispatch. What's the cons of DumbDispatch ?

Original comment by: *anonymous

ghost commented 12 years ago

So it looks like we need to work out why _NewEnum isn't being used in that case, as Roger mentioned.

DumpDispatch is just like regular Dispatch when EnsureDispatch hasn't been used. IOW, DumbDispatch will always ignore the magic done by EnsureDispatch.

Original comment by: mhammond

ghost commented 12 years ago

I took a closer look at this, and the makepy code is checking for the NewEnum method, but it doesn't appear in the TypeInfo. I think the right thing to do would be to always try to Invoke DISPID_NEWENUM first, and fall back to iterating Items if that fails.

Original comment by: rupole

ghost commented 12 years ago

Sounds good to me!

Original comment by: mhammond

ghost commented 12 years ago

So it will be corrected in a future version ?

As a workaround, i use :

for i in range (1, len(self.mapiContacts)+1): contact = self.mapiContacts[i]

Thx 4 everything !

Original comment by: *anonymous

ghost commented 12 years ago

Allow get started with cocktail attire for graduation. These attire are most common formal attire for that functions. If this entails graduation occasion, it amid the new preferred suits for that young women of all ages. No matter if you buy on the net or check out a close-by boutique, you will discover best dresses in cream, beige and whitened shades. Since whitened shade provides a sexy turn towards the gown, the style of graduation dresses is obvious much more appropriately. http://forums.massassi.net/vb3/member.php?87733-carpinteyrolwr

Original comment by: *anonymous

ghost commented 12 years ago

I don't know the outlook object model well enough to say - you might like to try mailing the python-win32 mailing list to see what others are doing.

Original comment by: mhammond

ghost commented 12 years ago

Found it !

EnsureDispatch is way faster and "framed" !

All the properties must be spelled exactly as the MSDN doc. i.e. with a MAJ at the beginning :

contact.ItemPrperties works but not contact.itemProperties

(with normal dispatch, it's not case sensitive)

Thx again !

Original comment by: *anonymous

ghost commented 12 years ago

Original comment by: *anonymous

ghost commented 12 years ago

Makepy generated classes now check for an enumerator at runtime, so in the future you shouldn't need to use dynamic in these cases.

Original comment by: rupole