Instantly share code, notes, and snippets.
krzydoug/Export-OutlookSharedCalendar.ps1
Last active Apr 15, 2020
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