Advanced Windows PowerShell Scripting Video Training

Advanced Windows PowerShell Scripting Video Training
Advanced Windows PowerShell Scripting Video Training

Wednesday, August 7, 2013

Have PowerShell Verbally Provide Information

Let’s face it.  Sometimes scripts take a while to run.   Often I have a lower end client sitting in the back of my office specifically for executing schedule scripts or scripts that will run for a long period of time.  Normally I have the scripts email me once they have completed and I simply run Receive-job to collect the data.
I developed this cmdlet as a fun way of demonstrating passing input via the pipeline into a cmdlet.  It gives you the opportunity to have PowerShell talk to you.  Maybe to alert you that a threshold has been exceeded or to let you know that a workflow has completed.  In any case, have some fun with.  Remember its intent was to act as a demonstration of parameter passing.  Look carefully and you will see examples of passing parameters ByValue and ByPropertyName.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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

Function Out-Voice
{
[cmdletBinding()]
Param
(
    [parameter(ValueFromPipeline=$True,
               ValueFromPipelineByPropertyName=$True)]
               [String]$VoiceMessage,
    [parameter(ValueFromPipelineByPropertyName=$True)]
    [ValidateSet("US_Male","UK_Female","US_Female")]          
               [String]$VoiceType,
               [Switch]$PassThru,
    [parameter(ValueFromPipeline=$True)]
               [PSObject]$InputObject         
)
    BEGIN
    {
        # When the cmdlet starts, create a new
        # SAPI voice object.
        $voice = New-Object -com SAPI.SpVoice
    }
   
    PROCESS
    {
        # If an array of messages is passed, this will allow
        # for each message to be read.
        ForEach ($M in $VoiceMessage)
        {
            # If the client is Windows 8, then allow for different voices.
            If ((Get-CimInstance -ClassName Win32_Operatingsystem).Name -Like "*Windows 8*")
            {             
                # Get a list of all voices.
                $Voice.GetVoices() | Out-Null
                $voices = $Voice.GetVoices();
                $V = @()
                ForEach ($Item in $Voices)
                {
                    $V += $Item
                }                  
                   
                # Set the voice to use using the $VoiceType parameter.
                # The defualt voice will be used otherwise.
                Switch ($VoiceType)
                {
                    "US_Male" {$Voice.Voice = $V[0]}
                    "UK_Female" {$Voice.Voice = $V[1]}
                    "US_Female" {$Voice.Voice = $V[2]}
                }
            } # End: IF Statment.
            # Speak the message.
            $voice.Speak($M) | Out-Null
        }
    } # End: ForEach ($M in $VoiceMessage)
   
    END
    {
        If ($PassThru)
        {
            Write-Output $InputObject
        }
    } #End: PROCESS

<#
.SYNOPSIS
Reads a message to the user.

.DESCRIPTION
Uses the default voice of the client to read a message
to the user.

.PARAMETER Message
The string of text to read.

.PARAMETER VoiceType
Allows for the default choice to be changed using the
default voices installed on Windows 8. Acceptable values are:
US_Male
UK_Female
US_Female

.PARAMETER PassThru
Passes the piped in object to the pipeline.

.EXAMPLE
Out-Voice "Script Complete"

Reads back to the user "Script Complete"

.EXAMPLE
$CustomObject | Out-Voice -PassThru

If the object has a property called "VoiceMessage" and is of
data type [STRING], then the string is read.  If the object
contains a "VoiceType" parameter that is valid, that
voice will be used. The original object is then passed
into the pipeline.

.EXAMPLE
Get-WmiObject Win32_Product |
ForEach -process {Write-Output $_} -end{Out-Voice -VoiceMessage "Script Completed"}

Recovers the product information from WMI and the notifies the
user with the voice message "Script Completed" while also
passing the results to the pipeline.

.EXAMPLE
Start-Job -ScriptBlock {Get-WmiObject WIn32_Product} -Name GetProducts
While ((Get-job -Name GetProducts).State -ne "Completed")
{
    Start-sleep -Milliseconds 500
}
Out-Voice -VoiceMessage "Done"

Notifies the user when a background job has completed.

.NOTES
Tested on Windows 8
+-------------------------------------------------------------+
| Copyright 2013 MCTExpert, Inc. All Rights Reserved          |
| User takes full responsibility for the execution of this    |
| and all other code.                                         |
+-------------------------------------------------------------+
#>
} # End: Out-Voice



Lines 6-7 allow the parameter $VoiceMessage to pass information ByValue and ByProperty name.  This string is what Windows will read back to you.  By having ByPropertyName, this allows you to add a “VoiceMessage” property to your objects should you need a verbal message given.
Lines 9-11 allow you to choose the voice that you want to use.  There are three built in voices.  Advanced parameterization using the ValidateSet attribute allows you to provide TAB completion of this parameter.
The PassThru and InputObject parameters allows the original object piped to this cmdlet to continue in the pipeline.
Lines 16-21 executes when the pipeline first starts.  The Begin block will create an object of Windows Text-To-speech capabilities into PowerShell and allow you to use it.
Lines 23-26 runs for each object passed to this cmdlet. Should multiple lines of messages be passed to the cmdlet, a ForEach loop will handle them.
Line 30 test to make sure that this code is running on Windows 8.  The code was only tested on Windows 8.  To test on other platforms, change *Windows 8* to *.
Lines 32-39 collect the different voice objects.
Lines 43-48 set the voice based on the VoiceType parameter.  US_Male is the default.
Line 51 executes the Speak method and reads the text to the user.
Lines 55-61 is the END block.  it will only execute once after all elements in the upstream pipeline have been exhausted.  If the PassThru parameter has been specified, then the original object is passed through the pipeline.

No comments: