setup - outlook caldav synchronizer mac
Recuperar elementos de calendario(API de Outlook, WebDAV) mostrando un comportamiento extraño (1)
Estamos escribiendo un plugin de MS Outlook. Para satisfacer nuestra lógica comercial, debe verificar todas las citas entre algunas fechas. Estamos experimentando varios problemas al recuperar todos los elementos de los calendarios. Probamos dos opciones:
API de Outlook. Usamos la lógica estándar que se describe en MSDN: ordena los elementos por [Inicio], establece
IncludeRecurrences
enTrue
y ejecuta la consulta Buscar / Restringir sobre los elementos del calendario como aquí . Funciona bien en nuestro entorno de prueba. Sin embargo, en el entorno de nuestro cliente: para citas periódicas, las fechas de inicio y finalización se establecen en las fechas correspondientes de una "cita maestra". Por ejemplo, en el calendario de algunas habitaciones tenemos una cita semanal que se creó en enero, y si tratamos de encontrar todos los artículos en agosto, obtenemos entre otros cuatro elementos de esta cita recurrente, pero sus fechas de inicio y finalización se establecen en enero. . Pero Outlook muestra las fechas correctas en el mismo calendario ...¡Muy mal, pero todavía tenemos WebDAV! Escribimos una aplicación de prueba simple e intentamos consultar todos los elementos del calendario usando WebDAV. Por supuesto, no reinventamos la rueda y simplemente pegamos el código de la documentation . El problema anterior está resuelto, pero surge el siguiente: no devuelve elementos recurrentes que se crearon hace más de aproximadamente seis meses. No tengo ni idea - ¡no hay parámetros que restrinjan artículos ''viejos''!
¿Qué está mal? ¿Nos estamos perdiendo algo importante?
Detalles técnicos: Exchange 2003, Outlook 2003-2010. Hablando francamente, el primer error desaparece si activamos el modo de intercambio en caché, pero no podemos hacer eso.
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();
}
ACTUALIZACIÓN 1:
Investigaciones adicionales utilizando OutlookSpy muestran que el problema no está en nuestro código: las fechas de Inicio / Fin son incorrectas dentro de la API cuando el Modo de intercambio en caché está desactivado. ¡Pero los desarrolladores de Outlook lo sabían y de alguna manera muestran las fechas correctas en los calendarios! ¿Alguien sabe cómo?
ACTUALIZACIÓN 2:
Respuesta del ingeniero de escalación de soporte de Outlook:
En base a esto, puedo confirmar que este es un problema en nuestro producto.
Causa posible:
- Ordenar después de establecer IncluirRecurrencias.
Aquí está mi código de un módulo de PowerShell que recupera elementos de Outlook entre dos fechas.
Y un pequeño applet para verificar los cambios y enviar un correo electrónico que incluya las actualizaciones de la agenda, que es útil cuando no tiene acceso móvil a Exchange.
Ruta de acceso : Documentos / 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 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 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
Este es el código para invocar la función de PowerShell en el módulo:
Ruta de acceso : Documentos / 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
}
Para ejecutar el script de PowerShell, use powershell.exe. Para ejecutar esto al inicio, un acceso directo en "% APPDATA% / Microsoft / Windows / Start Menu / Programs / Startup /":
C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -ExecutionPolicy Bypass "C:/Users/Jose/Documents/WindowsPowerShell/mono.ps1"