Event Handler in Powershell

This topic contains 11 replies, has 3 voices, and was last updated by  Anonymous 4 years, 3 months ago.

  • Author
    Posts
  • #4613

    Martin Krämer
    Participant

    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.

  • #4622

    Toni
    Participant

    Have you tried Register-ObjectEvent?

    Something like:

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

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

  • #4623

    Martin Krämer
    Participant

    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.

  • #4629

    Toni
    Participant
  • #4630

    Anonymous

    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

     

  • #4638

    Martin Krämer
    Participant
    [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:

     

     

  • #4639

    Anonymous

    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.

  • #4640

    Martin Krämer
    Participant
             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:

     

  • #4641

    Anonymous

    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

     

     

  • #4642

    Martin Krämer
    Participant

     

     

    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.

     

     

  • #4699

    Martin Krämer
    Participant

    How can I mark this discussion as "solved"?

  • #4704

    Anonymous

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

You must be logged in to reply to this topic.