Advanced Windows PowerShell Scripting Video Training

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

Thursday, August 29, 2013

Getting information back from a Message Box with PowerShell

Sometimes I want a script to run automatically, but still prompt me before it takes an action.  A neat way of doing this is with a pop up message box.  Utilizing the MessageBox class from the .NET Framework, we can do just that.  For example, maybe I have a script that notifies me with the Dow Jones Industrial Average drops by 300 points in the current trading session.  Hey, that is a money making opportunity! 
1
2



3
4
5
6
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$Answer = [Windows.Forms.MessageBox]::Show("DJIA has dropped by 300 points today `n Do you want to `n go to your IRA?", "Trade Alert",
          [Windows.Forms.MessageBoxButtons]::YESNO,
          [Windows.Forms.MessageBoxIcon]::Information)

If ($Answer -eq "Yes")
{
    Write-Host "Do Something."
}
Essentially, line 1 gives us access to the Windows Forms objects.
Line 2 Saves the answer of our message box in a the variable $Answer.  To control the type of message box that we display, we have several options. 

The Windows.Forms.MessageBox class is overloaded.  That means that you can implement it in several different ways.  In this instance, we are using the Show method.  Take a look at the screen shot below of the many different versions of the Show method for this class:
image
What differentiates each call to the MessageBox class is the number of arguments and their data types that you pass to the class.  In this case, we passing the 7th item which is String, String, MessageBoxButtons, MessageBoxIcon.
Clicking on this item, we are taken to the MessageBox.Show Method (String, String, MessageBoxButtons, MessageBoxIcon) method on MSDN.  Here we can see that the first string is the message and the second is the caption on the message box window.
image
From here, if we click on System.Windows.Forms.MessageBoxButtons, we can see the types of buttons that we have access to.
image
In this example, we are using YesNo. Yes or No will be returned and stored in $Answer
We are also choosing an icon for this message box from MessageBoxIcon. Here are valid options are:
image
In the end, this is what you will see:
image
Either the string Yes or No will be returned when the appropriate button is clicked.

Sunday, August 11, 2013

How to configure Group Policy to allow you to offer Remote Assistance

Let’s face it, no matter how hard you try, it is sometimes best if you just do it yourself. In the tech support world, we have to often remind ourselves that the talents of our users is not in IT and we need to do more than just talk someone through a problem. Remote Assistance in Windows allows you to both see and interact with the end users’ desktop while they are still logged in.

The standard set up of Remote Assistance is for the user to request assistance. This can be an issue for many users as it adds to the stress of the situation. Configuring your environment to allow you help desk to offer remote assistance will increase the speed of the support while at the same time decreasing the stress of the problem.

To turn on the ability to offer remote assistance, configure this GPO:

Computer Configuration / Policies / Administrative Templates / System / Remote Assistance / Configure Offer Remote Assistance

Set this policy to Enabled.

Scope this GPO to apply to your domain. You may also will want to add your tech support group to the Remote Users Group on each client computers.

To offer Remote Assistance from Windows 8, go to the Start screen.

Type MSRA.exe /offerra. This window appears.

clip_image001[5]

Type the name or IP address of the client that you want to offer assistance to.

The user receiving the assistance will get a request to approve to assistance.

clip_image002[4]

Once the user clicks Yes, the remote assistance session is established.

The expert still needs to request control of the session. This allows the end user maintain control of the session.

clip_image003[4]

To further customize the users remote assistance experience, you can also configure custom messages. This way the user knows that the offer came from company tech support and not some random piece of malware.

Computer Configuration / Policies / Administrative Templates / System / Remote Assistance / Customize Warning Messages

clip_image005[5]

Once these GPOs are deployed to your clients, they will know the support session came from you.

clip_image006[4]

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.