Event Handler in Powershell

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.

Have you tried Register-ObjectEvent?

Something like:

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

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

Perfect.
This was exactly what I was looking for :slight_smile:
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 :frowning:

Thank you again.

I think in the -Action scriptblock you should have access to $sender.

Take a look on these links about event handling:

http://blogs.technet.com/b/heyscriptingguy/archive/2011/06/16/use-asynchronous-event-handling-in-powershell.aspx

http://blogs.technet.com/b/heyscriptingguy/archive/2011/06/17/manage-event-subscriptions-with-powershell.aspx

 

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

 

[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:

 

 

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.

         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 :frowning:

I did the following:

 

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

 

 

 

 

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.

 

 

How can I mark this discussion as “solved”?

I don’t believe it’s possible. :confused: