Vb.net 如何使用Exchange Web服务接受所需与会者的约会并向其添加类别

Vb.net 如何使用Exchange Web服务接受所需与会者的约会并向其添加类别,vb.net,exchangewebservices,ews-managed-api,Vb.net,Exchangewebservices,Ews Managed Api,我正在使用ExchangeService(ExchangeVersion.Exchange2010\u SP1) 我想接受并向所需的与会者约会添加类别。为此,我需要找到这些预约 我在EWS中的理解是,在保存需要与会者的约会时,会为每个“需要的与会者”创建一个新的会议请求 如何访问为“所需与会者”自动创建的约会?这些将作为约会以及会议请求显示在所需的与会者日历中 我在这个问题上做了一个粗略的发现(步骤如下) 以组织者身份连接到服务器 创建约会 设定主题 添加所需的与会者 保存约会 根据需要连接到服

我正在使用ExchangeService(ExchangeVersion.Exchange2010\u SP1)

我想接受并向所需的与会者约会添加类别。为此,我需要找到这些预约

我在EWS中的理解是,在保存需要与会者的约会时,会为每个“需要的与会者”创建一个新的会议请求

如何访问为“所需与会者”自动创建的约会?这些将作为约会以及会议请求显示在所需的与会者日历中

我在这个问题上做了一个粗略的发现(步骤如下)

  • 以组织者身份连接到服务器
  • 创建约会
  • 设定主题
  • 添加所需的与会者
  • 保存约会

  • 根据需要连接到服务器步骤4中的与会者

  • 在步骤3中查找具有主题的约会
  • 在步骤7将类别添加到约会
  • 在第7步更新约会
  • 在第7步接受预约
  • 这确实有效,但担心的用户会改变话题

    我已尝试向组织者创建的约会添加扩展属性和值,然后在作为所需与会者连接的约会中查找扩展属性值的数据项。这是行不通的

    对于我想要完成的事情,有没有更好的方法

    多谢各位

    Private Shared ReadOnly m_organiserEmailAddress As String = "Organiser@test.com"
    Private Shared ReadOnly m_eventIdExtendedPropertyDefinition As New ExtendedPropertyDefinition(DefaultExtendedPropertySet.Meeting, "EventId", MapiPropertyType.Long)
    
    '--> start here
    Public Shared Function SaveToOutlookCalendar(eventCalendarItem As EventCalendarItem) As String
    
        If eventCalendarItem.Id Is Nothing Then
            'new
            Dim newAppointment = EventCalendarItemMapper.SaveNewAppointment(eventCalendarItem)
            'set the Id
            eventCalendarItem.Id = newAppointment.Id.UniqueId.ToString()
            'accept the calendar item on behalf of the Attendee
            EventCalendarItemMapper.AcceptAppointmentAsAttendees(newAppointment)
            Return eventCalendarItem.Id
        Else
            'update existing appointment
            Return EventCalendarItemMapper.UpdateAppointment(eventCalendarItem)
        End If
    
    
    End Function
    
    Private Shared Sub ConnectToServer(Optional autoUser As String = "")
    
        If autoUser = "" Then
            _service.Url = New Uri(ExchangeWebServicesUrl)
        Else
            _service.AutodiscoverUrl(autoUser)
        End If
    
    End Sub
    
    Private Shared Sub ImpersonateUser(userEmail As String)
    
        _service.Credentials = New NetworkCredential(ImpersonatorUsername, ImpersonatorPassword, Domain)
        _service.ImpersonatedUserId = New ImpersonatedUserId(ConnectingIdType.SmtpAddress, userEmail)
    
    End Sub
    
    Private Shared Function SaveNewAppointment(eventCalendarItem As EventCalendarItem) As Appointment
    
        Try
            ConnectToServer(m_organiserEmailAddress)
            ImpersonateUser(m_organiserEmailAddress)
    
            Dim appointment As New Appointment(_service) With {
                       .Subject = eventCalendarItem.Subject}
    
            'add attendees
            For Each attendee In eventCalendarItem.Attendees
                appointment.RequiredAttendees.Add(attendee.Email)
            Next
    
            'add categories
            For Each category In eventCalendarItem.Categories
                appointment.Categories.Add(Globals.GetEnumDescription(category))
            Next
    
            'add EventId = 5059 as an extended property of the appointment
            appointment.SetExtendedProperty(m_eventIdExtendedPropertyDefinition, 5059)
    
            appointment.Save(SendInvitationsMode.SendOnlyToAll)
    
            Return appointment
        Catch
            Throw New Exception("Can't save appointment")
        End Try
    
    
    End Function
    
    Private Shared Sub AcceptAppointmentAsAttendees(appointment As Appointment)
    
        For Each attendee In appointment.RequiredAttendees
            Try
                ConnectToServer(attendee.Address.ToString())
                ImpersonateUser(attendee.Address.ToString())
    
                For Each a In FindRelatedAppiontments(appointment)
                    a.Categories.Add(Globals.GetEnumDescription(CalendarItemCategory.Workshop))
                    a.Update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToNone)
                    a.Accept(True)
                Next
    
            Catch
                Throw
            End Try
        Next
    End Sub
    
    Private Shared Function FindRelatedAppiontments(appointment As Appointment) As List(Of Appointment)
    
        Dim view As New ItemView(1000)
        Dim foundAppointments As New List(Of Appointment)
    
        view.PropertySet =
            New PropertySet(New PropertyDefinitionBase() {m_eventIdExtendedPropertyDefinition})
    
        'Extended Property value = 5059
        Dim searchFilter = New SearchFilter.IsEqualTo(m_eventIdExtendedPropertyDefinition, 5059)
    
        For Each a In _service.FindItems(WellKnownFolderName.Calendar, searchFilter, view)
            If a.ExtendedProperties.Count > 0 Then
                foundAppointments.Add(appointment.Bind(_service, CType(a.Id, ItemId)))
            End If
        Next
    
        Return foundAppointments
    
    End Function
    

    有一件事是可以肯定的,EWS中没有直接的内容。 老实说,到目前为止,我还没有将内部日历整合到交换日历中,我的经验正好相反,那就是从交换中获取什么到内部日历

    不管怎样,在阅读了你的代码之后,我认为你就快到了。不过,我建议您通过使用“it’s not's hard”(这并不难)来捕捉到达与会者的约会! 所以我想说步骤应该是这样的

  • 创建约会
  • 应用扩展属性(我建议使用GUID而不是硬编码的数字),如下所示
  • 创建一个扩展属性,并为约会放置guid,它不会更改,除非您从另一个约会复制了一个副本(毕竟它只是一个属性)

  • 使用StreamingNotificationEvent捕捉约会。在我看来,一个好方法是同时运行组织者和与会者,并抓住他们之间的约会。 为了看一个例子,我已经发布了对前面一个问题的答案。如果你觉得我的答案有用,请投票支持这两篇文章(这里和那里)的答案
  • 我不想让你害怕,但一旦你解决了当前的问题;如果你想继续,事情会变得更复杂。我可以写下我是如何解决会议问题的,但我一点也看不出来,所以如果你自己写的话可能会更好


    干杯

    为什么扩展属性不起作用?他们是否已从组织者复制到与会者?@否,因此,如果在步骤6中我以组织者身份连接到服务器,请为我的扩展属性值设置FindItems的SearchFilter,约会将返回。使用相同的代码,但作为所需的与会者连接到服务器,不会返回任何约会。我已尝试在FindItems WellKnownFolderName.Inbox中用于会议请求和约会的WellKnownFolderName.Calendar。老实说,我不认为我真的100%符合您的意思,或者您为什么想要这样。也许你可以用一些代码来解释如何作为组织者或与会者连接到服务器。你有两份申请吗?我可能建议您使用,以便您可以检测与会者日历上的约会。@BraveHeart我已包含一些代码。如果我在AcceptAppPointmentAsAttendes中连接到组织者电子邮件地址为的服务器,则将返回扩展属性值为5059的约会,但是,如果我像示例中那样连接为所需的与会者电子邮件地址,则不会返回任何约会-因此,我认为扩展属性不会复制到所需的与会者约会或会议请求。我希望我正在做的事情,从约会中获得为所需与会者创建的约会和/或会议请求将是简单的……谢谢,我将在这个周末看看你的建议,我会让你知道我进展如何。我还不太害怕;-)对不起,已经有一段时间了。我回到这个项目,在为所需的与会者创建日历项目时,使用事件处理程序设置流式通知,这样做了。非常感谢。我需要整理代码,一旦完成,我会发布解决方案并投票给你。
    private static readonly PropertyDefinitionBase AppointementIdPropertyDefinition = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "AppointmentID", MapiPropertyType.String);
    public static PropertySet PropertySet = new PropertySet(BasePropertySet.FirstClassProperties, AppointementIdPropertyDefinition);
    
    
    //Setting the property for the appointment 
     public static void SetGuidForAppointement(Appointment appointment)
    {
        try
        {
            appointment.SetExtendedProperty((ExtendedPropertyDefinition)AppointementIdPropertyDefinition, Guid.NewGuid().ToString());
            appointment.Update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToNone);
        }
        catch (Exception ex)
        {
            // logging the exception
        }
    }
    
    //Getting the property for the appointment
     public static string GetGuidForAppointement(Appointment appointment)
    {
        var result = "";
        try
        {
            appointment.Load(PropertySet);
            foreach (var extendedProperty in appointment.ExtendedProperties)
            {
                if (extendedProperty.PropertyDefinition.Name == "AppointmentID")
                {
                    result = extendedProperty.Value.ToString();
                }
            }
        }
        catch (Exception ex)
        {
         // logging the exception
        }
        return result;
    }