grokbulb1

This post is part of my grok-posh series describing why developers should learn PowerShell.

A PowerShell console is basically an doorway into the entire realm that is .NET, COM, and WMI.  As I say in my talks – you can think of PowerShell as an interactive way to discover, obtain, and manipulate objects.

This makes it a great place to explore the things you can do and to learn about these objects by manipulating them.

Here’s a great example - the other day @shaylevy posted this little gem on twitter:

$error | % { (New-Object -ComObject SAPI.SPVoice).Speak($_.Message) }

Shay’s code is using the Microsoft Speech API to have the computer “read” the error message(s) raised by the last PowerShell command executed.  Slick.

I’ve never played with the Speech API.  Let’s see how I can use PowerShell to interactively learn what I can do with this object:

1 PS > $voice = New-Object -ComObject SAPI.SPVoice 2 PS > $voice | get-member 3 4 5 TypeName: System.__ComObject#{269316d8-57bd-11d2-9eee-00c04f797396} 6 7 Name MemberType Definition 8 ---- ---------- ---------- 9 DisplayUI Method void DisplayUI (int, string, string, Variant) 10 GetAudioOutputs Method ISpeechObjectTokens GetAudioOutputs (string, string) 11 GetVoices Method ISpeechObjectTokens GetVoices (string, string) 12 IsUISupported Method bool IsUISupported (string, Variant) 13 Pause Method void Pause () 14 Resume Method void Resume () 15 Skip Method int Skip (string, int) 16 Speak Method int Speak (string, SpeechVoiceSpeakFlags) 17 SpeakCompleteEvent Method int SpeakCompleteEvent () 18 SpeakStream Method int SpeakStream (ISpeechBaseStream, SpeechVoiceSpeakFlags) 19 WaitUntilDone Method bool WaitUntilDone (int) 20 AlertBoundary Property SpeechVoiceEvents AlertBoundary () {get} {set} 21 AllowAudioOutputFormatChangesOnNextSet Property bool AllowAudioOutputFormatChangesOnNextSet () {get} {set} 22 AudioOutput Property ISpeechObjectToken AudioOutput () {get} {set by ref} 23 AudioOutputStream Property ISpeechBaseStream AudioOutputStream () {get} {set by ref} 24 EventInterests Property SpeechVoiceEvents EventInterests () {get} {set} 25 Priority Property SpeechVoicePriority Priority () {get} {set} 26 Rate Property int Rate () {get} {set} 27 Status Property ISpeechVoiceStatus Status () {get} 28 SynchronousSpeakTimeout Property int SynchronousSpeakTimeout () {get} {set} 29 Voice Property ISpeechObjectToken Voice () {get} {set by ref} 30 Volume Property int Volume () {get} {set} 31

Line 1 creates a new instance of the SAPI.SPVoice object in the shell variable $voice.  Line 2 passes the $voice variable to the get-member cmdlet, which outputs all the methods and properties that the COM object supports.

Lots of opaque methods there – some UI elements it looks like, some asynchronous hooks.  Looks like we can change the rate at which the speech is spoken, the volume, oooohhh – looks like there are other voice options too!  Let’s see what voices we have available:

PS > $voice.GetVoices() Id DataKey Category -- ------- -------- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Token... System.__ComObject System.__ComObject

Aw, sad trombone …  we have only one voice available.  Hey, what’s it sound like anyway?

PS > $voice.Speak( 'Hello Beef!' )
Hello yourself!  Not bad.  What does that Rate property do?

PS > $voice.Rate 0 PS > $voice.Rate = 5 PS > $voice.Speak( 'The build has failed!' ) 1 PS > # oh dear, that has the potential to raise my stress level PS > # let's try to get more of a southern drawl going... PS > $voice.Rate = -5 PS > $voice.Speak( 'Oh no! The build, she has failed!' ) 1 PS > # now that's more like it!

Neat.  As much fun as I’m having, I’m learning a bit about the Speech API.  PowerShell allows me to interact with the object, trying things out and testing theories.  Will I eventually need to turn to MSDN if I want to do anything serious?  Probably.  But consider what I’ve learned so far using nothing but PowerShell for about 60 seconds:

  1. I know the methods and properties exposed by the Speech API voice object;
  2. I know that voices are somehow linked to my registry, and the API suggests that it’s possible to install and remove voices, or create my own;
  3. Based on the methods of the voice object, I can assume there is a way to have the API generate speech asynchronously;
  4. I can manipulate the properties of a voice to my liking.  In fact, using PowerShell I can get immediate feedback on what the voice sounds like.

You can generalize this interaction to almost any object if you know a few key PowerShell cmdlets.  Here I use these key cmdlets to discover how I can work with windows services in my PowerShell session:

1 PS >#what commands apply to services? 2 PS >get-command *service 3 4 CommandType Name Definition 5 ----------- ---- ---------- 6 Cmdlet Get-Service Get-Service [[-Name] <String[]>] [-ComputerName <String[]>] [-DependentServices... 7 Cmdlet New-Service New-Service [-Name] <String> [-BinaryPathName] <String> [-DisplayName <String>]... 8 Cmdlet Restart-Service Restart-Service [-Name] <String[]> [-Force] [-PassThru] [-Include <String[]>] [... 9 Cmdlet Resume-Service Resume-Service [-Name] <String[]> [-PassThru] [-Include <String[]>] [-Exclude <... 10 Cmdlet Set-Service Set-Service [-Name] <String> [-ComputerName <String[]>] [-DisplayName <String>]... 11 Cmdlet Start-Service Start-Service [-Name] <String[]> [-PassThru] [-Include <String[]>] [-Exclude <S... 12 Cmdlet Stop-Service Stop-Service [-Name] <String[]> [-Force] [-PassThru] [-Include <String[]>] [-Ex... 13 Cmdlet Suspend-Service Suspend-Service [-Name] <String[]> [-PassThru] [-Include <String[]>] [-Exclude ... 14 15 16 PS >#looks promising. what does get-service do? 17 PS >get-help get-service 18 19 NAME 20 Get-Service 21 22 SYNOPSIS 23 Gets the services on a local or remote computer. 24 25 26 SYNTAX 27 Get-Service [[-Name] <string[]>] [-ComputerName <string[]>] [-DependentServices] [-Exclude <string[]>] [-Include <string[]>] [-RequiredServices] [<CommonParameters>] 28 29 Get-Service -DisplayName <string[]> [-ComputerName <string[]>] [-DependentServices] [-Exclude <string[]>] [-Include <string[]>] [-RequiredServices] [<CommonParameters>] 30 31 Get-Service [-InputObject <ServiceController[]>] [-ComputerName <string[]>] [-DependentServices] [-Exclude <string[]>] [-Include <string[]>] [-RequiredServices] [<CommonParamete 32 rs>] 33 34 35 DESCRIPTION 36 The Get-Service cmdlet gets objects that represent the services on a local computer or on a remote computer, including running and stopped services. 37 38 You can direct Get-Service to get only particular services by specifying the service name or display name of the services, or you can pipe service objects to Get-Service. 39 40 41 RELATED LINKS 42 Online version: http://go.microsoft.com/fwlink/?LinkID=113332 43 Start-Service 44 Stop-Service 45 Restart-Service 46 Resume-Service 47 Suspend-Service 48 Set-Service 49 New-Service 50 51 REMARKS 52 To see the examples, type: "get-help Get-Service -examples". 53 For more information, type: "get-help Get-Service -detailed". 54 For technical information, type: "get-help Get-Service -full". 55 56 57 58 PS >#ok, now let's see what we can do with a service... 59 PS >get-service | get-member 60 61 62 TypeName: System.ServiceProcess.ServiceController 63 64 Name MemberType Definition 65 ---- ---------- ---------- 66 Name AliasProperty Name = ServiceName 67 RequiredServices AliasProperty RequiredServices = ServicesDependedOn 68 Disposed Event System.EventHandler Disposed(System.Object, System.EventArgs) 69 Close Method System.Void Close() 70 Continue Method System.Void Continue() 71 CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType) 72 Dispose Method System.Void Dispose() 73 Equals Method bool Equals(System.Object obj) 74 ExecuteCommand Method System.Void ExecuteCommand(int command) 75 GetHashCode Method int GetHashCode() 76 GetLifetimeService Method System.Object GetLifetimeService() 77 GetType Method type GetType() 78 InitializeLifetimeService Method System.Object InitializeLifetimeService() 79 Pause Method System.Void Pause() 80 Refresh Method System.Void Refresh() 81 Start Method System.Void Start(), System.Void Start(string[] args) 82 Stop Method System.Void Stop() 83 ToString Method string ToString() 84 WaitForStatus Method System.Void WaitForStatus(System.ServiceProcess.ServiceControllerStatus desiredStatus), System.Void WaitForStatus(System.ServiceProcess.Se... 85 CanPauseAndContinue Property System.Boolean CanPauseAndContinue {get;} 86 CanShutdown Property System.Boolean CanShutdown {get;} 87 CanStop Property System.Boolean CanStop {get;} 88 Container Property System.ComponentModel.IContainer Container {get;} 89 DependentServices Property System.ServiceProcess.ServiceController[] DependentServices {get;} 90 DisplayName Property System.String DisplayName {get;set;} 91 MachineName Property System.String MachineName {get;set;} 92 ServiceHandle Property System.Runtime.InteropServices.SafeHandle ServiceHandle {get;} 93 ServiceName Property System.String ServiceName {get;set;} 94 ServicesDependedOn Property System.ServiceProcess.ServiceController[] ServicesDependedOn {get;} 95 ServiceType Property System.ServiceProcess.ServiceType ServiceType {get;} 96 Site Property System.ComponentModel.ISite Site {get;set;} 97 Status Property System.ServiceProcess.ServiceControllerStatus Status {get;} 98 99 100 PS > 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299

The key PowerShell commands: get-command (line 2), get-help (line 17), and get-member (line 59) help you find the objects you’re looking for and tell you what it is they can do.