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:
Outlook-API. Wir verwenden die Standard - Logik , die in MSDN beschrieben wird - eine Art von Artikel [Start], Satz
IncludeRecurrences
zuTrue
und 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 ...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.
Antworten:
Mögliche Ursache:
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"
quelle