Outlook - automatic export and calendar

Hello,

I used outlook 2013. When I export shared calendar (permission as owner) I use:

 

  • Click File > Save Calendar.
  • This will open a window where you will pick where to save the file to your computer, confirm the file name and click More Options.
  • Change the date range so it includes all of the data you would like to export.
  • Change the Detail select to Full Details.
  • Click OK and then Save the file.
Can you please advise me on how to do these operations in powershell? Thank you

 

I’d be more than happy to help you figure it out. I’d need you to post what you’ve tried that’s not working.

I tried this code, but I don’t know load share calendar

Add-Type -AssemblyName microsoft.office.interop.outlook
$olFolders = “Microsoft.Office.Interop.Outlook.OlDefaultFolders” -as [type]
$olCalendarDetail = “Microsoft.Office.Interop.Outlook.olCalendarDetail” -as [type]
$olCalendarMailFormat = “Microsoft.Office.Interop.Outlook.olCalendarMailFormat” -as [type]
$outlook = New-Object -ComObject outlook.application
$namespace = $Outlook.GetNameSpace(“mapi”)
$folder = $namespace.getDefaultFolder($olFolders::olFolderCalendar)
$CalendarSharing=$folder.GetCalendarExporter()
$CalendarSharing.CalendarDetail = $olCalendarDetail::olFreeBusyOnly
$CalendarSharing.startDate = Get-Date
$CalendarSharing.endDate = (Get-Date).addDays(365)
$CalendarSharing.RestrictToWorkingHours = $false
$CalendarSharing.IncludeAttachments = $false
$CalendarSharing.IncludePrivateDetails = $false
$MailItem = $CalendarSharing.SaveAsICal(“calendar.ics”)

Yeah it seems there is information everywhere about getting the DEFAULT calendar… I believe you’ll probably need .GetSharedDefaultFolder() or .OpenSharedItem() but I haven’t had success with it yet. I’ll keep trying as I have time. If you figure it out, please share!

OK it is quite ugly, hopefully someone comes along and updates with a cleaner answer. Here is what I got to work.

Add-Type -assemblyname "microsoft.office.interop.outlook"
$olFolders = “Microsoft.Office.Interop.Outlook.OlDefaultFolders” -as [type]
$olCalendarMailFormat = “Microsoft.Office.Interop.Outlook.olCalendarMailFormat” -as [type]
$outlook = New-Object -ComObject outlook.application
$namespace = $Outlook.GetNameSpace(“mapi”)
$olCalendarNav = $namespace.Application.ActiveExplorer().navigationpane.modules.getnavigationmodule(1)
$sharedcalendars = $olCalendarNav.NavigationGroups.GetDefaultNavigationGroup(2).navigationfolders # 1 = My Calendars, 2 = Shared Calendars, 3 = Other Calendars
$targetcalendar = $sharedcalendars | where-object displayname -like 'target calendar*'
$CalendarSharing = $targetcalendar.Folder.GetCalendarExporter()
$CalendarSharing.CalendarDetail = 2 #You wanted full detail
$CalendarSharing.startDate = (Get-Date).addDays(-365)
$CalendarSharing.endDate = (Get-Date).addDays(-180)
$CalendarSharing.RestrictToWorkingHours = $false
$CalendarSharing.IncludeAttachments = $false
$CalendarSharing.IncludePrivateDetails = $false
$MailItem = $CalendarSharing.SaveAsICal(“c:\temp\calendar.ics”)

 

Take note of the where-object to get the desired shared calendar. You can also target “My Calendars” and “Other Calendars” group as commented. This was really interesting to learn, thanks for asking the question.

 

Something else you should know is if your powershell is running as admin, your outlook should be too. (or closed) I’ve also had some issues in the past trying to do some of these outlook methods with certain versions of office 365 Outlook.

I hope this helps!

Thank you very much. I get error

You cannot call a method on a null-valued expression.

$sharedcalendars = $olCalendarNav.NavigationGroups.GetDefaultNavigationGroup <<<< (2).navigationfolders # 1 = My Calendars, 2 = Shared Calendars, 3 = Other Calendars

  • CategoryInfo : InvalidOperation: (GetDefaultNavigationGroup:String) [], RuntimeException
  • FullyQualifiedErrorId : InvokeMethodOnNull

It seems like $olCalendarNav is empty. Maybe it depends on outlook being open? Did you test with outlook open or closed?

OK yes it definitely depends on outlook being open. I had a feeling the way I was using the activeexplorer, navigation pane, and navigation folders, was all dependent on the outlook window itself. With outlook closed, first thing I had to do is at the $namespace = mapi command I had to choose an outlook profile. Second thing is have the outlook window open. There has got to be another, better way. Are you needing to do this on your own calendar only? Would the requirement to have outlook open make this not acceptable?

I’m tested with outlook open an outlook close, but error stay

I would like to get an ics from shared calendar.

if necessary, I can edit my rights in the shared calendar

OK I am not sure how to attach a file here or if i can, so apologies for how long it is. I wrote a function so you can specify what owner, date range, details that you want. I added a couple of examples that should help you to use it. My only fear is the formatting getting messed up from the forum. I need to get this uploaded to the gallery but I want to do a lot more testing first. I was able to use this to export 3 different shared calendars and i tried many combinations of options.

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.3
DateCreated: 2020-04-08
DateUpdated: 2020-04-08

.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\exporttest.ics' -detail FreeBusyOnly -RestrictToWorkingHours

#>
[cmdletbinding()]
Param(
[alias('CalendarOwner')]
[Parameter(Mandatory=$true)]
$Owner,

[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

)

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

# access Outlook object model
$outlook = New-Object -ComObject outlook.application

# connect to the appropriate location
$namespace = $outlook.GetNameSpace('MAPI')

#create a recipient object representing the owner of the shared calendar you want to export
$calendarowner = $owner # can be the full smtp address (what i prefer), display name, or alias.
$recipient = $namespace.CreateRecipient($calendarowner)
$null = $recipient.Resolve()

#specify the type of folder object we are wanting to work with
$olFolderCalendar = [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderCalendar

#get the specified user/specified default folder
$CalendarFolder = $namespace.GetSharedDefaultFolder($recipient, $olFolderCalendar)

#Set up the exporter
$calendarsharing = $CalendarFolder.GetCalendarExporter()

#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.startDate = [datetime]"01/01/1970"
$CalendarSharing.endDate = (get-date)
}

#export the calendar
if($pathtest = [bool](Test-Path $Path) -and ($AllowClobber -eq $false)){write-error "File $path already exists and AllowClobber not specified";break}
if($pathtest){Remove-Item $path -Force}
$MailItem = $CalendarSharing.SaveAsICal($Path)
}

 

I really hope this helps!

 

Thank you very much for your time willingness and effort, I do not understand why errors are still displayed

obrazek

OK let’s figure this out. Could you run each of these lines one by one and tell me where you get the first error.

 

#fill this out
$owner = “name@email.com
$path = “c:\temp\test.ics”

Add-Type -AssemblyName ‘Microsoft.Office.Interop.Outlook’

$outlook = New-Object -ComObject outlook.application
$namespace = $outlook.GetNameSpace(‘MAPI’)
$calendarowner = $owner # can be the full smtp address (what i prefer), display name, or alias.
$recipient = $namespace.CreateRecipient($calendarowner)
$null = $recipient.Resolve()
$olFolderCalendar = [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderCalendar
$CalendarFolder = $namespace.GetSharedDefaultFolder($recipient, $olFolderCalendar)
$calendarsharing = $CalendarFolder.GetCalendarExporter()

$CalendarSharing.CalendarDetail = 2
$CalendarSharing.IncludeAttachments = $false
$CalendarSharing.IncludePrivateDetails = $false
$CalendarSharing.RestrictToWorkingHours = $false
$CalendarSharing.startDate = (get-date).AddDays(-365)
$CalendarSharing.endDate = (get-date)
$MailItem = $CalendarSharing.SaveAsICal($Path)

first error is

Cannot convert argument “0”, with value: “System.__ComObject”, for “GetSharedDefaultFolder” to type “Microsoft.Office.Interop.Outlook.Recipient”: “Cannot convert the “System.__ComObject” value of type “Syst
em.__ComObject#{00063045-0000-0000-c000-000000000046}” to type “Microsoft.Office.Interop.Outlook.Recipient”.”
At C:\TEMP\test.ps1:13 char:52
+ $CalendarFolder = $namespace.GetSharedDefaultFolder <<<< ($recipient, $olFolderCalendar)
+ CategoryInfo : NotSpecified: (:slight_smile: [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

Ok run these lines and paste the output. Be sure to update the owner email.

$owner = “name@email.com”
$path = “c:\temp\test.ics”

Add-Type -AssemblyName ‘Microsoft.Office.Interop.Outlook’

$outlook = New-Object -ComObject outlook.application
$namespace = $outlook.GetNameSpace(‘MAPI’)
$calendarowner = $owner # can be the full smtp address (what i prefer), display name, or alias.

write-output $owner
$recipient = $namespace.CreateRecipient($calendarowner)
$recipient.Resolve()

output show
first line : mailbox owner
second line: True

I assume by mailbox owner you mean the owner’s email. I’m not sure why it’s saying it can’t convert the com object to recipient. What version of exchange and what version of outlook are you using?

OK give this one a try if you can

#fill this out
$owner = “user@email.com”
$path = “c:\temp\test.ics”
Add-Type -AssemblyName ‘Microsoft.Office.Interop.Outlook’

$outlook = New-Object -ComObject outlook.application
$namespace = $outlook.GetNameSpace(‘MAPI’)
$calendarowner = $owner # can be the full smtp address (what i prefer), display name, or alias.
$recipient = $namespace.CreateRecipient($calendarowner)
$null = $recipient.Resolve()
$olFolderCalendar = [Microsoft.Office.Interop.Outlook.OlDefaultFolders]::olFolderCalendar
$CalendarFolder = $outlook.Session.GetSharedDefaultFolder($recipient, $olFolderCalendar)
$calendarsharing = $CalendarFolder.GetCalendarExporter()
$CalendarSharing.CalendarDetail = 2
$CalendarSharing.IncludeAttachments = $false
$CalendarSharing.IncludePrivateDetails = $false
$CalendarSharing.RestrictToWorkingHours = $false
$CalendarSharing.startDate = (get-date).AddDays(-365)
$CalendarSharing.endDate = (get-date)
$MailItem = $CalendarSharing.SaveAsICal($Path)

 

I have Exchange 2010 and Microsoft Outlook 2013