Thursday, March 08, 2012

How To Series Sample 4 : Reporting on Items of a certain Type

This is the forth of my samples based on the EWS Managed API and Powershell how to series this script shows a method you can use to produce a report of all the Items within a Mailbox based on one particular Item type. Eg if you want to show the size and number of Items for a custom Message class eg "IPM.Note.Myclass" or a another third party item type like IPM.Note.EnterpriseVault.ShortCut etc.

This script first gets all the folders within a mailbox then gets all the Items of a particular ItemClass using a Searchfilter. Its then adds the number of Items and their size and produces a final CSV type report at the end showing the FolderPath and number and size details.

I've put a download of this script here the code looks like

  1. ## Load Managed API dll  
  2. Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll"  
  3.   
  4. ## Set Exchange Version  
  5. $ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1  
  6.   
  7. ## Create Exchange Service Object  
  8. $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)  
  9.   
  10. ## Set Credentials to use two options are availible Option1 to use explict credentials or Option 2 use the Default (logged On) credentials  
  11.   
  12. #Credentials Option 1 using UPN for the windows Account  
  13. $creds = New-Object System.Net.NetworkCredential("user@domain.com","password")   
  14. $service.Credentials = $creds      
  15.   
  16. #Credentials Option 2  
  17. #service.UseDefaultCredentials = $true  
  18.   
  19. ## Choose to ignore any SSL Warning issues caused by Self Signed Certificates  
  20.   
  21. [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}  
  22.   
  23. ## Set the URL of the CAS (Client Access Server) to use two options are availbe to use Autodiscover to find the CAS URL or Hardcode the CAS to use  
  24.   
  25. $MailboxName = "user@domain.com"  
  26. #CAS URL Option 1 Autodiscover  
  27. $service.AutodiscoverUrl($MailboxName,{$true})  
  28. "Using CAS Server : " + $Service.url   
  29. $rptCollection = @()  
  30.   
  31. #Define ItemType  
  32. $ItemType = "IPM.Note.Exchange.ActiveSync.MailboxLog"  
  33.   
  34. $fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1000)  
  35. $fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep  
  36. $folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)   
  37.   
  38. $tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)  
  39.   
  40. $sfItemSearchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass,$ItemType)  
  41.   
  42. $PR_Folder_Path = new-object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(26293, [Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String);    
  43.   
  44. $pfPropSet =  new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)   
  45. $fvFolderView.PropertySet = $pfPropSet  
  46. $fvFolderView.PropertySet.Add($PR_Folder_Path)  
  47.   
  48. #Define Function to convert String to FolderPath    
  49. function ConvertToString($ipInputString){    
  50.     $Val1Text = ""    
  51.     for ($clInt=0;$clInt -lt $ipInputString.length;$clInt++){    
  52.             $Val1Text = $Val1Text + [Convert]::ToString([Convert]::ToChar([Convert]::ToInt32($ipInputString.Substring($clInt,2),16)))    
  53.             $clInt++    
  54.     }    
  55.     return $Val1Text    
  56. }    
  57.   
  58. $findFolderResults = $null  
  59. do{  
  60.     $findFolderResults = $tfTargetFolder.FindFolders($fvFolderView)  
  61.     foreach($folder in $findFolderResults.Folders){  
  62.             "Processing Folder " + $folder.DisplayName  
  63.             $foldpathval = $null    
  64.             #Try to get the FolderPath Value and then covert it to a usable String     
  65.             if ($folder.TryGetProperty($PR_Folder_Path,[ref] $foldpathval))    
  66.             {    
  67.                 $binarry = [Text.Encoding]::UTF8.GetBytes($foldpathval)    
  68.                 $hexArr = $binarry | ForEach-Object { $_.ToString("X2") }    
  69.                 $hexString = $hexArr -join ''    
  70.                 $hexString = $hexString.Replace("FEFF""5C00")    
  71.                 $fpath = ConvertToString($hexString)    
  72.             }    
  73.             $ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)  
  74.             $rptObj = "" | select FolderPath,NumberofItems,SizeofItems  
  75.             $rptObj.NumberofItems = 0  
  76.             $rptObj.FolderPath = $fpath  
  77.             $findItemsResults = $null  
  78.             do{  
  79.                 $findItemsResults = $folder.FindItems($sfItemSearchFilter,$ivItemView)  
  80.                 foreach($itItem in $findItemsResults.Items){  
  81.                     $rptObj.NumberofItems += 1  
  82.                     $rptObj.SizeofItems += [INT32]$itItem.Size  
  83.                 }  
  84.                 $ivItemView.offset += $findItemsResults.Items.Count  
  85.             }while($findItemsResults.MoreAvailable -eq $true)  
  86.             if($rptObj.NumberofItems -gt 0){  
  87.                 $rptCollection += $rptObj  
  88.             }  
  89.         }  
  90.     $fvFolderView.offset += $findFolderResults.Folders.Count  
  91. }while($findFolderResults.MoreAvailable -eq $true)  
  92. $rptCollection  
  93. $rptCollection | Export-Csv -NoTypeInformation c:\mbItemTypeReport.csv  


1 comment:

Ondrej Ĺ ebela said...

Hi,
I see that you offer posibility to connect to manually enter CAS URL. But is there any easy and quick way to tell, that this URL is ok (isnt changed from last time when I checked it? For saving time i Want to use hard coded URL instead of autodiscover, but I want use autodiscover when the connection failed.