检索显示异常行为的日历项(Outlook API,WebDAV)


79

我们正在编写一个MS Outlook插件。为了满足我们的业务逻辑,它应该检查某些日期之间的所有约会。从日历中检索所有项目时,我们遇到了一些问题。我们尝试了两种选择:

  1. Outlook API。我们使用MSDN中描述的标准逻辑-按[开始]对项目进行排序,设置IncludeRecurrencesTrue并运行对日历项目的Find \ Restrict查询,例如此处。在我们的测试环境中,它运作良好。但是,在我们客户的环境中:对于定期约会,开始日期和结束日期设置为“主约会”的相应日期。例如,在某个房间的日历中,我们有一个在1月创建的每周约会,如果我们尝试查找8月的所有项目,则除此定期约会外,我们还有其他4个项目,但它们的开始日期和结束日期设置为1月。 。但是Outlook在同一日历中显示正确的日期...

  2. 非常糟糕,但是我们仍然有WebDAV!我们编写了一个简单的测试应用程序,并尝试使用WebDAV查询日历中的所有项目。当然,我们并没有重新发明轮子,只是从文档中粘贴了代码。前一个问题已解决,但下一个问题出现了:它不会返回大约六个月前创建的重复项目。我不知道-没有参数限制“旧”物品!

怎么了?我们缺少重要的东西吗?

技术详细信息:Exchange 2003,Outlook 2003-2010。坦白说,如果打开“缓存Exchange模式”,第一个错误就会消失,但是我们不能这样做。

var nameSpace = application.GetNamespace("MAPI");
var recepient = nameSpace.CreateRecipient(roomEMail);
recepient.Resolve();
var calendar = nameSpace.GetSharedDefaultFolder(recepient, OlDefaultFolders.olFolderCalendar);
var filter = string.Format("[Start]<'{1}' AND [End]>'{0}'",
  dateFrom.ToString("dd/MM/yyyy HH:mm", CultureInfo.InvariantCulture), dateTo.ToString("dd/MM/yyyy HH:mm", CultureInfo.InvariantCulture)
);
var allItems = calendar.Items;
allItems.Sort("[Start]");
allItems.IncludeRecurrences = true;
var _item = allItems.Find(filter);
while (_item != null) {
  AppointmentItem item = _item as AppointmentItem;
  if (item != null) {
    if (item.Subject != "some const")
      && (item.ResponseStatus != OlResponseStatus.olResponseDeclined)
      && (item.MeetingStatus != OlMeetingStatus.olMeetingReceivedAndCanceled 
      && item.MeetingStatus != OlMeetingStatus.olMeetingCanceled))
    {
      /* Here we copy item to our internal class.
       * We need: Subject, Start, End, Organizer, Recipients, MeetingStatus,
       * AllDayEvent, IsRecurring, RecurrentState, ResponseStatus,
       * GlobalAppointmentID */
    }
  }
  _item = allItems.FindNext();
}

更新1:

使用OutlookSpy进行的其他研究表明,问题不在我们的代码中-当关闭“缓存Exchange模式”时,API中的开始\结束日期不正确。但是Outlook开发人员意识到了这一点,并且他们以某种方式在日历中显示了正确的日期!有人知道吗?

更新2:

Outlook支持升级工程师的回答:

基于此,我可以确认这是我们产品中的问题。


3
1.您的代码是什么?2.不要使用WebDAV;不推荐使用。
德米特里·斯特雷布琴科

看起来很好...访问约会的代码是什么?您是否曾经访问过AppointmentItem.Parent(它将为您提供重复活动实例的主约会)?
德米特里·斯特雷布琴科

我已经更新了上面的代码。不,我们不使用AppointmentItem.Parent。无论如何,在访问开始日期和结束日期之前,我们仅访问AppointmentItem的Subject,ResponseStatus和MeetingStatus属性。
Bolick

一方面,Outlook不使用OOM来显示Calendar文件夹的内容,其次,为什么您认为开始/结束日期不正确?到底是什么问题?
德米特里·斯特雷布琴科

确实:OutlookSpy向我们显示了几个具有相同StartTime的约会,在我们的例子中是2012年11月1日,这绝对是每周定期活动的主约会(同一组织者,同一主题等)。但是在日历中,我们可以看到正确的图片-每周一次。如果您能解释Outlook的工作原理,它用于显示日历的技术,关于在OOM中导致错误的原因以及如何解决这些错误的任何想法,我将不胜感激。
Bolick

Answers:


1

可能的原因:

  • 设置IncludeRecurrences后进行排序。

这是我在两个日期之间检索Outlook项目的PowerShell模块的代码。

还有一个小程序,用于检查更改并发送包含议程更新的电子邮件,当您无法通过移动设备访问Exchange时,该小程序将很方便。

路径:Documents \ WindowsPowerShell \ Modules \ Outlook \ expcal.ps1

Function Get-OutlookCalendar
{
  <#
   .Synopsis
    This function returns appointment items from default Outlook profile
   .Description
    This function returns appointment items from the default Outlook profile. It uses the Outlook interop assembly to use the olFolderCalendar enumeration.
    It creates a custom object consisting of Subject, Start, Duration, Location
    for each appointment item.
   .Example
    Get-OutlookCalendar |
    where-object { $_.start -gt [datetime]"5/10/2011" -AND $_.start -lt `
    [datetime]"5/17/2011" } | sort-object Duration
    Displays subject, start, duration and location for all appointments that
    occur between 5/10/11 and 5/17/11 and sorts by duration of the appointment.
    The sort is the shortest appointment on top.
   .Notes
    NAME:  Get-OutlookCalendar
    AUTHOR: ed wilson, msft
    LASTEDIT: 05/10/2011 08:36:42
    KEYWORDS: Microsoft Outlook, Office
    HSG: HSG-05-24-2011
   .Link
     Http://www.ScriptingGuys.com/blog
 #Requires -Version 2.0
 #>

 echo Starting... Initialize variables

 Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null
 $olFolders = "Microsoft.Office.Interop.Outlook.OlDefaultFolders" -as [type]
 $olCalendarDetail = "Microsoft.Office.Interop.Outlook.OlCalendarDetail" -as [type]

 echo ... Getting ref to Outlook and Calendar ...

 $outlook = new-object -comobject outlook.application
 $namespace = $outlook.GetNameSpace("MAPI")
 $folder = $namespace.getDefaultFolder($olFolders::olFolderCalendar)

 echo ... Calculating dates ...

 $now = Get-Date -Hour 0 -Minute 00 -Second 00

 echo From $a To $b

 echo ... Getting appointments ...

 $Appointments = $folder.Items
 $Appointments.IncludeRecurrences = $true
 $Appointments.Sort("[Start]")

 echo ... Setting file names ...

 $oldfile = "$env:USERPROFILE\outlook-calendar.bak"
 echo oldfile: $oldfile
 $newfile = "$env:USERPROFILE\outlook-calendar.txt"
 echo newfile: $newfile
 $calfile = "$env:USERPROFILE\outlook-calendar.ics"
 echo calfile: $calfile

 echo ... Exporting calendar to $calfile ...

 $calendarSharing = $folder.GetCalendarExporter()
 $calendarSharing.CalendarDetail = $olCalendarDetail::olFullDetails
 $calendarSharing.IncludeWholeCalendar = $false
 $calendarSharing.IncludeAttachments = $false
 $calendarSharing.IncludePrivateDetails = $true
 $calendarSharing.RestrictToWorkingHours = $false
 $calendarSharing.StartDate = $now.AddDays(-30)
 $calendarSharing.EndDate = $now.AddDays(30)
 echo $calendarSharing
 $calendarSharing.SaveAsICal($calfile)

 echo ... Backing up $newfile into $oldfile ...

 if (!(Test-Path $newfile)) {
  echo "" |Out-File $newfile
 }

 # Backup old export into $oldfile
 if (Test-Path $oldfile) {
  echo "Deleting old backup file $oldfile"
  del $oldfile 
 }
 echo " ... moving $newfile into $oldfile ... "
 move $newfile $oldfile

 echo "... Generating text report to file $newfile ..."

 $Appointments | Where-object { $_.start -gt $now -AND $_.start -lt $now.AddDays(+7) } | 
  Select-Object -Property Subject, Start, Duration, Location, IsRecurring, RecurrenceState  |
  Sort-object Start |
  Out-File $newfile -Width 100

 echo "... Comparing with previous export for changes ..."

 $oldsize = (Get-Item $oldfile).length
 $newsize = (Get-Item $newfile).length

 if ($oldsize -ne $newsize ) {
  echo "!!! Detected calendar change. Sending email..."
  $mail = $outlook.CreateItem(0)

  #2 = high importance email header
  $mail.importance = 2

  $mail.subject = $env:computername + “ Outlook Calendar“

  $mail.Attachments.Add($newfile)
  $mail.Attachments.Add($calfile)
  $text = Get-Content $newfile | Out-String
  $mail.body = “See attached file...“ + $text

  #for multiple email, use semi-colon ; to separate
  $mail.To = “your-email@your-mail-domain.com“

  $mail.Send()

 }
 else {
  echo "No changes detected in Calendar!"
 }


} #end function Get-OutlookCalendar

Function Get-OutlookCalendarTest
{
 echo starting...
 Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null
 $olFolders = "Microsoft.Office.Interop.Outlook.OlDefaultFolders" -as [type]
 $outlook = new-object -comobject outlook.application
 $namespace = $outlook.GetNameSpace("MAPI")
 $folder = $namespace.getDefaultFolder($olFolders::olFolderCalendar)

 $a = Get-Date -Hour 0 -Minute 00 -Second 00
 $b = (Get-Date -Hour 0 -Minute 00 -Second 00).AddDays(7)
 echo From $a To $b

 $Appointments = $folder.Items
 $Appointments.IncludeRecurrences = $true
 $Appointments.Sort("[Start]")

 $Appointments | Where-object { $_.start -gt $a -AND $_.start -lt $b } | Select-Object -Property IsRecurring, RecurrenceState, Subject, Start, Location

} #end function Get-OutlookCalendarTest

这是在模块中调用PowerShell函数的代码:

路径:Documents \ WindowsPowerShell \ mono.ps1

Import-Module -Name Outlook\expcal.psm1 -Force

$i=0

#infinite loop for calling connect function   
while(1)
{
   $i = $i +1
   Write-Output "Running task Get-OutlookCalendar ($i)"
   Get-OutlookCalendar

   start-sleep -seconds 300

}

要运行PowerShell脚本,请使用powershell.exe。要在启动时运行此程序,请在“%APPDATA%\ Microsoft \ Windows \ Start Menu \ Programs \ Startup \”上运行一个快捷方式:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass "C:\Users\%USERNAME%\Documents\WindowsPowerShell\mono.ps1"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.