Sunday, July 03, 2005

Speech with MSH

In the MSH newsgroup, there has been a lot of discussion around how to script access to objects. As it turns out, the B1 drop of MSH does not support the '-activex' paramater to new-object (a short term issue and to be rectified in the next drop). Thus some of the simple cool scripting shown on Jeffrey's TechEd presentation slides can't currently be done with our drop.

But that hasn't stopped the beta testers. Since MSH provides, in effect, full access to the .NET framework, it can do some amazing things! The following MSH function, written by Ryan Milligan, is a way in the latest drop to invoke an object's method:

function invoke-method($obj, $name)
{
$obj.GetType().InvokeMember($name,[System.Reflection.BindingFlags]::InvokeMethod, $null, $obj, $args)
}

The following MSH function leverages invoke-method, to call the Speach API's SPVoice function to speak text passed as a paramater.

Function say-text([string] $texttosay)
{
$speech = [Activator]::CreateInstance([Type]::GetTypeFromProgID("SAPI.SpVoice"))
invoke-method $speech "Speak" $texttosay 0
}

To test this:

say-text "Hello World"

For fun - what do you think would happen if you called say-text with a number such as 123456789. Try it - I was sure surprised at the result.

I'm not sure how admins would discover the details of method names, unless they know a lot about programming against COM and .NET. But the power of MSH is that someone can post a few lines of script, which you can quickly adapt, and in the example above, refactor into a command (say-text). MSH is likely to be one of the first products delveoped where there'll be more stuff out there (script hacks such as I've posted here) than code in MSH itself.

1 comment:

/\/\o\/\/ said...

Looks like this does not work anymore.

MSH C:\> $speech = new-object -com "SAPI.SpVoice"
MSH C:\> $speech.speak("hello mow",0)
Object reference not set to an instance of an object.
At line:1 char:14
+ $speech.speak( <<<< "hello mow",0)

strange is that I can do this :

MSH C:\> $speech.speak


MemberType : Method
OverloadDefinitions : {int Speak (string, SpeechVoiceSpeakFlags)}
TypeOfValue : System.Management.Automation.MshMethod
Value : int Speak (string, SpeechVoiceSpeakFlags)
Name : Speak
IsInstance : True


there should be a .NET class in winFX but could not find Speech.dll

$speech = new-object System.Speech.Synthesis.SpeechSynthesizer

I also tryed

MSH C:\> [System.Reflection.Assembly]::LoadFile("c:\mowmsh\Interop.SpeechLib.dll
")

GAC Version Location
--- ------- --------
False v1.1.4322 c:\mowmsh\Interop.SpeechLib.dll

MSH C:\> $speech = new-object "Speechlib.SpVoice"
new-object : Constructor not found. Cannot find an appropriate constructor for
type Speechlib.SpVoice.
At line:1 char:21
+ $speech = new-object <<<< "Speechlib.SpVoice"

Guess we have to wait till the RTM to get Speech..

gr /\/\o\/\/