Advanced Windows PowerShell Scripting Video Training

Friday, February 26, 2016

Often when I am writing large amounts of code, I like to
enter items into an event log of some type.
For those of you who have been sitting in my Advanced PowerShell classes
where we use SAPIEN PowerShell Studio, you may have noticed that I will
sometimes include a tabbed page where I have a log file.

In DSC we have an Analytic log that we can send messages to
using a DSC resource called Log,

PS C:\WINDOWS\system32> Get-DscResource -Name Log

ImplementedAs Name ModuleName Version Properties

------------- ---- ---------- ------- ----------

Binary
Log PSDesiredStateConfiguration 1.1
{Message, Depend...

This log file contains all of the verbose messages sent to
the Analytic log.

Look for Event ID
4098 with a ‘Warning’ level.

Warnings are represented with the value of 3. Unfortunately,
not all event 4098 will be yours. Take a
look at this configuration:

# Create your configuration.

ConfigurationTestMessage

{

Import-DscResource-ModuleNamePSDesiredStateConfiguration

$Message="`n
`nConfigEventID: 001`n"

$Message+="Task
XYZ Completed`n"

$Message+="`nAdd
Whatever else you need to add"

Node"localHost"

{

LogTestMessage

{

#
This will write a message to the event log with event

# ID
4098.

Message ="$Message"

}

}

}

You can see that I am creating a custom message that I want
to make sure is visually separated from the rest of the metadata presented in
the events message. My next set of code
allows me to filter out all of the other information and just see my message.

Wednesday, February 17, 2016

From time to time, I take a good look at how I am teaching
PowerShell just to make sure that I am providing the most effective
delivery. That may be why when someone
audits the class, they say they learn new material. Besides, if I did not make changes, I would
get bored.

Over the last few months I’ve been teaching how to create
calculated properties with Select-Object a little differently. This is a key skill to have so I need to make
sure that we get it right. Here is an
explanation of how to create a custom property.

A custom property simply adds an additional property to an
object in the PowerShell pipeline. It
does not change the original object, just the copy of it in the pipeline. Take
a look at the properties of Get-Date.

PS C:\> Get-date | Select *

DisplayHint : DateTime

DateTime : Thursday,
February 11, 2016 7:46:10 PM

Date : 2/11/2016
12:00:00 AM

Day : 11

DayOfWeek : Thursday

DayOfYear : 42

Hour : 19

Kind : Local

Millisecond : 564

Minute : 46

Month : 2

Second : 10

Ticks :
635908167705642214

TimeOfDay :
19:46:10.5642214

Year : 2016

We are going to add a new property called OurDate. This new property will have a
value consisting of the current year, month, and day in this format:
YYYY-MM-DD. Here is the code to
accomplish this:

Get-Date|

Select-Object-Property*,

@{

Name="OurDate";

Expression={"$($_.Year)-$($_.Month)-$($_.Day)"}

}

We first place a DateTime object into the pipeline by
calling Get-Date. Next we pipe it to
Select-Object. We use the –Property parameter to select which properties to keep from the original
object. In this case, we use ‘*’ to keep
all of them. Next we add a second
property. This one is a hash table.

A hash table is a key/value pair. In our case, a Property Name / Property Value
pair. Hash tables in PowerShell are
denoted by @{}. Inside of the curly
braces is where we declare the property name and the property value.

The Name value
provides us with the property name. You
can see that we set this value equal to a string of what we want to call this
new calculated property, “OurDate”.

The Expression is the calculated part. The actual calculation is done inside of its
own set of curly braces ‘{}’. While calculating this property, you can
reference the current object in the PowerShell pipeline by using one of two
generic variables. $_ is usable in all versions of PowerShell. $PSItem
is for PowerShell 3 and higher. They
both represent the current object in the PowerShell pipeline. Because this variable represents the object,
you have access to all the properties and methods of the object. In our
example, we are creating a string that contains the values of 3 properties from
the object in the pipeline. Since we are
creating this value as a string, each time we reference the object, we need to
place it inside of a subexpression. That
would be the $() surrounding each call to the object. Here is the end result.

DisplayHint : DateTime

DateTime : Thursday,
February 11, 2016 8:56:23 PM

Date : 2/11/2016
12:00:00 AM

Day : 11

DayOfWeek : Thursday

DayOfYear : 42

Hour : 20

Kind : Local

Millisecond : 151

Minute : 56

Month : 2

Second : 23

Ticks :
635908209831513532

TimeOfDay :
20:56:23.1513532

Year : 2016

OurDate : 2016-2-11

Take a look at the last item. It is our calculated property.

You can shorten this code up a bit:

Get-Date|

Select-Object-Property*,

@{

N="OurDate";

E={"$($_.Year)-$($_.Month)-$($_.Day)"}

}

Or

Get-Date|

Select-Object-Property*,

@{N="OurDate" ; E={"$($_.Year)-$($_.Month)-$($_.Day)"}}

You can also look at the examples in the help file for Select-Object. Take a look at example
#4 for another example of creating a calculated property.

Monday, February 15, 2016

In my PowerShell class last week, we took a lab a bit
further. This lab involved using the old
WMI commands. Well, that is no fun. I was providing my answers to the lab using
the new CIM cmdlets. I did this once before, but I forgot to update my answers. You see, there is a difference in how you
provide information to Invoke-CIMMethod and Invoke-WMIMethod.

The objective was to change the Start Mode of the WinRM
service. To do this in WMI:

Get-WmiObject–ClassWin32_Service–Filter"Name='WinRM'"
|

Invoke-WmiMethod–NameChangeStartMode–Argument'Automatic'

You would think that you could do the same with the CIM
cmdlets, but PowerShell did not like this.

Using Invoke-CIMMethod, the –Arguments parameter requires a System.Collections.IDictionary object. Say what???? So, I took a look at the MSDN
documentation for System.Collections.IDictionary. In the Remarks
section, I learned that this object is simply a key/value pair.

Wednesday, February 10, 2016

Yesterday, I posted some code on how to draw on a GUI using
transparent colors. To further
demonstrate this transparency, we are going to add some animation.

You can use your code from yesterday and just add to
it. The only object that you need to add
is a timer control. Simply drag the timer control from the Toolbox in SAPIEN
PowerShell Studio onto your form.

The timer control will appear under he actual form in the
Designer tab.

Here are some differences from yesterday’s code. (The entire code will be posted below)

First we need to set the bounds for the circles to
move. They will be bouncing off the
walls. Remember that the ellipse origin
is the upper left corner, not the center.
That is why our right and bottom boundaries are 156 and not 256. The ellipses have a size of 100 pixels.

# Set the X and Y max and min values.

$XMin = 0

$YMin = 0

$XMax = 156

$YMax = 156

We need to declare the starting positions of all three
ellipses. Since these values will be
modified in events, we assign them to be script level variables. We need to
provide both X and Y positions for all three ellipses.

# Set the starting values for the circles.

$Script:RX = 78 ; $Script:RY
= 50

$Script:GX = 50; $Script:GY
= 95

$Script:BX = 106; $Script:BY
= 95

We need to provide a rate of movement each time our timer’s
Tick event executes. Here we will send all three ellipses into different
directions.

# Set the directions

$Script:RXMove = 1 ; $Script:RYMove
= 1

$Script:GXMove = 1; $Script:GYMove
= -1

$Script:BXMove = -1; $Script:BYMove
= 1

We need to set an interval value for the timer. The interval determines how long windows will
wait before executing the Tick event of the timer. It is in milliseconds. Once set, we execute the Start method.

# Set the speed of the motion by controlling how fast the
Timer ticks.

$Timer1.Interval = 10# Milliseconds.

# Start the timer.

$timer1.Start()

In the paint event, we need to change the X and Y values to
reflect or position variables as opposed to hard coding them.

The $timer1_Tick event is next. We need to monitor the values of our position
variables. Since we are only changing
them by a value of 1, we can look to see when they are equal to our
boundaries. If they do equal the
boundary, then we multiple the movement direction by -1. This reverses the movement’s directions.