How to use Windows System.Speech for TTS in PowerShell 7 (or is there an alternative)


I have the same profile.ps1 in both WindowsPowerShell and PowerShell. It includes commands that invoke Windows Text-To-Speech However, these commands fail when run in PowerShell 7.

The errors occur when I try to use the $PomrptTTS object I create with the following code:

Add-Type -AssemblyName System.speech
$PromptTTS = New-Object System.Speech.Synthesis.SpeechSynthesizer

In PowerShell 7, any attempt to access or use my $PormptTTS object, produces the following:

SetValueInvocationException: ....\profile.ps1:82
Line |
  82 |  $PromptTTS.Rate = 0 ; $PromptTTS.Speak("Time for the $((Get-Date).DayofWeek) shuffle")
     |  ~~~~~~~~~~~~~~~~~~~
     | Exception setting "Rate": "Object reference not set to an instance of an object."

MethodInvocationException: ....\profile.ps1:82
Line |
  82 |  … e = 0 ; $PromptTTS.Speak("Time for the $((Get-Date).DayofWeek) shuffle")
     |                                             ~~~~~~~~~~~~~~~~~~~~
     | Exception calling "Speak" with "1" argument(s): "Object reference not set to an instance of an object."

As of PowerShell 7.0 / .NET Core 3.1, System.Speech.Synthesis.SpeechSynthesizer is considered a .NET Framework-only API and therefore not supported in .NET Core.

  • A discussion about this is ongoing in this GitHub issue; since the underlying API is specific to Windows, the question is whether it's worth exposing via the cross-platform .NET Core framework.

The workaround is to use the SAPI.SpVoice COM object (which the .NET Framework API is ultimately based on, I presume):

$sp = New-Object -ComObject SAPI.SpVoice
$sp.Speak("Time for the $((Get-Date).DayOfWeek) shuffle")

A related question asks about changing the speaking voice, which, unfortunately doesn't seem to be supported in PowerShell Core as of PowerShell 7.0, due to limited COM support - see this answer.