Author Posts

May 12, 2013 at 7:18 am

Hi,
I am trying to do some voice recognition via Powershell. – Just to play a bit. I have already found some information about this with help of google. But the most source code is in C#.
My Problem is the following. In C# the event handler is attached like the following:

1
2

`speechRecognitionEngine.SpeechRecognized += `
`  "new` `EventHandler(engine_SpeechRecognized);`

How can I do this in Powershell? I've tried to do the following:

1
2

`$handler` `= "[System.EventHandler[System.Speech.Recognition.SpeechDetectedEventArgs]]"(engine_SpeechRecognized)`
`$speechRecognitionEngine".SpeechRecognized += "$handler`

But this doesn't work. It tells me "Property 'SpeechRecognized' cannot be found on this object; Make sure it exists and is settable."

For additional Information:

– $SpeechRecognitionEngine is a object of type System.Speech.Recognition.SpeechRecognitionEngine
– engine_SpeechRecognized is a function doing something ( in easiest way to write-host "SpeechRecognzed" ).

I know about Add-Type command and that I can use C# Code within powershell with it. But that is not what I want.

Thank you for your help
mk.maddin

EDIT: Sorry didn't know about the new forum. This is why I posted on both.

May 12, 2013 at 8:57 am

Have you tried Register-ObjectEvent?

Something like:

$speechRecognition = New-Object System.Speech.Recognition.SpeechRecognitionEngine

Register-ObjectEvent -InputObject $speechRecognition -EventName SpeechRecognized -Action { Write-Host "SpeechRecognized" }

May 12, 2013 at 9:04 am

Perfect.
This was exactly what I was looking for 🙂
I didn't know the cmdlet Register-ObjectEvent.

But how can I now decide what was recognized? In c# there is something like "object sender".
I already tried with $sender or $this ... but they are empty 🙁

Thank you again.

May 12, 2013 at 9:59 am

Hi Martin,

To access an event's arguments, use the $EventArgs.SourceArgs built-in variable. $Sender contains the object that generated the event, not it's arguments. For more info on the built-in event variables, check out `Get-Help about_Automatic_Variables`.

As an example, say I wanted to access the SignalTime argument passed to the Elapsed event in a Timer object. I would so the following:

$Timer = New-Object Timers.Timer
$Timer.Interval = 1000

$ElapsedAction = { Write-Host ($Event.SourceArgs.SignalTime) }

Register-ObjectEvent -InputObject $Timer `
                     -EventName Elapsed `
                     -SourceIdentifier TimerAction `
                     -Action $ElapsedAction

$Timer.Enabled = $True

 

May 12, 2013 at 10:22 am

[Reflection.Assembly]::LoadWithPartialName("System.Speech") | Out-Null
[Reflection.Assembly]::LoadWithPartialName("System.Globalization") | Out-Null

#Show aviable languages
#[System.Speech.Recognition.SpeechRecognitionEngine]::InstalledRecognizers()

$Aktion ={
         Write-Host "Erkannt" 
         Write-host "---------"
         Write-Host "Sender:  " $Sender
         Write-Host "Event:   " $Event
         Write-host "EventArg:" $EventArg
         Write-host "---------"
         }

$CultureInfo = New-Object System.Globalization.CultureInfo("en-US")
$SpeechRecognitionEngine = New-Object System.Speech.Recognition.SpeechRecognitionEngine($CultureInfo)

$Texts = New-Object System.Speech.Recognition.Choices
$Texts.Add("Test")
$Texts.Add("Bla")
$Texts.Add("Hello")

$GrammarBuilder = New-Object System.Speech.Recognition.GrammarBuilder($Texts)
$WordsList = New-Object System.Speech.Recognition.Grammar($GrammarBuilder)
$SpeechRecognitionEngine.SetInputToDefaultAudioDevice()
$SpeechRecognitionEngine.LoadGrammarAsync($WordsList)

# attache an event handler
Unregister-Event "SpeechModuleCommandRecognized" -ErrorAction SilentlyContinue
#-->Olny for known commands in $WordList
#Register-ObjectEvent $WordsList SpeechRecognized -SourceIdentifier "SpeechModuleCommandRecognized" -Action { engine_SpeechRecognized $this } | Out-Null

#-->for ALL commands 
Register-ObjectEvent $SpeechRecognitionEngine SpeechRecognized -SourceIdentifier "SpeechModuleCommandRecognized" -Action {. $Aktion} | Out-Null

# start recognition
$RecognizeMode = New-Object System.Speech.Recognition.RecognizeMode
$RecognizeMode.value__ = 1 # 0=Signle; 1=Multiple

$SpeechRecognitionEngine.EmulateRecognize("bla") | Out-Null
#$SpeechRecognitionEngine.RecognizeAsync($RecognizeMode)

 

 

Thank you for your support.
All these variables are empty at mine.

Here is the whole source code:

 

 

May 12, 2013 at 10:33 am

I'm guessing that you're seeing the quotes in Write-Host print but not the objects themselves, right? If that's what you're running into, then you're dealing with one of the quirks of PowerShell eventing. If you insist on calling Write-Host on an object, you have to call its ToString() method. To validate that $Event is actually being returned, save it to a global variable ($Global:Foo = $Event) and then access it.

May 12, 2013 at 10:58 am

         Write-Host "Erkannt" 
         Write-host "---------"
         Write-Host "Sender:  " 
         $global:a = $Sender
         Write-Host "Event:   " 
         $global:b = $Event
         Write-host "EventArg:" 
         $global:c = $EventArg
         Write-host "---------"

But the variables $global:a , b and c are all empty 🙁

I did the following:

 

May 12, 2013 at 11:40 am

I modified your example slightly to show a working example:

[Reflection.Assembly]::LoadWithPartialName("System.Speech") | Out-Null
[Reflection.Assembly]::LoadWithPartialName("System.Globalization") | Out-Null

$Aktion ={ Write-Host "Did you say $($Event.SourceArgs.Result.Text)?" }

$CultureInfo = New-Object System.Globalization.CultureInfo("en-US")
$SpeechRecognitionEngine = New-Object System.Speech.Recognition.SpeechRecognitionEngine($CultureInfo)

$Texts = New-Object System.Speech.Recognition.Choices
$Texts.Add("Test")
$Texts.Add("Bla")
$Texts.Add("Hello")

$GrammarBuilder = New-Object System.Speech.Recognition.GrammarBuilder($Texts)
$WordsList = New-Object System.Speech.Recognition.Grammar($GrammarBuilder)
$SpeechRecognitionEngine.SetInputToDefaultAudioDevice()
$SpeechRecognitionEngine.LoadGrammarAsync($WordsList)

Unregister-Event "SpeechModuleCommandRecognized" -ErrorAction SilentlyContinue

Register-ObjectEvent $SpeechRecognitionEngine SpeechRecognized -SourceIdentifier "SpeechModuleCommandRecognized" -Action $Aktion | Out-Null

# start recognition
$RecognizeMode = New-Object System.Speech.Recognition.RecognizeMode
$RecognizeMode.value__ = 1 # 0=Signle; 1=Multiple

$SpeechRecognitionEngine.EmulateRecognize('Hello') | Out-Null

 

 

May 12, 2013 at 12:29 pm

 

 

Okay... I found my problem.
I used -Action {. $Aktion} instead of -Action $Aktion in line:

Register-ObjectEvent$SpeechRecognitionEngineSpeechRecognized-SourceIdentifier"SpeechModuleCommandRecognized"-Action$Aktion|Out-Null

I don't understand what is the difference but it looks like there is one.

But not everything is recognized now...just the predefined Texts.
Is there no way to get what the computer understood? – The idea behind all this was to can say anything and get it as text... – similar to dictation.

 

 

May 13, 2013 at 11:11 pm

How can I mark this discussion as "solved"?

May 14, 2013 at 1:24 am

I don't believe it's possible. :/