Skip to content

Instantly share code, notes, and snippets.

@krzydoug
Last active October 19, 2021 12:46
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krzydoug/f624cc7cec81fd006e1230907b74b446 to your computer and use it in GitHub Desktop.
Save krzydoug/f624cc7cec81fd006e1230907b74b446 to your computer and use it in GitHub Desktop.
Export-OutlookSharedCalendar - a powershell function to export shared calendars
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 'first.last@contoso.com' -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 first.last@constoso.com from the default (or chosen) outlook profile and exports it to 'c:\temp\contoso shared calendar.ics'
.EXAMPLE
Export-OutlookSharedCalendar -Owner 'first.last@contoso.com' -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
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment