SELECT SamAccountName,DisplayName,InPolicy,OutOfPolicy,TotalDuration,BookableTime,BookedPercentage
FROM OpenExchangePSQuery(
    POWERSHELL, '
    param
(


[DateTime]$StartDate = (Get-Date).addDays(-30),
[DateTime]$EndDate = (Get-date)


)


$Mailboxes = Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails RoomMailbox #| select -First 10



$rptcollection = @()


## Load Managed API dll  
Add-Type -Path "C:\Program Files\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll"


## Set Exchange Version  
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP1


## Create Exchange Service Object  
$service = New-Object    Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion)


## Set Credentials to use two options are available Option1 to use explicit credentials or Option 2 use the Default (logged On) credentials


#Credentials Option 1 using UPN for the windows Account  
#$psCred = Get-Credential


#$creds = New-Object    System.Net.NetworkCredential($psCred.GetNetworkCredential().username.ToString(),#$psCred.GetNetworkCredential().password.ToString(),$psCred.GetNetworkCredential().domain.ToString())  
#$service.Credentials = $creds


 
#Credentials Option 2  
$service.UseDefaultCredentials = $true


## 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.ToolkitExtensions.Net.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
$TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
[System.Net.ServicePointManager]::CertificatePolicy=$TrustAll


## end code from http://poshcode.org/624


## 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


#CAS URL Option 1 Autodiscover  
#$service.AutodiscoverUrl($MailboxName,{$true})  
#"Using CAS Server : " + $Service.url 


#CAS URL Option 2 Hardcoded


$uri=[system.URI] "https://enow-mail3.enowzone.ad/ews/exchange.asmx"  
$service.Url = $uri


$obj = @{}
$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



$WorkingDays = ($Mailbox | Get-mailboxCalendarConfiguration).WorkDays.ToString()
$WorkingHoursStartTime = ($Mailbox |    Get-mailboxCalendarConfiguration).WorkingHoursStartTime
$WorkingHoursEndTime = ($Mailbox | Get-mailboxCalendarConfiguration).WorkingHoursEndTime


if($WorkingDays -eq "Weekdays"){$WorkingDays = "Monday,Tuesday,Wednesday,Thursday,Friday"}
if($WorkingDays -eq "AllDays"){$WorkingDays = "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday"}
if($WorkingDays -eq "WeekEndDays"){$WorkingDays = "Saturday,Sunday"}


## Optional section for Exchange Impersonation  
$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $Mailbox.PrimarySMTPAddress)


$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Calendar,$Mailbox.PrimarySMTPAddress.tostring())  
$Calendar = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service,$folderid)


if($Calendar.TotalCount -gt 0){
    $cvCalendarview = new-object    Microsoft.Exchange.WebServices.Data.CalendarView($StartDate,$EndDate,2000)
$cvCalendarview.PropertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)


$frCalendarResult = $Calendar.FindAppointments($cvCalendarview)
$inPolicy = New-TimeSpan
$OutOfPolicy = New-TimeSpan
$TotalDuration = New-timespan
$BookableTime = New-TimeSpan
$c = 0
foreach ($apApointment in $frCalendarResult.Items){
     $c +=1
     Write-Progress -Status "$($Mailbox.DisplayName)" -Activity "Mailbox $i of $($Mailboxes.Count)" -PercentComplete ($i/$($mailboxes.count)*100) -SecondsRemaining $timeleft -Id 100 -CurrentOperation "Processing calendarItem $c or $($frCalendarResult.Items.count)"
     $psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
     $apApointment.load($psPropset)
     if($apApointment.IsAllDayEvent -eq $false)
     {         if($apApointment.Duration)
         {
                if($WorkingDays.split(",") -contains ($apApointment.start).dayofweek)
                {
                    $TotalDuration = $TotalDuration.add((new-timespan -End $apApointment.End.tolongTimeString() -start $apApointment.start.tolongTimeString()))                    #Only count to inPolicy if within the workinghours time
                    if($apApointment.start.tolongTimeString() -lt $WorkingHoursStartTime)
                    {  
                        $tStart = $WorkingHoursStartTime.ToString()
                    }  
                    else
                    {
                        $tStart = $apApointment.start.ToLongTimeString()
                    }                    if($apApointment.End.tolongTimeString() -gt $WorkingHoursEndTime)
                    {  
                        $tEnd = $WorkingHoursEndTime.ToString()
                    }  
                    else
                    {
                        $tEnd = $apApointment.End.ToLongTimeString()


                    }


                    $Duration = New-TimeSpan -Start $tStart -End $tEnd
                    $inPolicy = $inPolicy.add($Duration)
                }
            }
     }


}


#Calculate to total hours of bookable time between the 2 dates
for ($d=$Startdate;$d -le $Enddate;$d=$d.AddDays(1)){
  if ($WorkingDays.split(",") -contains $d.DayOfWeek)
  {
    $BookableTime += $WorkingHoursEndTime - $WorkingHoursStartTime


  }
  } #for


#Save result....
$rptobj = "" | Select samAccountName,DisplayName,inPolicy,OutOfPolicy,TotalDuration,BookableTime,BookedPercentage
$rptobj.samAccountName = $Mailbox.samAccountName
$rptobj.DisplayName = $Mailbox.DisplayName
$rptobj.inPolicy =  '{0:f2}' -f ($inPolicy.TotalHours)
$rptobj.OutOfPolicy =  '{0:f2}' -f (($TotalDuration - $inPolicy).TotalHours)
$rptobj.TotalDuration =  '{0:f2}' -f ($TotalDuration.TotalHours)
$rptobj.BookableTime =  '{0:f2}' -f ($BookableTime.TotalHours)
$rptobj.BookedPercentage =  '{0:f2}' -f (($inPolicy.TotalHours / $BookableTime.TotalHours) * 100)
$rptcollection += $rptobj


} #ForEach
}


$rptcollection



              ', POWERSHELL
)