비정상적인 동작을 표시하는 일정 항목 (Outlook API, WebDAV) 검색


79

MS Outlook 플러그인을 작성하고 있습니다. 비즈니스 로직을 만족 시키려면 일부 날짜 사이의 모든 약속을 확인해야합니다. 달력에서 모든 항목을 검색하는 데 몇 가지 문제가 발생했습니다. 두 가지 옵션을 시도했습니다.

  1. Outlook API. [시작]을 기준으로 정렬 항목, 세트 - 우리는 표준 MSDN에 설명되어있는 논리를 사용 IncludeRecurrencesTrue와 항목이 달력을 통해 쿼리 제한 \ 찾기를 실행 여기에 좋아 . 테스트 환경에서 잘 작동합니다. 그러나 고객 환경에서 : 되풀이 약속의 경우 시작 및 종료 날짜가 '마스터 약속'의 해당 날짜로 설정됩니다. 예를 들어, 어떤 방의 달력에는 1 월에 생성 된 주간 약속이 있고 8 월에 모든 항목을 찾으려고하면이 반복 약속의 4 개 항목이 있지만 시작 및 종료 날짜는 1 월로 설정됩니다. . 하지만 Outlook은 동일한 캘린더에 정확한 날짜를 표시합니다.

  2. 매우 나쁘지만 여전히 WebDAV가 있습니다! 간단한 테스트 응용 프로그램을 작성하고 WebDAV를 사용하여 달력의 모든 항목을 쿼리합니다. 물론 우리는 바퀴를 재발 명하지 않고 문서 에서 코드를 붙여 넣었습니다 . 이전 문제는 해결되었지만 다음 문제가 발생합니다. 약 6 개월 전에 생성 된 되풀이 항목을 반환하지 않습니다. 단서가 없습니다. '오래된'항목을 제한하는 매개 변수가 없습니다!

뭐가 잘못 되었 니? 중요한 것을 놓치고 있습니까?

기술 세부 정보 : 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를 사용하지 마십시오. 더 이상 사용되지 않습니다.
드미트리 Streblechenko

완벽 해 보입니다 ... 약속에 액세스하는 코드는 무엇입니까? AppointmentItem.Parent (반복 활동 인스턴스에 대한 마스터 약속을 제공함)에 액세스 한 적이 있습니까?
Dmitry Streblechenko

위의 코드를 업데이트했습니다. 아니요, AppointmentItem.Parent를 사용하지 않습니다. 어쨌든 시작 및 종료 날짜에 액세스하기 전에 AppointmentItem의 Subject, ResponseStatus 및 MeetingStatus 속성에만 액세스합니다.
Bolick 2012-08-29

우선 Outlook은 OOM을 사용하여 일정 폴더 내용을 표시하지 않습니다. 둘째, 시작 / 종료 날짜가 잘못되었다고 생각하는 이유는 무엇입니까? 정확히 무엇이 잘못 되었습니까?
Dmitry Streblechenko 2012-08-29

정확함 : OutlookSpy는 동일한 StartTime (이 경우 = 2012 년 11 월 1 일)으로 여러 약속을 표시하며 이는 확실히 반복되는 주간 활동 (동일한 주최자, 동일한 주제 등)의 마스터 약속입니다. 그러나 달력에서는 매주 한 항목 씩 정확한 그림을 볼 수 있습니다. Outlook의 작동 방식, 일정을 표시하는 데 사용하는 기술, OOM에서 잘못된 결과가 나오는 이유 및 이러한 오류를 수정하는 방법에 대해 설명해 주시면 감사하겠습니다.
Bolick 2012-08-29

답변:


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"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.