Gorgsenegger
Gorgsenegger

Reputation: 7856

Retrieve Outlook appointments for other users

I want to query Outlook calendar appointments for the working days of the current week for different users (whose calendars I have access to in Outlook). I get the information for my own calendar, but how/where can I define which other user's calendar information I want to get?

This is what I've got working so far:

Function Get-OutlookCalendar
{
 Add-type -assembly "Microsoft.Office.Interop.Outlook" | out-null
 $olFolders = "Microsoft.Office.Interop.Outlook.OlDefaultFolders" -as [type]
 $outlook = new-object -comobject outlook.application
 $namespace = $outlook.GetNameSpace("MAPI")
 $folder = $namespace.getDefaultFolder($olFolders::olFolderCalendar)

 $Appointments = $folder.Items
 $Appointments.IncludeRecurrences = $true
 $Appointments.Sort("[Start]")

 $Appointments | Where-object { $_.start -gt "10/12/2020" -AND $_.start -lt "10/17/2020" -AND ($_.busystatus -eq 1 -OR $_.busystatus -eq 2) } | Select-Object -Property Subject, Start, BusyStatus   
} #end function Get-OutlookCalendar

Get-OutlookCalendar

Upvotes: 1

Views: 1226

Answers (1)

Doug Maurer
Doug Maurer

Reputation: 8868

I wrote a function to export shared calendars for a user at powershell.org.

It's rather long but for completeness here it is.

Function Export-OutlookSharedCalendar{
    <#
    .Synopsis
    Allows a user to export a shared calendar from their outlook.
    .DESCRIPTION
    Allows a user to export a shared calendar from their outlook.
    .NOTES
    Name: Export-OutlookSharedCalendar.ps1
    Author: Doug Maurer
    Version: 1.0.0.5
    DateCreated: 2020-04-14
    DateUpdated: 2020-04-14
    .LINK
    .INPUTS
    None
    .OUTPUTS
    An ics file of the calendar
    .PARAMETER Owner
    The actual owner of the shared calendar
    .PARAMETER Path
    Full path for the exported file, including the filename.
    .PARAMETER StartDate
    The start date of the desired export period
    .PARAMETER EndDate
    The end date of the desired export period
    .PARAMETER Detail
    The level of calendar detail to export.
    .PARAMETER RestrictToWorkingHours
    Used to restrict the export to working hours
    .PARAMETER IncludePrivateDetails
    Switch for including private details of the calendar items
    .PARAMETER IncludeAttachments
    Switch for including attachments with the calendar items
    .EXAMPLE
    Export-OutlookSharedCalendar -Owner '[email protected]' -Path 'c:\temp\contoso shared calendar.ics' -startdate 01/01/2019 -enddate 09/01/2019 -detail FullDetails -AllowClobber
    Description
    -----------
    Exports specific items from shared calendar owned by [email protected] from the default (or chosen) outlook profile and exports it to 'c:\temp\contoso shared calendar.ics'
    .EXAMPLE
    Export-OutlookSharedCalendar -Owner '[email protected]' -Path 'c:\users\windowsuser\documents\salescalendar.ics' -detail FreeBusyAndSubject -RestrictToWorkingHours

    .EXAMPLE
    Export-OutlookSharedCalendar -CalendarOwner 'John Smith' -FilePath 'G:\HR\Shared\PTO.ics' -Detail FreeBusyAndSubject -IncludePrivateDetails -StartDate 01/01/2017 -EndDate 12/31/2018
    #>
    [cmdletbinding()]
    Param(

        [alias('CalendarOwner')]
        [Parameter(Mandatory=$true)]
        $Owner,

        [alias('Filepath')]
        [Parameter(Mandatory=$true)]
        $Path,

        [datetime]$StartDate,

        [datetime]$EndDate,

        [Parameter()][ValidateSet("FreeBusyOnly","FreeBusyAndSubject","FullDetails")]$Detail = "FreeBusyOnly",

        [switch]$RestrictToWorkingHours = $false,

        [switch]$IncludeAttachments = $false,

        [switch]$IncludePrivateDetails = $false,

        [switch]$AllowClobber = $false

    )

    begin{
        function Quit-Outlook {
            try 
            {
                if($stopoutlook){$outlook.Quit()}
                [void][System.Runtime.InteropServices.Marshal]::ReleaseComObject($outlook)
                [void][System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($outlook)
                [gc]::Collect()
                if($stopoutlook){Get-Process OUTLOOK -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue}
            }
            catch {}
            finally 
            {
                $namespace = $outlook = $Calendarowner = $owner = $CalendarFolder = $recipient = $null
            }
            break
        }

        Function Stop-Function{
            Param($message)
            $Exception = [Exception]::new($message)
            $ErrorRecord = [System.Management.Automation.ErrorRecord]::new(
                $Exception,
                10010,
                [System.Management.Automation.ErrorCategory]::ObjectNotFound,
                $error[0] # usually the object that triggered the error, if possible
            )
            $PSCmdlet.WriteError($ErrorRecord)
            Quit-Outlook
        }
    }

    process{
    
        $ErrorActionPreference = 'stop'

        # make a note if outlook is not running so we can try to close it after
        if(-not [bool](Get-Process -Name outlook -ErrorAction SilentlyContinue)){$stopoutlook = $true}

        # load the required .NET types
        Add-Type -AssemblyName 'Microsoft.Office.Interop.Outlook'

        # access Outlook object model
        try{
            $outlook = New-Object -ComObject outlook.application -ErrorAction Stop
        }
        catch{
            Stop-Function 'Unable to open Outlook'
        }

        # connect to the appropriate location
        try{
            $namespace = $outlook.GetNameSpace('MAPI')
        }
        catch{
            Stop-Function 'Unable to load Outlook profile'
        }

        # prepare some objects (avoids occasional type conversion failure for recipient/calendar)
        $recipient = [Microsoft.Office.Interop.Outlook.Recipient] -as [type]
        $calendarfolder = [Microsoft.Office.Interop.Outlook.MAPIFolder] -as [type]
        $olFolderCalendar = [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderCalendar

        # create a recipient object representing the owner of the shared calendar you want to export
        try{
            $recipient = $namespace.CreateRecipient($owner) # can be the full smtp address (what i prefer), display name, or alias.
            $null = $recipient.Resolve()
        }
        catch{
            Stop-Function "Error with recipient: $($owner)"
        }

        # get the specified user/specified default folder
        try{
            $CalendarFolder = $namespace.GetSharedDefaultFolder($recipient, $olFolderCalendar)
        }
        catch{
            Stop-Function "Error retrieving calendar for $($recipient.name)"
        }

        # Set up the exporter

        try{
            #Set up the exporter
            $calendarsharing = $CalendarFolder.GetCalendarExporter()
        }
        catch{
            Stop-Function 'Unable to create calendar exporter'
        }

        #assign any switches first, because detail may override these settings
        if($RestrictToWorkingHours){$CalendarSharing.RestrictToWorkingHours = $true}
        if($IncludeAttachments){$CalendarSharing.IncludeAttachments = $true}
        if($IncludePrivateDetails){$CalendarSharing.IncludePrivateDetails = $true}

        switch($Detail){
            "FreeBusyOnly" {
                $CalendarSharing.CalendarDetail = 0
                $CalendarSharing.IncludeAttachments = $false
                $CalendarSharing.IncludePrivateDetails = $false
            }
            "FreeBusyAndSubject" {
                $CalendarSharing.CalendarDetail = 1
                $CalendarSharing.IncludeAttachments = $false
                $CalendarSharing.RestrictToWorkingHours = $false
            }
            "FullDetails" {
                $CalendarSharing.CalendarDetail = 2
                $CalendarSharing.RestrictToWorkingHours = $false
            }
        }

        if($startdate){
            $CalendarSharing.startDate = $startdate
            if($enddate){
                $CalendarSharing.endDate = $enddate
            }else{
                $CalendarSharing.endDate = (get-date)
            }
        } else {
            $CalendarSharing.IncludeWholeCalendar = $true
        }

        #export the calendar
        if($pathtest = [bool](Test-Path $Path) -and ($AllowClobber -eq $false)){Write-Warning "File $path already exists and AllowClobber not specified";Quit-Outlook;break}
        if($pathtest){Remove-Item $path -Force}
        try{
            $MailItem = $CalendarSharing.SaveAsICal($Path)
            Get-ChildItem $Path
        }
        catch{
            Stop-Function "Error saving calendar file: $Path"
        }
    }

    end{
        Quit-Outlook
    }
}

You can also download it as a gist here Export-OutlookSharedCalendar

Upvotes: 2

Related Questions