Skip to content

Instantly share code, notes, and snippets.

@josheinstein
Last active December 16, 2015 01:30
Show Gist options
  • Select an option

  • Save josheinstein/5355916 to your computer and use it in GitHub Desktop.

Select an option

Save josheinstein/5355916 to your computer and use it in GitHub Desktop.
Create temporary rules in Outlook by naming them with " (Until date)" or " (Until date time)" and then run this script at periodic intervals to disable those rules when they expire.
##############################################################################
#.SYNOPSIS
# Scans your Outlook rules (Outlook must be running) and disables any rules
# whose name matches a specific pattern such as:
# Move Stuff (Until 4/10/2013 5:00 PM)
# Ignore Stuff (Until 4/11/2013)
#
#.DESCRIPTION
#
# To create temporary rules in Outlook, just create rules as you would
# normally, but name them such that they end in " (Until date)" or
# " Until (date time)".
#
# The script should be run using the Windows Task scheduler or some other
# mechanism that will periodically run it so that rules will be disabled when
# they are set to expire.
##############################################################################
[CmdletBinding(DefaultParameterSetName='Run', SupportsShouldProcess=$true)]
param(
# When this switch is present, Outlook will be started if it is not
# already running. Otherwise the script will return an error if
# Outlook is not running.
[Parameter(ParameterSetName='Run')]
[Switch]$Force,
# When this switch is present, the job will be scheduled with Windows
# Task Scheduler to run hourly at 5 minutes past the hour.
# Note that no precautions are taken to prevent multiple jobs being
# scheduled so that's on you.
[Parameter(ParameterSetName='Schedule')]
[Switch]$Schedule
)
##############################################################################
# PRIVATE FUNCTIONS
# Get a running COM object from the running object table
function Get-ComObject([String]$ComObject, [Switch]$Force) {
try {
[System.Runtime.InteropServices.Marshal]::GetActiveObject($ComObject)
}
catch [System.Management.Automation.MethodInvocationException] {
if ( $Force ) { New-Object -ComObject $ComObject }
else { Write-Error "An active object of type $ComObject is not available." }
}
}
# Decrement (or zero out if -Force) the reference count of the RCW
function Release-ComObject([Object[]]$Object, [Switch]$Force) {
foreach ($O in $Object) {
if ($O -eq $Null) { continue; }
[Int32]$Remaining = 0
do {
$Remaining = [System.Runtime.InteropServices.Marshal]::ReleaseComObject($O)
} while ($Force -and $Remaining -gt 0)
Write-Verbose "Release COM Object: $Remaining remaining"
}
}
# Pulls off the expiration date from the name of a rule and stores
# it as an extended property on the Rule object
filter ParseExpirationDate {
$Expires = $Null
if ($_.Name -match " \(Until (.*)\)$") {
try {
$Expires = [DateTime]::Parse($Matches[1])
}
catch {
Write-Warning "Couldn't parse $($Matches[1]) as a date. Skipping."
}
}
if ($Expires) {
Add-Member NoteProperty Expires $Expires -InputObject:$_ -PassThru
}
}
# END FUNCTIONS
##############################################################################
switch ($PSCmdlet.ParameterSetName) {
# Scheduling mode registers with Windows Task Schedule to
# run every hour at 5 minutes past the hour
'Schedule' {
Import-Module PSScheduledJob
$JobArgs = @{
Name = Split-Path $MyInvocation.MyCommand.Path -Leaf
FilePath = $MyInvocation.MyCommand.Path
Trigger = @(
@{Frequency='Daily'; At='12:05 AM'; RepetitionInterval='01:00:00'; RepetitionDuration='1.00:00:00'}
)
}
Register-ScheduledJob @JobArgs
}
# Run mode runs the script on demand
# This is the default mode if the -Schedule switch is not provided
'Run' {
# Reserve these in scope so we can safely release
# them later without trouncing on a higher scope
$Outlook = $Null
$OutlookSession = $Null
$OutlookStore = $Null
$OutlookRules = $Null
try {
# Any of these could fail because, well... Outlook. Yeah.
# So the finally block will take care of releasing whatever
# was acquired.
$Outlook = Get-ComObject Outlook.Application -Force:$Force
$OutlookSession = $Outlook.Session
$OutlookStore = $OutlookSession.DefaultStore
$OutlookRules = $OutlookStore.GetRules()
$NeedsSave = $False
$OutlookRules |
ParseExpirationDate |
Where { $_.Enabled } |
Where { $_.Expires -lt [DateTime]::Now } |
ForEach {
# If the -WhatIf switch was used, this will return
# false after writing a message to the host
if ($PSCmdlet.ShouldProcess($_.Name)) {
$_.Enabled = $False
$NeedsSave = $True
Write-Host "Disabled expired rule: $($_.Name)"
}
}
if ($NeedsSave) {
$OutlookRules.Save()
}
}
finally {
# Zeroes out the reference count of the runtime-callable wrappers
Release-ComObject -Force (
$OutlookRules,
$OutlookStore,
$OutlookSession,
$Outlook
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment