VBA GetObject不';t返回对正在运行的Outlook实例的引用,如果它是';他才刚开始

VBA GetObject不';t返回对正在运行的Outlook实例的引用,如果它是';他才刚开始,vba,outlook,Vba,Outlook,这段代码来自一个更大的块(一个在MS Access中运行的VBA类),但我把它缩小到了失败的部分 如果Outlook刚刚启动,第150行使用GetObject会触发错误429。如果我手动启动Outlook,立即切换回“代码”窗口,并保留大约10秒钟,然后调用上面的子窗口,它运行正常。如果我打开Outlook,使其获得焦点,我可以在大约5秒钟后运行sub CreateObject始终有效 当我检查Outlook是否打开,发现它没有打开,以编程方式打开它,然后运行上面的子项时,这一点很重要 或者,在

这段代码来自一个更大的块(一个在MS Access中运行的VBA类),但我把它缩小到了失败的部分

如果Outlook刚刚启动,第150行使用GetObject会触发错误429。如果我手动启动Outlook,立即切换回“代码”窗口,并保留大约10秒钟,然后调用上面的子窗口,它运行正常。如果我打开Outlook,使其获得焦点,我可以在大约5秒钟后运行sub

CreateObject始终有效

当我检查Outlook是否打开,发现它没有打开,以编程方式打开它,然后运行上面的子项时,这一点很重要

或者,在快速用户手动打开Outlook,然后快速运行我的代码的情况下,这很重要

我知道任何指向Outlook实例的对象变量总是指向同一个实例,但最好让它可靠地工作

我怀疑这与Outlook未正确初始化有关,可能是MAPI连接未建立。是否存在表示“准备就绪并等待”或类似内容的MAPI属性

我尝试了一些使用计时器暂停的方法(虽然成功率参差不齐),给Outlook一个正常启动的机会。但这似乎很笨拙。Outlook启动和运行所需的时间将取决于太多的因素,我要么必须将计时器设置得太长,浪费用户的时间,要么设置得太短,可能会出现错误429


欢迎您的建议。

您最好始终使用
CreateObject
——正如您所提到的,由于Outlook是一个单例对象,因此您总是可以得到相同的对象

如果要检查Outlook以前是否运行过,请检查
Application.Explorers.Count
Application.Inspectors.Count
是否都为零

Public Sub mrm_StartOutlook()
     
       Dim m_objOutlook As Outlook.Application
       Dim m_objNamespace As Outlook.NameSpace
     
140    On Error GoTo PROC_ERR
     
150      Set m_objOutlook = GetObject(, "Outlook.Application") 'reliably fails if Outlook just opened.
         'Set m_objOutlook = CreateObject("Outlook.Application") 'reliably works
     
160      Set m_objNamespace = m_objOutlook.GetNamespace("MAPI")
     
170    MsgBox m_objOutlook.Name & ", " & m_objNamespace.Accounts.Item(1)
     
PROC_EXIT:
180    Exit Sub
     
PROC_ERR:
190    MsgBox "line " & Erl & " Error: " & Err.Number & ". " & Err.Description, , _
       "StartOutlook"
200    Resume PROC_EXIT
     
     End Sub