Reporting on expired recurring conferences with EWS and Powershell

Reporting on expired recurring conferences with EWS and Powershell Somebody requested an attention-grabbing query about recurring Appointments in Change just lately that I believed I would broaden on a bit with weblog put up. Recurrence in Appointments,Assembly and Duties are one of many extra helpful options of Change, however they’re additionally one the options which might be more durable for builders and anyone writing code or scripts to get a deal with on. Lately there may be some actually good technical documentation on this so I will not clarify an excessive amount of however firstly but in addition the Change Protocol Doc are a should to learn.

To refine this down a bit with Calendar Appointments if in case you have a recurring Appointment you do not have separate objects for every incidence of the recurring Appointment, the recurrence is only a sample saved in a property on what known as the grasp occasion of that exact Appointment, Assembly or Activity. Exception data is saved as a part of the Recurrence sample (whereas the precise information from the Exception if there may be something completely different from the Grasp occasion eg say you add an attachment to an exception this information will get saved as AttachedItem on the Grasp occasion).

What this all means is that when it comes time to really question the Calendar Appointments these recurrence patterns have to be expanded. To do that in EWS you employ the CalendarView class and also you specify a Begin and Finish Date on your question. Change will then do all the exhausting give you the results you want and return the expanded Appointments (and exceptions) to you.

To get again to the precise query nonetheless of the way you would discover expired recurring Calendar Appointments it’s important to overlook about making an enlargement question and as an alternative you wish to make a question to return an inventory of those grasp situations of recurring calendar Appointments after which filter these on the consumer aspect to work out what has expired (or if you wish to do different reporting like seeing who has made non expiring appointments you are able to do this).

So to do that you should use the FindItem operation with a restriction on the PidLidRecurring property which appears like this

  1. $Recurring = new-object Microsoft.Change.WebServices.Information.ExtendedPropertyDefinition([Microsoft.Exchange.WebServices.Data.DefaultExtendedPropertySet]::Appointment, 0x8223,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Boolean);   
  3. $sfItemSearchFilter = new-object Microsoft.Change.WebServices.Information.SearchFilter+IsEqualTo($Recurring,$true)   

It will then return an inventory of Grasp Appointment situations, to get the total particulars of the Recurrence of every appointment it’s worthwhile to do a GetItem on every of the grasp occasion which within the Managed API you should use the LoadPropertiesForItems technique for. It will make a batch GetItem request to the Change Server to return the element on all Gadgets your request it for.

After getting the recurrence data you possibly can then filter these Conferences which have an Finish Date (or Recurrence quantity) set through the use of the HasEnd property.  Then to examine the Final Incidence you should use the LastOccurrence property. If you wish to report on different issues like conferences that do not have an EndDate or conferences which might be expiring within the subsequent week or month that is the place you possibly can put your individual customization.

The next script will produce a report of any expired Conferences in a Mailbox’s calendar and save this to a CSV file. I’ve put a download of this script right here the code itself appears like

  1. ## Get the Mailbox to Entry from the 1st commandline argument  
  3. $MailboxName = $args[0]  
  5. ## Load Managed API dll    
  6. Add-Sort -Path “C:Program FilesMicrosoftExchangeWeb Services2.1Microsoft.Exchange.WebServices.dll”    
  8. ## Set Change Model    
  9. $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Change2010_SP2    
  11. ## Create Change Service Object    
  12. $service = New-Object Microsoft.Change.WebServices.Information.ExchangeService($ExchangeVersion)    
  14. ## Set Credentials to use two choices are availible Option1 to use explict credentials or Choice 2 use the Default (logged On) credentials    
  16. #Credentials Choice 1 utilizing UPN for the home windows Account    
  17. $psCred = Get-Credential    
  18. $creds = New-Object System.Web.NetworkCredential($psCred.UserName.ToString(),$psCred.GetNetworkCredential().password.ToString())    
  19. $service.Credentials = $creds        
  21. #Credentials Choice 2    
  22. #service.UseDefaultCredentials = $true    
  24. ## Select to ignore any SSL Warning points precipitated by Self Signed Certificates    
  26. ## Code From  
  27. ## Create a compilation setting  
  28. $Supplier=New-Object Microsoft.CSharp.CSharpCodeProvider  
  29. $Compiler=$Supplier.CreateCompiler()  
  30. $Params=New-Object System.CodeDom.Compiler.CompilerParameters  
  31. $Params.GenerateExecutable=$False  
  32. $Params.GenerateInMemory=$True  
  33. $Params.IncludeDebugInformation=$False  
  34. $Params.ReferencedAssemblies.Add(“System.DLL”) | Out-Null  
  36. $TASource=@ 
  37.   namespace Native.ToolkitExtensions.Web.CertificatePolicy{ 
  38.     public class TrustAll : System.Web.ICertificatePolicy { 
  39.       public TrustAll() {  
  40.       } 
  41.       public bool CheckValidationResult(System.Web.ServicePoint sp, 
  42.         System.Safety.Cryptography.X509Certificates.X509Certificates cert,  
  43.         System.Web.WebRequest req, int downside) { 
  44.         return true; 
  45.       } 
  46.     } 
  47.   } 
  48. @   
  49. $TAResults=$Supplier.CompileAssemblyFromSource($Params,$TASource)  
  50. $TAAssembly=$TAResults.CompiledAssembly  
  52. ## We now create an occasion of the TrustAll and connect it to the ServicePointManager  
  53. $TrustAll=$TAAssembly.CreateInstance(“Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll”)  
  54. [System.Net.ServicePointManager]::CertificatePolicy=$TrustAll  
  56. ## finish code from  
  58. ## Set the URL of the CAS (Shopper Entry Server) to use two choices are availbe to use Autodiscover to discover the CAS URL or Hardcode the CAS to use    
  60. #CAS URL Choice 1 Autodiscover    
  61. $service.AutodiscoverUrl($MailboxName,{$true})    
  62. “Using CAS Server : “ + $Service.url     
  64. #CAS URL Choice 2 Hardcoded    
  66. #$uri=[system.URI] “https://casservername/ews/exchange.asmx”    
  67. #$service.Url = $uri      
  69. ## Optionally available part for Change Impersonation    
  71. #$service.ImpersonatedUserId = new-object Microsoft.Change.WebServices.Information.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)   
  73. # Bind to the Calendar Folder  
  74. $folderid= new-object Microsoft.Change.WebServices.Information.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar,$MailboxName)     
  75. $Calendar = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)  
  77. $Recurring = new-object Microsoft.Change.WebServices.Information.ExtendedPropertyDefinition([Microsoft.Exchange.WebServices.Data.DefaultExtendedPropertySet]::Appointment, 0x8223,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Boolean);   
  79. $sfItemSearchFilter = new-object Microsoft.Change.WebServices.Information.SearchFilter+IsEqualTo($Recurring,$true)   
  82. #Outline ItemView to retrive simply 1000 Gadgets      
  83. $ivItemView =  New-Object Microsoft.Change.WebServices.Information.ItemView(1000)     
  84. $rptCollection = @()  
  85. $fiItems = $null      
  86. do{   
  87.     $psPropset= new-object Microsoft.Change.WebServices.Information.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)    
  88.     $fiItems = $service.FindItems($Calendar.Id,$sfItemSearchFilter,$ivItemView)     
  89.     if($fiItems.Gadgets.Depend -gt 0){  
  90.         [Void]$service.LoadPropertiesForItems($fiItems,$psPropset)    
  91.         foreach($Merchandise in $fiItems.Gadgets){   
  92.             if($Merchandise.Recurrence.HasEnd){  
  93.                 if($Merchandise.LastOccurrence.Finish -lt (Get-Date)) Choose Mailbox,Organizer,AppointmentSubject,FirstOccuranceStart,FirstOccuranceEnd,LastOccuranceStart,LastOccuranceEnd  
  94.                     Write-Host “Appointment : “  $Merchandise.Topic  
  95.                     Write-Host “Last Occurance : “ $Merchandise.LastOccurrence.Begin  
  96.                     $rptObj.Mailbox = $MailboxName  
  97.                     $rptObj.Organizer = $Merchandise.Organizer.Identify  
  98.                     $rptObj.AppointmentSubject = $Merchandise.Topic  
  99.                     $rptObj.FirstOccuranceStart = $Merchandise.FirstOccurrence.Begin  
  100.                     $rptObj.FirstOccuranceEnd = $Merchandise.FirstOccurrence.Finish  
  101.                     $rptObj.LastOccuranceStart = $Merchandise.LastOccurrence.Begin  
  102.                     $rptObj.LastOccuranceEnd = $Merchandise.LastOccurrence.Finish               
  103.                     $rptCollection += $rptObj  
  105.             }  
  106.         }  
  107.     }  
  108.     $ivItemView.Offset += $fiItems.Gadgets.Depend      
  109. }whereas($fiItems.MoreAvailable -eq $true)   
  110. $rptCollection | Export-Csv -NoTypeInformation -Path c:Temp$MailboxName-ExpiredRecurringMeetings.csv  
  111. Write-Host “Report written to “ c:Temp$MailboxName-ExpiredRecurringMeetings.csv