Instantly share code, notes, and snippets.
Last active
October 19, 2021 12:46
-
Save krzydoug/f624cc7cec81fd006e1230907b74b446 to your computer and use it in GitHub Desktop.
Export-OutlookSharedCalendar - a powershell function to export shared calendars
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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