Here is some info about paging a calendar view: http://stackoverflow.com/questions/11999781/how-to-do-paging-with-exchange-web-services-calendarview
And here is where you d/l the most recent EWS managed API (2.2): http://www.microsoft.com/en-us/download/details.aspx?id=42951 From: [email protected] [mailto:[email protected]] On Behalf Of Michael B. Smith Sent: Thursday, October 23, 2014 9:58 AM To: [email protected] Subject: RE: [Exchange] Re: Powershell help OK. Dealing with calendars is a little odd. A single “view” of a calendar cannot exceed 2 years, nor can it contain more than 1,000 items. The code below supports only that single view. If you want to go back further (or forward further), then you start “paging”, i.e., go a month at a time or a week at a time. You still have that 1,000 item limit to deal with. To open a user’s calendar requires that you have: [a] full control, [b] receive-as, or [c] impersonation privileges. The easiest thing to do is to give yourself (or a service account) receive-as on the relevant mailbox databases. Run this script under that service account. I sanitized this rather quickly from a much larger script. It seems to work for me, but it isn’t my prettiest work. Note that it outputs “objects” so you can search and manipulate the objects as you would expect from any PowerShell solution. Enjoy. param ( [DateTime]$StartDate = ( Get-Date -Year 1970 -Month 1 -Day 1 -Hour 8 -Minute 0 -Second 0 ), [DateTime]$EndDate = ( Get-Date ), [bool]$useDefaultCredentials = $true, [string]$ewsURL = 'https://server2/ews/exchange.asmx' ) Set-StrictMode -Version 2.0 function Connect-EWS { ## Load EWS Managed API Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll" ## Set minimum EWS managed API Version $Version = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2 ## Create Exchange Service Object $script:service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService( $Version ) if( $service -eq $null ) { throw $error[ 0 ] } if( $useDefaultCredentials ) { $script:service.useDefaultCredentials = $true } else { ## FIXME ## $service.Credentials = ???? } ## define a couple of well-known folders $script:wkf_Inbox = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox $script:wkf_Calendar = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar } function Set-myCertificatePolicy { ## Choose to ignore any SSL Warning issues caused by Self Signed Certificates ## Code From http://poshcode.org/624 ## Create a compilation environment $Provider = New-Object Microsoft.CSharp.CSharpCodeProvider $Compiler = $Provider.CreateCompiler() $Params = New-Object System.CodeDom.Compiler.CompilerParameters $Params.GenerateExecutable = $false $Params.GenerateInMemory = $true $Params.IncludeDebugInformation = $false $Params.ReferencedAssemblies.Add( 'System.DLL' ) | Out-Null $TASource = @' namespace Local.CertificatePolicy { public class TrustAll : System.Net.ICertificatePolicy { public TrustAll() { } public bool CheckValidationResult( System.Net.ServicePoint sp, System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Net.WebRequest req, int problem) { return true; } } } '@ $TAResults = $Provider.CompileAssemblyFromSource( $Params, $TASource ) $TAAssembly = $TAResults.CompiledAssembly ## We now create an instance of the TrustAll and attach it to the ServicePointManager $script:TrustAll = $TAAssembly.CreateInstance( 'Local.CertificatePolicy.TrustAll' ) [System.Net.ServicePointManager]::CertificatePolicy = $script:TrustAll ## end code from http://poshcode.org/624 } ## Main Connect-EWS Set-myCertificatePolicy $mailboxes = Get-Mailbox -ResultSize Unlimited ## Get the EWS URL. Use either AutoD or a hardcoded EWS URL if( [String]::IsNullOrEmpty( $ewsURL ) ) { $mailboxSmtp = $mailboxes[ 0 ].PrimarySmtpAddress.ToString() $service.AutodiscoverUrl( $mailboxSmtp, $true ) Write-Host "Using AutoD EWS Server :" $Service.url } else { $uri = [System.URI] $ewsURL $service.Url = $uri Write-Host "Using parameterized EWS server :" $ewsURL } $rptcollection = @() $start = Get-Date $i = 0 foreach( $mailbox in $mailboxes ) { $i += 1 $Duration = ( New-TimeSpan -Start ($start) -End (Get-Date) ).TotalSeconds $TimeLeft = ( $Duration / $i ) * ( $mailboxes.Count - $i ) Write-Progress -Status $mailbox.DisplayName ` -Activity "Mailbox $i of $($mailboxes.Count)" ` -PercentComplete ( $i / $mailboxes.Count * 100 ) ` -SecondsRemaining $timeleft ` -Id 100 ## FIXME - impersonation? or admin perms? I don't care, but decide ## Optional section for Exchange Impersonation ## $service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $Mailbox.PrimarySMTPAddress) $folderid = $null ## clear value (if any) from prior iteration $calendar = $null ## clear value (if any) from prior iteration try { $folderid = New-Object Microsoft.Exchange.WebServices.Data.FolderId( $wkf_Calendar, $mailbox.PrimarySMTPAddress.ToString() ) $calendar = [Microsoft.Exchange.WebServices.Data.Folder]::Bind( $service, $folderid ) } catch { Write-Host "Could not bind to Calendar for" $mailbox.PrimarySMTPAddress.ToString() continue } ##$calendar | fl * -force ##$global:saveCal = $calendar ##$global:saveEWS = $service ##$global:propSet = $calPropSet Write-Host "Bound to Calendar for" $mailbox.PrimarySMTPAddress.ToString() Write-Host ".... total items in Calendar $($calendar.TotalCount)" if( $calendar.TotalCount -eq 0 ) { continue } $calPropSet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet( ` [Microsoft.Exchange.WebServices.Data.BasePropertySet ]::IdOnly, ` [Microsoft.Exchange.WebServices.Data.ItemSchema ]::Subject, ` [Microsoft.Exchange.WebServices.Data.AppointmentSchema]::AppointmentState, ` [Microsoft.Exchange.WebServices.Data.AppointmentSchema]::AppointmentType, ` [Microsoft.Exchange.WebServices.Data.AppointmentSchema]::End, ` [Microsoft.Exchange.WebServices.Data.AppointmentSchema]::Start, ` [Microsoft.Exchange.WebServices.Data.AppointmentSchema]::IsRecurring, ` [Microsoft.Exchange.WebServices.Data.AppointmentSchema]::Location, ` [Microsoft.Exchange.WebServices.Data.AppointmentSchema]::Organizer ) ## [Microsoft.Exchange.WebServices.Data.AppointmentSchema]:: ### a calendar view is limited to two years ### so to look at an entire calendar is a bit of a hassle ### we just examine $EndDate - 730 days worth of data (or up to 1000 calendar items) $StartDate = $EndDate.AddDays( -730 ) $calView = $null $calView = New-Object Microsoft.Exchange.WebServices.Data.CalendarView( $StartDate, $EndDate, 1000 ) $calView.PropertySet = $calPropSet $global:Collection = $null $global:Collection = $calendar.FindAppointments( $calView ) $count = 0 foreach( $appointment in $Collection.Items ) { if( $appointment.IsRecurring -eq $false ) { continue } ##$appointment | ft Subject, IsRecurring, ## AppointmentType, AppointmentState, ## Location, Organizer $count += 1 Write-Progress -Status $mailbox.DisplayName ` -Activity "Mailbox $i of $($mailboxes.Count)" ` -PercentComplete ( $i/ $mailboxes.count * 100 ) ` -SecondsRemaining $timeleft ` -Id 100 ` -CurrentOperation "Processing calendarItem $count of $($Collection.Items.Count)" $obj = "" | Select Subject, ` AppointmentState, AppointmentType, ` Start, End, ` IsRecurring, ` Location, Organizer $obj.Subject = $appointment.Subject $obj.AppointmentState = $appointment.AppointmentState $obj.AppointmentType = $appointment.AppointmentType $obj.Start = $appointment.Start $obj.End = $appointment.End $obj.IsRecurring = $appointment.IsRecurring $obj.Location = $appointment.Location $obj.Organizer = $appointment.Organizer Write-Output $obj } } ## foreach( $mailbox in $mailboxes )
