使用 Exchange Powershell 检索 public 个文件夹日历约会

Retrieve public folder calendar appointments with Exchange Powershell

我正在尝试检索组织的 public 文件夹中日历中的所有约会,以用于报告目的。

Exchange 2010 的 Powershell cmdlet Get-PublicFolderItemStatistics 提供了 return 我需要的一些信息,但 returned 对象似乎缺少一些属性 that should exist on the Appointment object ,尽管我确实在 Outlook 中看到了他们在约会中的价值(也是 2010 年)。

具体来说,我需要开始和结束日期属性,它们返回空白。

一个例子:

Get-PublicFolderItemStatistics -identity " Day" | Sort-Object CreationTime | Format-List

Returns:

ServerName           : EXCHANGE1
DatabaseName         : Public Folder Database 167851469
Subject              : Test 30
PublicFolderName     :  Day
LastModificationTime : 1/19/2015 3:05:05 PM
CreationTime         : 1/19/2015 3:05:05 PM
HasAttachments       : False
ItemType             : IPM.Appointment
MessageSize          : 5.47 KB (5,601 bytes)
Identity             : (removed)
MapiIdentity         : (removed)
OriginatingServer    : exchange1.mydomain.local
IsValid              : True
ObjectState          : Changed

并且:

Get-PublicFolderItemStatistics -identity " Day" | Sort-Object CreationTime | Format-List Subject,CreationTime,Start,End

Returns:

Subject      : Test 30
CreationTime : 1/19/2015 3:05:05 PM
Start        : 
End          : 

但是 Outlook 中的约会正确显示开始和结束时间:

有没有办法从服务器端检索这些信息?我希望尽可能避免 Outlook 互操作。

该 cmdlet 仅 returns 项目属性的有限子集,如果您需要任何其他内容,您将需要使用客户端 API,如 EWS 或 outlook OOM 来访问 Public文件夹和内容。要对文件夹使用客户端 API,您需要拥有该文件夹的权限,然后您可以在 EWS 和 Powershell

中使用类似的东西
## Get the Mailbox to Access from the 1st commandline argument

$MailboxName = $args[0]

## Load Managed API dll  

###CHECK FOR EWS MANAGED API, IF PRESENT IMPORT THE HIGHEST VERSION EWS DLL, ELSE EXIT
$EWSDLL = (($(Get-ItemProperty -ErrorAction SilentlyContinue -Path Registry::$(Get-ChildItem -ErrorAction SilentlyContinue -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Web Services'|Sort-Object Name -Descending| Select-Object -First 1 -ExpandProperty Name)).'Install Directory') + "Microsoft.Exchange.WebServices.dll")
if (Test-Path $EWSDLL)
    {
    Import-Module $EWSDLL
    }
else
    {
    "$(get-date -format yyyyMMddHHmmss):"
    "This script requires the EWS Managed API 1.2 or later."
    "Please download and install the current version of the EWS Managed API from"
    "http://go.microsoft.com/fwlink/?LinkId=255472"
    ""
    "Exiting Script."
    exit
    } 

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

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

## Set Credentials to use two options are availible Option1 to use explict 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.UserName.ToString(),$psCred.GetNetworkCredential().password.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://casservername/ews/exchange.asmx"  
#$service.Url = $uri    

## Optional section for Exchange Impersonation  

#$service.ImpersonatedUserId = new-object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName) 

function FolderIdFromPath{
    param (
            $FolderPath = "$( throw 'Folder Path is a mandatory Parameter' )"
          )
    process{
        ## Find and Bind to Folder based on Path  
        #Define the path to search should be seperated with \  
        $folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::PublicFoldersRoot)   
        $tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)  
        #Split the Search path into an array  
        $fldArray = $FolderPath.Split("\") 
         #Loop through the Split Array and do a Search for each level of folder 
        for ($lint = 1; $lint -lt $fldArray.Length; $lint++) { 
            #Perform search based on the displayname of each folder level 
            $fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1) 
            $SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$fldArray[$lint]) 
            $findFolderResults = $service.FindFolders($tfTargetFolder.Id,$SfSearchFilter,$fvFolderView) 
            if ($findFolderResults.TotalCount -gt 0){ 
                foreach($folder in $findFolderResults.Folders){ 
                    $tfTargetFolder = $folder                
                } 
            } 
            else{ 
                "Error Folder Not Found"  
                return $null
            }     
        }  
        if($tfTargetFolder -ne $null){
            return $tfTargetFolder.Id.UniqueId.ToString()
        }
    }
}
#Example use
$fldId = FolderIdFromPath -FolderPath "\test\calendar"
$SubFolderId =  new-object Microsoft.Exchange.WebServices.Data.FolderId($fldId)
$SubFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$SubFolderId)
if($SubFolder -ne $null){
    #Define ItemView to retrive just 1000 Items    
    $ivItemView =  New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)    
    $fiItems = $null    
    do{    
        $fiItems = $service.FindItems($SubFolder.Id,$ivItemView)    
        #[Void]$service.LoadPropertiesForItems($fiItems,$psPropset)  
        foreach($Item in $fiItems.Items){      
                    $Item.Subject + " " + $Item.Start    
        }    
        $ivItemView.Offset += $fiItems.Items.Count    
    }while($fiItems.MoreAvailable -eq $true) 
}

干杯 格伦