C++ 通过activex从c++;随机返回未知错误

C++ 通过activex从c++;随机返回未知错误,c++,vbscript,outlook,activex,exchange-server,C++,Vbscript,Outlook,Activex,Exchange Server,我目前正在编写一个程序,需要导入整个Outlook通讯录。该程序是用C++编写的(用GCC(MIWW)编译),我用ActiveX连接Outlook。 我是这样做的: 创建Outlook.Application的实例 获取当前会话 获取地址列表 对于AddressList中的每个AddressList:获取AddressEntries 对于AddressEntries中的每个AddressEntries:确定它是ContactItem、ExchangeUser还是其他内容 如果是ContactIt

我目前正在编写一个程序,需要导入整个Outlook通讯录。该程序是用C++编写的(用GCC(MIWW)编译),我用ActiveX连接Outlook。 我是这样做的:

  • 创建Outlook.Application的实例
  • 获取当前会话
  • 获取地址列表
  • 对于AddressList中的每个AddressList:获取AddressEntries
  • 对于AddressEntries中的每个AddressEntries:确定它是ContactItem、ExchangeUser还是其他内容
  • 如果是ContactItem:请阅读以下属性:FirstName、LastName、MailingAddressStreet、MailingAddressPostOfficeBox、MailingAddressPostalCode、MailingAddressCity、CompanyName、Department、JobTitle、PrimaryTelephoneNumber、OtherTelephoneNumber、BusinessFaxNumber和Email1Address
  • 如果是Exchange用户:请阅读以下属性:FirstName、LastName、StreetAddress、PostalCode、City、CompanyName、Department、JobTitle、BusinessTelephoneNumber、MobileTelephoneNumber、Address
  • 如果它是另一种类型的AddressEntry,请忽略它
  • 只要通讯录中只有几个联系人,这就很有魅力。 但现在我正在一家更大的公司试驾,地址簿中大约有500个联系人(包括ContactItems和ExchangeUsers),分为22个不同的地址列表

    在读取最大的地址列表(包含180个地址条目,所有ExchangeUsers)期间,Outlook的ActiveX组件突然返回未知错误(IDispatch->Invoke的返回值为0xFFFFFF)。它通常位于第105和第115个AddressEntry之间,并且通常在读取MobileTelephoneNumber属性的过程中(但是如果我将其注释掉,它只会在另一个调用中失败)

    知道我做错了什么吗? 我的印象是,这与大量连续呼叫有关。也许每次呼叫后我都应该做一些清理工作

    反正, 任何帮助都将不胜感激

    问候,, ldx

    编辑:代码 (为了简洁起见,省略头文件)

    1.申请类别
    Contact*MSOutlookContactSource::ToContact(SP contactUser)const
    {
    触点*c=新触点;
    c->setFirstName(contactUser->GetFirstName())
    .setLastName(contactUser->GetLastName())
    .setStreet(contactUser->GetMailingAddressStreet())
    .setStreetNr(contactUser->GetMailingAddressPostOfficeBox())
    .setZip(contactUser->GetMailingAddressPostalCode())
    .setCity(contactUser->GetMailingAddressCity())
    .setCompany(contactUser->GetCompanyName())
    .setDepartment(contactUser->GetDepartment())
    .setFunction(contactUser->GetJobTitle())
    .setTel1(contactUser->GetPrimaryTelephoneNumber())
    .settL2(contactUser->GetOtherTelephoneNumber())
    .setFax(contactUser->GetBusinessFaxNumber())
    .setEmail(contactUser->GetEmail1Address());
    返回c;
    }
    //----------------------------------------------------------------------
    联系人*MSOutlookContactSource::ToContact(SP exchangeUser)常量
    {
    触点*c=新触点;
    c->setFirstName(exchangeUser->GetFirstName())
    .setLastName(exchangeUser->GetLastName())
    .setStreet(exchangeUser->GetStreetAddress())
    .setZip(exchangeUser->GetPostalCode())
    .setCity(exchangeUser->GetCity())
    .setCompany(exchangeUser->GetCompanyName())
    .setDepartment(exchangeUser->GetDepartment())
    .setFunction(exchangeUser->GetJobTitle())
    .setTel1(exchangeUser->GetBusinessTelephoneNumber())
    .settL2(exchangeUser->GetMobileTelephoneNumber())
    .setEmail(exchangeUser->GetAddress());
    返回c;
    }
    //----------------------------------------------------------------------
    vector MSOutlookContactSource::GetAllContacts()常量
    {
    日志getAddressList());
    长numAddressLists=addressLists->GetCount();
    
    LOG你需要服从调度程序,这样你的宏就不会被终止。有几种方法可以解决这个问题,但我发现与的结合似乎可以解决这个问题

    这可能需要根据您的环境设置和性能需要进行一些调整

    弯钩 j=1到objaddresentries.Count的
    
    '允许其他事件触发
    对于intWait=1到15000
    多芬特
    下一个
    "屈服于其他事件",
    如果(j Mod 50=0),则
    睡眠(5000)
    如果结束
    '进程地址条目
    '...
    下一个
    
    睡眠依赖项(位于模块子模块顶部)
    声明子睡眠库“kernel32”(ByVal-dwms长度)
    
    错误为RPC_S_调用失败和RPC_E_服务器故障。 这表示您打开的对象太多,RPC通道已用完(限制由Exchange服务器施加)。
    一旦停止使用Outlook对象,请立即释放它们,并避免使用多点表示法(这会创建无法显式引用和释放的隐式变量).

    您应该为上下文共享您的代码。您可能是。嗯,我的格式似乎有问题……恐怕这解决不了问题。首先:vbs示例不是outlook中的宏,它是一个简单的vbs文件(由windows脚本主机执行)第二,这并不能解决我的C++应用程序中的问题,第三,我已经尝试在第二个循环中插入一个睡眠(因此在每个地址条目的处理之间)没有帮助。是的,我也在某个地方读过。我已经更新了VBS代码来显式地将使用的对象重新设置为零。(我读到,这是在VBS中处理对象的方法(我以前没有VBS的经验),但是结果保持不变。正如您所看到的,我在C++中的基础对象的析构函数中显式调用IDISPoto->释放(AcExxPosiver),我知道它是有效的(日志)。.那么我猜这些物体没有被正确释放?你知道怎么释放吗
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    If Not objFSO.FileExists("out.log") Then
       objFSO.CreateTextFile("out.log")
    End If
    Set objLog = objFSO.OpenTextFile("out.log", 2, True)
    
    Set objOutlook = CreateObject("Outlook.Application")
    Set objSession = objOutlook.Session
    Set objAddressLists = objSession.AddressLists
    objLog.WriteLine("--- Found " + CStr(objAddressLists.Count) + " AddressLists")
    
    For i = 1 To objAddressLists.Count
        objLog.WriteLine("--- AddressList " + CStr(i))
        Set objAddressList = objAddressLists.Item(i)
        objLog.WriteLine("+++ AddressListName = " + objAddressList.Name)
        Set objAddressEntries = objAddressList.AddressEntries
        objLog.WriteLine("--- AddressList has " + CStr(objAddressEntries.Count) + " AddressEntries")
    
        For j = 1 To objAddressEntries.Count
    
          objLog.WriteLine("--- AddressEntry " + CStr(i) + "." + CStr(j))
          Set objAddressEntry = objAddressEntries.Item(j)    
    
          If objAddressEntry.AddressEntryUserType = olExchangeUserAddressEntry Then
    
            Set objExchangeUser = objAddressEntry.GetExchangeUser()
            objLog.WriteLine("Exchangeuser: " + _
                             objExchangeUser.FirstName + "|" + _
                             objExchangeUser.LastName + "|" + _
                             objExchangeUser.StreetAddress + "|" + _
                             objExchangeUser.PostalCode + "|" + _
                             objExchangeUser.City + "|" + _
                             objExchangeUser.CompanyName + "|" + _
                             objExchangeUser.Department + "|" + _
                             objExchangeUser.JobTitle + "|" + _
                             objExchangeUser.BusinessTelephoneNumber + "|" + _
                             objExchangeUser.MobileTelephoneNumber + "|" + _
                             objExchangeUser.Address)
            Set objExchangeUser = Nothing
    
          ElseIf objAddressEntry.AddressEntryUserType = olOutlookContactAddressEntry Then
    
            Set objContact = objAddressEntry.GetContact()
            objLog.WriteLine("Contactuser: " + _
                             objContact.FirstName + "|" + _
                             objContact.LastName + "|" + _
                             objContact.MailingAddressStreet + "|" + _
                             objContact.MailingAddressPostOfficeBox + "|" + _
                             objContact.MailingAddressPostalCode + "|" + _
                             objContact.MailingAddressCity + "|" + _
                             objContact.CompanyName + "|" + _
                             objContact.Department + "|" + _
                             objContact.JobTitle + "|" + _
                             objContact.PrimaryTelephoneNumber + "|" + _
                             objContact.OtherTelephoneNumber + "|" + _
                             objContact.BusinessFaxNumber + "|" + _
                             objContact.Email1Address)
            Set objContact = Nothing
          End If
          Set objAddressEntry = Nothing
        Next
        Set objAddressEntries = Nothing
        Set objAddressList = Nothing
    Next
    
    objTextFile.Close
    MsgBox "Done"
    
    Error: The server threw an exception Code: 80010105 Source: (null) Error: The remote procedure call failed Code: 800706BE Source: (null)