Rufen Sie Kalenderelemente (Outlook API, WebDAV) ab, die ein seltsames Verhalten aufweisen

79

Wir schreiben ein MS Outlook Plugin. Um unsere Geschäftslogik zu erfüllen, sollten alle Termine zwischen bestimmten Daten überprüft werden. Beim Abrufen aller Elemente aus Kalendern treten verschiedene Probleme auf. Wir haben zwei Möglichkeiten ausprobiert:

  1. Outlook-API. Wir verwenden die Standard - Logik , die in MSDN beschrieben wird - eine Art von Artikel [Start], Satz IncludeRecurrenceszu Trueund führen Sie die Suche \ Artikel einschränken Abfrage über Kalender wie hier . In unserer Testumgebung funktioniert es einwandfrei. In der Umgebung unseres Kunden: Bei wiederkehrenden Terminen werden Start- und Enddatum auf die entsprechenden Daten eines Haupttermins festgelegt. In einigen Raumkalendern haben wir beispielsweise einen wöchentlichen Termin, der im Januar erstellt wurde. Wenn wir versuchen, alle Artikel im August zu finden, erhalten wir unter anderem vier Artikel dieses wiederkehrenden Termins, deren Start- und Enddatum jedoch auf Januar festgelegt sind . Outlook zeigt jedoch korrekte Daten im selben Kalender an ...

  2. Sehr schlecht, aber wir haben immer noch WebDAV! Wir schreiben eine einfache Testanwendung und versuchen, alle Elemente aus dem Kalender mit WebDAV abzufragen. Natürlich haben wir das Rad nicht neu erfunden und nur den Code aus der Dokumentation eingefügt . Das vorherige Problem ist gelöst, aber das nächste tritt auf: Es werden keine wiederkehrenden Elemente zurückgegeben, die vor mehr als ungefähr sechs Monaten erstellt wurden. Ich habe keine Ahnung - es gibt keine Parameter, die 'alte' Gegenstände einschränken!

Was ist falsch? Vermissen wir etwas Wichtiges?

Technische Details: Exchange 2003, Outlook 2003-2010. Ehrlich gesagt verschwindet der erste Fehler, wenn wir den zwischengespeicherten Exchange-Modus aktivieren, aber das können wir nicht.

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();
}

UPDATE 1:

Zusätzliche Untersuchungen mit OutlookSpy zeigen, dass das Problem nicht in unserem Code enthalten ist. Die Start- / Enddaten in der API sind falsch, wenn der Exchange-Cache-Modus deaktiviert ist. Aber Outlook-Entwickler waren sich dessen bewusst und zeigen irgendwie korrekte Daten in Kalendern an! Weiß jemand wie?

UPDATE 2:

Antwort von Outlook Support Escalation Engineer:

Auf dieser Grundlage kann ich bestätigen, dass dies ein Problem in unserem Produkt ist.

Bolick
quelle
3
1. Wie lautet Ihr Code? 2. Verwenden Sie WebDAV nicht. es ist veraltet.
Dmitry Streblechenko
Sieht vollkommen gut aus ... Wie lautet Ihr Code, der auf den Termin zugreift? Greifen Sie jemals auf AppointmentItem.Parent zu (wodurch Sie den Haupttermin für eine Instanz einer wiederkehrenden Aktivität erhalten)?
Dmitry Streblechenko
Ich habe den obigen Code aktualisiert. Nein, wir verwenden AppointmentItem.Parent nicht. Bevor wir auf Start- und Enddaten zugreifen, greifen wir auf die Eigenschaften Subject, ResponseStatus und MeetingStatus von AppointmentItem zu.
Bolick
Zum einen verwendet Outlook OOM nicht, um den Inhalt des Kalenderordners anzuzeigen, zum anderen, warum sind die Start- / Enddaten Ihrer Meinung nach falsch? Was genau ist falsch?
Dmitry Streblechenko
Genau: OutlookSpy zeigt uns mehrere Termine mit derselben Startzeit, in unserem Fall = 01.11.2012, und dies ist definitiv der Haupttermin für wiederkehrende wöchentliche Aktivitäten (derselbe Organisator, das gleiche Thema usw.). Aber im Kalender sehen wir das richtige Bild - ein Artikel pro Woche. Ich würde mich sehr freuen, wenn Sie erklären könnten, wie Outlook funktioniert, mit welcher Technologie der Kalender angezeigt wird, warum wir in OOM falsche Ergebnisse erzielen und wie diese Fehler behoben werden können.
Bolick

Antworten:

1

Mögliche Ursache:

  • Sortieren nach dem Festlegen von IncludeRecurrences.

Hier ist mein Code eines PowerShell-Moduls, das Outlook-Elemente zwischen zwei Daten abruft.

Und ein kleines Applet, mit dem Sie nach Änderungen suchen und eine E-Mail mit den Agenda-Updates senden können. Dies ist praktisch, wenn Sie keinen mobilen Zugriff auf Exchange haben.

Pfad: Dokumente \ WindowsPowerShell \ Module \ 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 = “[email protected]“

  $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

Dies ist der Code zum Aufrufen der PowerShell-Funktion im Modul:

Pfad: Dokumente \ 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

}

Verwenden Sie Powershell.exe, um das PowerShell-Skript auszuführen. Um dies beim Start auszuführen, klicken Sie auf "% APPDATA% \ Microsoft \ Windows \ Startmenü \ Programme \ Startup \":

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass "C:\Users\%USERNAME%\Documents\WindowsPowerShell\mono.ps1"
Jose Manuel Gomez Alvarez
quelle