PowerShell for Windows Admins


May 1, 2013  3:26 PM

Scripting Games–a word of advice for competitors

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

At the moment it isn’t necessary to run your script to give a vote.

Probably the quickest way to lose points is have an obvious and glaring error in your script such as

. . . | where {$_.LastWriteTime –lt (date).ADDdays(-90)} | . . .

or

. . . | where {$_.LastWriteTime –lt (get-date).ADDseconds(-90)} | . . .

Both of which I’ve seen today.

Please make sure your script syntax is correct before you submit otherwise all your hard work will be for nothing

May 1, 2013  2:21 PM

Filter vs Include

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I’ve gone through most of the Beginner event submissions over the last couple of days. One thing that has jumped out is the potential misunderstanding around using the –include or –filter parameters on get-childitem.

If we look at the two parameters

-Include
Gets only the specified items. The value of this parameter qualifies the Path parameter. Enter a path element or pattern, such as “*.txt”. Wildcards are permitted.
The Include parameter is effective only when the command includes the Recurse parameter or the path leads to the contents of a directory, such as C:\Windows\*, where the wildcard character specifies the contents of the C:\Windows directory.

-Filter
Specifies a filter in the provider’s format or language. The value of this parameter qualifies the Path parameter.
The syntax of the filter, including the use of wildcards, depends on the provider. Filters are more efficient than other parameters, because the provider applies them when retrieving the objects, rather than having Windows PowerShell filter the objects after they are retrieved.

These are best explained by some examples. Lets start with the current directory

PS> Get-ChildItem -Filter *.csv | select -First 1

Directory: C:\MyData\SkyDrive\Data\scripts

Mode LastWriteTime Length Name
—- ————- —— —-
-a— 12/09/2012 19:07 2665 log.csv

but

Get-ChildItem -include *.csv | select -First 1

returns nothing

To get –Include to work you need to do this

PS> Get-ChildItem -path .\* -include *.csv | select -First 1

Directory: C:\MyData\SkyDrive\Data\scripts

Mode LastWriteTime Length Name
—- ————- —— —-
-a— 12/09/2012 19:07 2665 log.csv

The path has to be given for –Include to return anything

Looking at another folder

These work

Get-ChildItem -Path C:\MyData\SkyDrive\Data\scripts -Filter *.csv

Get-ChildItem -Path C:\MyData\SkyDrive\Data\scripts\* -Filter *.csv

Get-ChildItem -Path C:\MyData\SkyDrive\Data\scripts\* -Include *.csv

Get-ChildItem -Path C:\MyData\SkyDrive\Data\scripts -Include *.csv -Recurse

But these don’t

Get-ChildItem -Path C:\MyData\SkyDrive\Data\scripts -Include *.csv

Get-ChildItem -Path C:\MyData\SkyDrive\Data\scripts\ -Include *.csv

If you want to use –Include remember the path and wildcard or use recurse


April 30, 2013  2:09 PM

Getting the folder name

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Consider the file information from get-childitem

PS> $file = ls servicesv0.6.txt

Fullname gives the full path to the file

PS> $file.Fullname
C:\MyData\SkyDrive\Data\scripts\servicesv0.6.txt

if you use DirectoryName you get the full path to the parent directory

PS> $file.DirectoryName
C:\MyData\SkyDrive\Data\scripts

The easiest way to get the folder holding the path is like this

PS> Split-Path -Path $file.DirectoryName -Leaf
scripts

However on a Windows 8/PS 3 setup you can also do this
PS> $file.Directory | select -ExpandProperty Name
scripts


April 30, 2013  1:25 PM

Don’t go mad on a one liner

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Looking at my first group of entries for Beginners Event 1 I’ve noticed what seems like a fanatical attempt to squash everything onto one line. command; command; command; command

is NOT a one liner. The ; marks the end of a line

command | command | command | command

IS a one liner, even if it goes onto multiple lines!

Don’t think one liner – think one PIPELINE


April 30, 2013  1:19 PM

Read the Question

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

When my children were at school and going off for a test or exam the last thing I told them was read the question.

It seems this needs to be repeated for the Scripting Games.  The Beginners Event 1 involved MOVING files from one server to another. I have seen a significant number of answers that are COPYING files.

Close doesn’t count in the Scripting Games.

Please read the question before diving into an answer


April 30, 2013  12:32 PM

WMI vs CIM speed tests–the final round

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

As a final test I want to see what happened when I ran multiple commands against the remote machine.

PS> 1..100 | foreach { Measure-Command -Expression{1..100 | foreach { Get-WmiObject -Class Win32_ComputerSystem -ComputerName W12SUS;
Get-WmiObject -Class Win32_OperatingSystem -ComputerName W12SUS;
Get-WmiObject -Class Win32_LogicalDisk -ComputerName W12SUS}} } |
Measure-Object -Average TotalMilliseconds

Count    : 100 Average  : 6986.797156 Sum      : Maximum  :
Minimum  : Property : TotalMilliseconds

PS> 1..100 | foreach { Measure-Command -Expression{1..100 | foreach { Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName W12SUS; Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName W12SUS; Get-CimInstance -ClassName Win32_LogicalDisk -ComputerName W12SUS}} } | Measure-Object -Average TotalMilliseconds

Count    : 100 Average  : 8430.833188 Sum      : Maximum  :
Minimum  : Property : TotalMilliseconds

 

PS> $sess = New-CimSession -ComputerName W12SUS PS> 1..100 | foreach { Measure-Command -Expression{1..100 | foreach {
Get-CimInstance -ClassName Win32_ComputerSystem -CimSession $sess;
Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $sess;
Get-CimInstance -ClassName Win32_LogicalDisk -CimSession $sess}} } |
Measure-Object -Average TotalMilliseconds

Count    : 100 Average  : 3460.203938 Sum      : Maximum  :
Minimum  : Property : TotalMilliseconds

WMI is slightly faster than CIM but using a CIM session is by far and away the fastest.

My conclusion is that WMI and CIM are comparable, with WMI having a slight edge for speed. If you want to run multiple commands against a remote machine you need to use a CIM session as it is way faster.


April 30, 2013  11:52 AM

Backticks are baaaaaad; don’t do backticks

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The voting/judging process has started for event 1 in the 2013 Scripting Games.  What I’m going to be doing over the next few weeks is point out some of the things that I’ve noticed when judging. Some will be good things that I think you should adopt; others will be bad things that you should avoid. There even may be some interesting stuff to get you thinking.

First off is the use of the backtick as a line continuation:

Get-Process | ` sort Handles –Descending

You don’t need a backtick at this point.  The pipe symbol acts as a line continuation marker so the backtick is redundant. All you need to do is this:

Get-Process | sort Handles -Descending

Its the same with commas. You don’t need to do this:

Get-Process | select Name, Id, ` Handles, CPU

because it works without the backtick

Get-Process | select Name, Id, Handles, CPU

You may see backticks used a lot in books but that is an attempt to reduce the width of the code to make it fit the page. We want you to be able to copy the code from the ebook and run it. The alternative is a line continuation marker which you would have to remove.

Bottom line – 99.9% recurring of the time you don’t need backticks as line continuation markers


April 29, 2013  1:17 PM

CIM vs WMI cmdlets-remote execution speed

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Following on from my previous post we’ll look at how the two types of cmdlets compare for accessing remote machines.

I used a similar format to the previous tests but was accessing a remote machine.

First off was the WMI cmdlet – using DCOM to access the remote Windows 2012 server

PS> 1..100 | foreach { Measure-Command -Expression{1..100 | foreach {Get-WmiObject -Class Win32_ComputerSystem -ComputerName W12SUS }}
} | Measure-Object -Average TotalMilliseconds

Count    : 100 Average  : 2084.122547 Sum      : Maximum  :
Minimum  : Property : TotalMilliseconds

 

The CIM cmdlets are similar but apparently a bit slower – probably due to having to build the WSMAN connection and teat it down each time.

PS> 1..100 | foreach { Measure-Command -Expression{1..100 | foreach {Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName W12SUS }} } | Measure-Object -Average TotalMilliseconds

Count    : 100 Average  : 2627.287458 Sum      : Maximum  :
Minimum  : Property : TotalMilliseconds

 

So what happens is you run the CIM command over a CIM session?

PS> $sess = New-CimSession -ComputerName W12SUS PS> 1..100 | foreach { Measure-Command -Expression{1..100 | foreach {Get-CimInstance -ClassName Win32_ComputerSystem -CimSession $sess }} } |
Measure-Object -Average TotalMilliseconds

Count    : 100 Average  : 877.746649999999 Sum      :
Maximum  : Minimum  : Property : TotalMilliseconds

This removes the setup and tear-down of the WSMAN connection. It suggests that the actual retrieval time for the CIM cmdlets should be reduced to 1749.540808 milliseconds for 100 accesses which is faster than the WMI cmdlets

It looks like the fastest way to access WMI information is across a CIM session. Next time we’ll look at running multiple commands


April 29, 2013  12:26 PM

AD Management in a Month of Lunches– chapter 9 in MEAP

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The MEAP for AD Management in a Month of Lunches has been updated with the release of chapter 9 on managing group policies


April 28, 2013  3:03 PM

CIM cmdlets vs WMI cmdlets–speed of execution

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

One question that came up at the summit was the comparative speed of execution of the new CIM cmdlets vs the old WMI cmdlets.  No of us knew the answer because we’d never tried measuring the speed.

I decided to perform some tests.

This first test is accessing the local machine.  In both cases the cmdlets are using COM.  WMI uses COM and CIM will use COM if a –ComputerName parameter isn’t used.

The results are as follows:

PS> 1..100 |
foreach {Measure-Command -Expression {
1..100 | foreach {Get-WmiObject -Class Win32_ComputerSystem} }
} | Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 2008.953978
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

 

PS> 1..100 |
foreach {Measure-Command -Expression {
1..100 | foreach {Get-CimInstance -ClassName Win32_ComputerSystem} }
} | Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 2078.763174
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

 

So for pure COM access the WMI cmdlets are marginally (3.4%) faster.

What if we use the ComputerName parameter?

PS> 1..100 |
foreach {
Measure-Command -Expression {
1..100 | foreach {Get-WmiObject -Class Win32_ComputerSystem -ComputerName $env:COMPUTERNAME } }
} | Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 1499.14379
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

PS> 1..100 |
foreach {
Measure-Command -Expression {
1..100 | foreach {Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $env:COMPUTERNAME } }
} | Measure-Object -Average TotalMilliseconds

Count    : 100
Average  : 3892.921851
Sum      :
Maximum  :
Minimum  :
Property : TotalMilliseconds

This one surprised me – the WMI cmdlets are 2.5 times faster.  I suspect that is because the CIM cmdlet has to build and then breakdown the WSMAN connection each time.

Next time we’ll look at accessing a remote machine.


Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to: