Advanced Windows PowerShell Scripting Video Training

Tuesday, August 1, 2017

Don’t you just hate it when you get partial
information? With information systems,
you would think that you would get everything you need. It is like when I ask one of my Sailors why they
are late and I have to ask a half dozen more questions before I get the full
story. (Insert rolling eyes).

A neat thing that I do to demonstrate to my advance
PowerShell classes is how to make a GUI using SAPIEN PowerShell Studio. Yes, I know. PowerShell was not supposed to
be ran in a GUI. Try asking a
non-technical user to execute something at the command line. I would rather visit the dentist. Placing a pretty GUI on top of the code fools
them into wanting to use it.

As you can see from the output, this is comma delimited
information. You also may notice is that we are missing information. Do you see what is missing? We are missing the header information that tells us the property names. It is not part
of the data received. No problem. We are free to create our own property
names. To do this, we are going to use ConvertFrom-CSV and use its parameter –Header. Reading the help file for ConvertFrom-CSV, we
see that we need to provide a comma separated list of property names. The order of the names need to match the
order that the data is received. Just remember that these names are the values of the -Header parameter. Do not place the entire string in quotes. Provide a normal comma separated.

Friday, July 28, 2017

Wow! I am actually
getting around to blogging this year.
This has been an epic year in terms of how busy I have been. Between speaking at both the PowerShell
Conferences in Europe and Asia, but also expanding my client base in Asia and
the Pacific islands, I have been busy.
Oh, let’s not forget adding Windows Server 2016 classes, Security+ and
my work on the Azure platform.

OK, yes I have been busy.
At some point, what I have been learning does get spilled over into my
classes and this blog.

One of the sticky points with learning PowerShell has been
the creation of calculated properties with Select-Object. To do so you need to use a hash table, associative
table, or dictionary. What you call it
depends on your background. Just
remember that most IT pros who take my PowerShell classes are not programmers
and have never been trained as such.
Makes for an interesting week for me.

Below is an example of how we have been teaching calculated properties.

Get-Process |

Select-Object-PropertyName,

@{

Name = 'VirtMemory'

Expression = {$PSItem.VM}

}

You
could short hand it as such.

Get-Process |

Select-Object-PropertyName,
@{N = 'VirtMemory'; E = {$PSItem.VM}}

Well,
that hash table is the problem. I have
not found a way to eliminate it, but I have found a way to write it a different
way.

$Hash1 = @{ 'Name'
= 'VirtMemory'; Expression = {$PSItem.VM}}

Get-Process | Select-Object-PropertyName,
$Hash1

The
idea is to break it up into multiple parts so the student can focus more on
what is going on and less on the confusing syntax used with Select-Object. You
can add additional calculated properties as shown below.

$Hash1 = @{ 'Name'
= 'VirtMemory'; Expression = {$PSItem.VM}}

$Hash2 = @{ 'Name'
= 'WorkMemory'; Expression = {$PSItem.WS}}

Get-Process | Select-Object-PropertyName,
$Hash1, $Hash2

This
technique will not work for all. If what
you are using works for you, then continue to use your technique. I will be introducing this syntax in my
PowerShell class next week in Phoenix to gauge the class response to this
technique as a step in their understanding of how to perform this very common
task and understand it.

What threw me off was the “The system cannot find the file
specified”. Well, here is the command
that I used:

New-SRPartnership `

-SourceComputerNameLON-SVR1 `

-SourceRGNameRG01 _`

-SourceVolumeNameM: `

-SourceLogVolumeNameN: `

-DestinationComputerNameLON-SVR4 `

-DestinationRGNameRG02 `

-DestinationVolumeNameM: `

-DestinationLogVolumeNameN: `

-Verbose

I did not specify any file. I logged into LON-SVR4 and tried
to look for the StorgeReplica
log. It was not present. When I executed Get-WindowsFeature –Name Storage-Replica,
it returned a state of InstallPending. Problem solved.

My code was executed from the other member of the
replica. It rebooted before it told the
other server to do so. My mistake. I still do not know what file it was referring
to, but the reboot needed to complete the installation fixed the problem.

Monday, May 15, 2017

I know.
Surprise! I am actually sitting
down to do some blogging. It has been a
very busy 2017. Last week I just
returned home from delivering 4 sessions at the PowerShell Conference in
Europe. The organizers did an outstanding
job. We all had a great time.

I like to be prepared before speaking to an audience. A
month before the conference, I had everything prepared. Every line of code was thoroughly
tested. A week before the conference, I
took a few days off in Venice, Italy and ran through everything one more
time. All the code worked. 24 hours prior to delivering one of my
presentations, I ran through the code again and…. It broke.

I started to receive errors like these two when trying to
work with Azure.

Save-AzureRmProfile : The term
'Save-AzureRmProfile' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or

if a path was included, verify
that the path is correct and try again.

One of the frustrations that we Microsoft trainers have with
Azure is how fast it changes. At one
level, this is really good. It means
that Microsoft is actively improving the product. However, the reason for the code breaking is
a bit frustrating. Below are the two cmdlets have changed.

Old

New

Save-AzureRmProfile

Save-AzureRmContext

Select-AzureRmProfile

Import-AzureRmContext

These cmdlets essentially do the same thing. I was working with Azure using local
background jobs to perform multiple tasks in Azure at the same time. I fixed this code a few hours before going on
stage. As of this writing, no mention in
the online documentation of the old cmdlets about the change. On another note, the old cmdlets worked when
I was not using background jobs. Interesting twist to the story.

Friday, March 24, 2017

Wow! It has been a
while since I last blogged. This has
been a very busy year. Between my Navy activities and all the classes that I’m
bringing online for clients, I am burning the candle at both ends.

As many of you know, my last day of a PowerShell class is “Project
Day”. One of the projects that I helped
out with this week involved determining if UAC was enabled. Utilizing the template we created in class
and a check of the registry, we were able to:

Remote to each client.

Determine if the client was online.

Report back the state of UAC.

I decided to advance the code just a little to make sure
everything reports back as an object.
Below is that code. Wish I had
more time to explain it step by step, but I have to keep moving. I only have 3 weeks to get everything done
for PowerShell Conference Europe.

Wednesday, March 8, 2017

I’m spending the week in San Diego delivering a Security+
class as part of my Annual Training for the United States Navy. It has been a few years since my last
Security+ class that I delivered to the US Air Force. Since then, PowerShell has undergone a few
version updates. I decided to leverage
one of the new cmdlets to help use demonstrate file hashing.

The group that we are working with this week is sharp and
asking some really great questions.
There is a little confusion out there on what a hash is so I’m adding
this to both my military and civilian Security+ classes.

Thursday, February 2, 2017

Wow, I finally got around to doing a little blogging. This has thus far been a very busy year. I’m actually writing this in the air heading
to teach a PowerShell class in North Carolina and prepping my sessions for
PowerShell Summit Europe in a few months.

When I start helping my students debug their issues in
class, I often walk up to their monitors and see the error right away. I am very cautious to point out at the
beginning of class that the reason that I see their errors so fast is because I
have made the same errors so often. Here
is one that left me scratching my head.

While adding a valid parameter to a function that I was
developing, I had this error in the ISE.

I’ll be honest, this was a new one for me. Looking at the message, I realized that there
was a casting of string. This pointed me
to my param block. Sure enough, I placed a comma where I should not have.

You can see it right after [String]. My bad.
Hey, all of us make mistakes.