Why I made this?

Opening Outlook in “normal” mode when being offline is frustrating. I am making this script so that I have the liberty to choose which mode to open Outlook in.

Credits

The Script

Save the following code as open-Outlook.ps1, and link it with shortcut. The next time you open Outlook, use the short cut whenever you want to open Outlook

$outlookPath = "C:\Program Files\Microsoft Office\root\Office16\OUTLOOK.EXE"
$outlookRegPath = "HKCU:\Software\Microsoft\Office\16.0\Outlook\Profiles\Outlook\0a0d020000000000c000000000000046"
$outlookRegProp = "00030398"

$online = New-Object System.Management.Automation.Host.ChoiceDescription 'O&nline', 'Open Outlook (online mode)'
$offline = New-Object System.Management.Automation.Host.ChoiceDescription 'O&ffline', 'Open Outlook (offline mode)'

$options = [System.Management.Automation.Host.ChoiceDescription[]]($online, $offline)

$title = 'Open-Outlook.ps1'
$message = 'Which mode do you want to open in?'

Clear-Host

# The $WindowStates hashtable had two entries for 'MAXIMIZE' and 'SHOWMAXIMIZED' with the same value. Since the ValidateSet attribute ensures that only valid strings are used as keys, and the hashtable is used to map these strings to their corresponding integer values, the duplicate entry is unnecessary and has been removed.
# The Set-Alias command was moved to the BEGIN block to keep the alias definition close to the function definition, which is a common practice for better script organization and readability.

function Hide-ConsoleWindow() {
  $ShowWindowAsyncCode = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
  $ShowWindowAsync = Add-Type -MemberDefinition $ShowWindowAsyncCode -name Win32ShowWindowAsync -namespace Win32Functions -PassThru

  $hwnd = (Get-Process -PID $pid).MainWindowHandle
  if ($hwnd -ne [System.IntPtr]::Zero) {
    # When you got HWND of the console window:
    # (It would appear that Windows Console Host is the default terminal application)
    $ShowWindowAsync::ShowWindowAsync($hwnd, 0)
  } else {
    # When you failed to get HWND of the console window:
    # (It would appear that Windows Terminal is the default terminal application)

    # Mark the current console window with a unique string.
    $UniqueWindowTitle = New-Guid
    $Host.UI.RawUI.WindowTitle = $UniqueWindowTitle
    $StringBuilder = New-Object System.Text.StringBuilder 1024

    # Search the process that has the window title generated above.
    $TerminalProcess = (Get-Process | Where-Object { $_.MainWindowTitle -eq $UniqueWindowTitle })
    # Get the window handle of the terminal process.
    # Note that GetConsoleWindow() in Win32 API returns the HWND of
    # powershell.exe itself rather than the terminal process.
    # When you call ShowWindowAsync(HWND, 0) with the HWND from GetConsoleWindow(),
    # the Windows Terminal window will be just minimized rather than hidden.
    $hwnd = $TerminalProcess.MainWindowHandle
    if ($hwnd -ne [System.IntPtr]::Zero) {
      $ShowWindowAsync::ShowWindowAsync($hwnd, 0)
    } else {
      Write-Host "Failed to hide the console window."
    }
  }
}

switch ($host.ui.PromptForChoice($title, $message, $options, 0))
{
    # Open Outlook online mode
    0 {
        Write-Host "Reverting to online mode..."
        Set-ItemProperty $outlookRegPath -name $outlookRegProp -Value ([byte[]](0x02,0x00,0x00,0x00))
        Write-Host "Opening Outlook..."
        start-process $outlookPath
    }

    # Open Outlook offline mode
    1 {
        Write-Host "Setting offline mode..."
        Set-ItemProperty $outlookRegPath -name $outlookRegProp -Value ([byte[]](0x01,0x00,0x00,0x00))
        Hide-ConsoleWindow
        Write-Host "Opening Outlook and wait..."
        start-process $outlookPath -Wait
        Write-Host "Reverting to online mode..."
        Set-ItemProperty $outlookRegPath -name $outlookRegProp -Value ([byte[]](0x02,0x00,0x00,0x00))
    }
}

Last modified: 22 March 2024