Send-OutlookMailMessage with Voting Options

I needed a way to programmatically send emails through Outlook that contained "voting options" ... the little buttons that let the recipients vote yes or no or whatever on a given topic.  So I whipped up a reusable cmdlet right quick.

#
Function Send-OutlookMailMessage
{
    [CmdletBinding()]
    Param([Parameter(Mandatory=$True)][String[]]$To,
          [Parameter(Mandatory=$False)][String]$Subject,
          [Parameter(Mandatory=$False)][String]$Body,
          [Parameter(Mandatory=$False)][String[]]$Attachments,
          [Parameter(Mandatory=$False)][String[]]$VotingOptions,
          [Parameter(Mandatory=$False)][ValidateSet('High','Low','Normal')][String]$Priority = 'Normal',
          [Parameter(Mandatory=$False)][Switch]$BodyAsHTML = $False)

    BEGIN
    {
        Set-StrictMode -Version Latest
        [Bool]$ShouldProcess = $True
        [Bool]$OutlookWasAlreadyRunning = $True

        Try
        {
            Get-Process Outlook -ErrorAction Stop | Out-Null
        }
        Catch
        {
            $OutlookWasAlreadyRunning = $False
        }

        Try
        {
            $Outlook = New-Object -ComObject Outlook.Application -ErrorAction Stop
            If ($Outlook -EQ $Null)
            {
                Throw 'COM Object was null.'
            }
            Write-Verbose -Message 'Outlook COM object loaded.'
        }
        Catch
        {
            Write-Error "Failed to load Outlook! ($($_.Exception.Message))"        
            $ShouldProcess = $False
        }
    }
    PROCESS
    {
        If ($ShouldProcess)
        {
            Try
            {
                $Mail = $Outlook.CreateItem(0)
                If ($Mail -EQ $Null)
                {
                    Throw
                }
                Write-Verbose -Message 'Mail item created.'
            }
            Catch
            {
                Write-Error "Failed to create mail item! ($($_.Exception.Message))"
                $ShouldProcess = $False
                Return
            }

            Foreach ($Recipient In $To)
            {
                Try
                {
                    $Mail.Recipients.Add($Recipient) | Out-Null
                }
                Catch
                {
                    Write-Error "Failed to add recipient $Recipient"
                    $ShouldProcess = $False
                    Return
                }
                Write-Verbose -Message "Added recipient $Recipient"
            }

            If ($Subject.Length -GT 0)
            {
                $Mail.Subject = $Subject
            }
            Else
            {
                Write-Warning 'No email subject was supplied.'
            }
            If ($Body.Length -GT 0)
            {
                If ($BodyAsHTML)
                {
                    $Mail.HTMLBody = $Body
                }
                Else
                {
                    $Mail.Body = $Body
                }
            }
            Else
            {
                Write-Warning 'No email body was supplied.'
            }

            Foreach ($File In $Attachments)
            {
                Try
                {
                    # TODO: Suppress warning dialog box when attempting to send an 'unsafe' attachment?
                    $Mail.Attachments.Add($File) | Out-Null
                }
                Catch
                {
                    Write-Error "Error adding $File as an attachment!"
                    $ShouldProcess = $False
                    Return
                }
            }

            If ($VotingOptions.Count -GT 0)
            {
                $Mail.VotingOptions = $VotingOptions -Join ';'
            }

            Switch ($Priority)
            {
                'High'
                { 
                    $Mail.Importance = 2
                }
                'Low' 
                { 
                    $Mail.Importance = 0
                }
                'Normal' 
                { 
                    $Mail.Importance = 1
                }
                Default 
                { 
                    Write-Error "Debug priority!"
                    $ShouldProcess = $False
                    Return
                }
            }

            $Mail.Send()
        }
    }
    END
    {
        If ($Outlook)
        {
            If (-Not($OutlookWasAlreadyRunning))
            {
                $Outlook.Quit()
            }
            [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Outlook) | Out-Null
        }
    }
}

Send-OutlookMailMessage -To 'ryan@myotherpcisacloud.com' -Subject 'Can you create an Outlook poll via Powershell?' -Body "

Well, can you?

" -VotingOptions 'Yes','No','IDK' -BodyAsHTML

Universal Pause Button

I like to play video games.  I also have a significant other, and she often walks into the room to talk to me while I'm playing a video game.  I would like to pause the game so that I can give her my undivided attention while she's talking to me, but a lot of games (particularly single-player ones) have these "un-pausable" cut scenes or other areas of the game where the normal pause functionality doesn't work.  This annoys both me and her, because I'm supposed to be the computer expert, and it looks like I don't even know how to pause my stupid video game.  So usually what ends up happening is I skip the cut scene and miss the story, or upset my SO by not paying attention to her as well as I should.

So that is why I wrote Universal Pause Button. It's a very simple Windows desktop app that sits in the system tray. Its icon resembles a pause button.  When you hit the actual Pause key (also known as Break) on your keyboard, the program determines which window is currently in the foreground (i.e. your game's window,) and pauses it.  No matter where you are in the game. Even in the middle of one of those pesky cut scenes that would otherwise be un-pausable.  When you press the key again (as long as you haven't since re-focused to another window,) the game will un-pause.

As of v1.0.3 you can now customize the "Pause" key that you want to use. Read the settings.txt file. The program reads the custom pause key from the settings.txt file during startup.

I've currently been testing this with The Witcher 3, and it is working great.  However, your mileage may vary. "Pausing" processes is something that usually only debuggers do, and I can't predict how your game will react to it.  Pausing processes may lead to race conditions among the threads of that process, but like I said, testing has been very positive for me so far.  I've already gotten great value out of the program, as there are lots of cut scenes in The Witcher 3, that I don't want to skip. The main use case for this app is single player games, as pausing your multi-player game will undoubtedly just get you kicked from the session, as if your computer had just crashed or hung. So don't use it in multi-player games.  It also works on applications that are not games at all.

Also, it's open source!  You can find the source on Github here.

If you prefer to just download the (signed) executable, here it is:

UniversalPauseButton.exe (124.3KB)