PowerShell for Windows Admins


April 11, 2012  7:47 AM

Scripting Games 2012 Comments: #3 Beginners Event 1

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I thought I’d publish a series on how I would go about solving these plus some comments and observations on the submitted scripts.

First event of the games

http://blogs.technet.com/b/heyscriptingguy/archive/2012/04/02/the-2012-scripting-games-beginner-event-1-use-windows-powershell-to-identify-a-working-set-of-processes.aspx

Firstly pick out the salient points of the event

Need to:

  • Identify Top 10 processes consuming memory resources on each computer
  • Decided that working set is the property to measure
  • Don’t need a script – implies a single pipeline will be acceptable
  • Should be capable of running remotely – not required to have multiple computers available
  • Aliases are acceptable – not compulsory though (we’ll come back to that statement)
  • Should return an object
  • Should be able to write results to file (but not a requirement)
  • Computers are Windows 7 & Windows 2008 R2
  • Single AD domain
  • Remoting is enabled

What do we have that can work with processes:

PS> Get-Command *process

CommandType     Name
———–     —-
Cmdlet          Debug-Process
Cmdlet          Get-Process
Cmdlet          Start-Process
Cmdlet          Stop-Process
Cmdlet          Wait-Process

 

Get-Process should work for us but it returns a whole bunch of processes and none of them are labelled working set! If we need to be able to find the top 10 working set consumers then need to be able to sort on working set

Time to use Get-Member

PS> Get-Process | Get-Member w* -MemberType property

   TypeName: System.Diagnostics.Process

Name         MemberType Definition
—-         ———- ———-
WorkingSet   Property   System.Int32 WorkingSet {get;}
WorkingSet64 Property   System.Int64 WorkingSet64 {get;}

One thing to be aware of is that sometimes the PowerShell team alias property names to make life easier for us. You also need to be aware that the column WS (K ) is workingset recast to kb instead of bytes

PS> Get-Process | Get-Member w* -MemberType aliasproperty

   TypeName: System.Diagnostics.Process

Name MemberType    Definition
—- ———-    ———-
WS   AliasProperty WS = WorkingSet

 

So we have a choice –  Workingset or WS its alias. Also we have to assume that the boss meant workingset even on 64 bit machines where WorkingSet64 may be a better answer

So lets sort on workingset

Get-Process | sort Workingset

This gives us the processes sorted in ascending order of working set usage. At this point we could just select the last 10

Get-Process | sort Workingset | select -Last 10

but that still leaves the results in ascending order which isn’t the way we usually look at things. So lets turn it round

Get-Process | sort Workingset -Descending | select -First 10

This gives us the top 10 consumers of working set on the local machine.

I have used aliases for sort-object (sort) and select-object (select) for a couple of reasons:

  • its easier
  • its still simple to read
  • its less typing
  • its accepted convention

I have left the rest of the script as full names so that if I save as script I can still read it.  Aliases are great at the command line if, and only if, you can remember them. Its better to use the full name and get the job done compared to hunting for the alias because its interactive work and some one says use aliases at the prompt.

If you are learning PowerShell stick with the full names (tab completion is a big help) until you are confident with a cmdlet – then introduce using aliases BUT ONLY FOR INTERACTIVE WORK.

So we can get the result for the local machine.  What about writing to a file?

Couple of ways to do that

Get-Process | sort Workingset -Descending | select -First 10 | Out-File top10proc.txt

gives the results in a text file – viewable with

Get-Content top10proc.txt

or use a csv file

Get-Process | sort Workingset -Descending | select -First 10 | Export-Csv top10proc.csv -NoTypeInformation
Import-Csv top10proc.csv

But notice you get the process information back formatted as a list with ALL of the properties presented.

If you want to be very clever here use tee-object which sends objects to a file and along the pipeline

Get-Process | sort Workingset -Descending | select -First 10 | Tee-Object -FilePath top10proc.txt

You get the display on screen and the data saved in a file

What about remote systems?

All your machines are in a domain for which you are the admin so presumably you have suitable permissions across all systems. Plus all machines are Windows 7 or Windows 2008 R2 so have PowerShell v2 available AND remoting is enabled.

There are two ways to approach this:

  • use the –computername parameter on get-process
  • use PowerShell remoting – probably invoke-command because we are only visiting a machine once

When you use the computername parameter and attempt to access the local machine there are three ways of accessing it without typing the name

Get-Process -ComputerName . | sort Workingset -Descending | select -First 10
Get-Process -ComputerName localhost | sort Workingset -Descending | select -First 10
Get-Process -ComputerName $env:COMPUTERNAME | sort Workingset -Descending | select -First 10

The second one doesn’t work on Windows 7 but does work on Windows 2008 R2.  There are other cmdlets that have problems with localhost so I advise against using it. My preference is to use $env:COMPUTERNAME

You might try this

"Win7", "Win7Test", "WebR201" |
Get-Process |
sort Workingset -Descending |
select -First 10

Note its still one pipeline – just split across multiple lines to make reading easier

But you’ll get an error

Get-Process : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of
the parameters that take pipeline input.

The problem is that the computername will only take pipeline input based on property name – so it expects an object that will have a computername property.

PS> get-help Get-Process -Parameter computername

-ComputerName <string[]>
    Gets the processes running on the specified computers. The default is the local computer.

    Type the NetBIOS name, an IP address, or a fully qualified domain name of one or more computers. To specify the loc
    al computer, type the computer name, a dot (.), or "localhost".

    This parameter does not rely on Windows PowerShell remoting. You can use the ComputerName parameter of Get-Process
    even if your computer is not configured to run remote commands.

    Required?                    false
    Position?                    named
    Default value
    Accept pipeline input?       true (ByPropertyName)
    Accept wildcard characters?  false

You can get round that like this

Get-Process -ComputerName "Win7", "Win7Test", "WebR201" 
sort Workingset -Descending |
select -First 10

but you then hit the problem that you can’t differentiate the results from each machine.

You also need to have a number of services running on the remote machine including the Remote Registry service AND the firewall configured to allow remote management.

This is starting to get messy.

Remember that remoting was enabled across the domain. This means we can do this

Invoke-Command -ComputerName "Win7", "Win7Test", "WebR201"  -ScriptBlock {
Get-Process |
sort Workingset -Descending |
select -First 10 }

Still a single pipeline.  The big advantage is that we get a property – PSComputerName – tacked onto the output that enables us to decide on the source of the data. That should answer all of requirements in the event. The computer names could be fed to Invoke-Command through a file or pipeline.

Change the script to this

Invoke-Command -ComputerName "Win7", "Win7Test", "WebR201"  -ScriptBlock {
Get-Process |
sort Workingset -Descending |
select -First 10 } |
Format-Table -GroupBy PSComputerName –AutoSize

and you have a nicely formatted output. Push that to a file

Invoke-Command -ComputerName "Win7", "Win7Test", "WebR201"  -ScriptBlock {            
Get-Process |            
sort Workingset -Descending |             
select -First 10 } |            
Format-Table -GroupBy PSComputerName -AutoSize |            
Out-File top10proc.txt

and you have a report ready to give to the boss.

Jobs a goodun!

Oh you want aliases.  Well if you must

icm -Cn "Win7", "Win7Test", "WebR201"  -Sc {

ps |

sort WS -Des |

select -F 10 }

trying to alias or abbreviate parameters can be problematic because the abbreviation must be resolvable unambiguously. Unless you really know the parameters on a cmdlet it can be confusing and take extra time to get right – its why I never bother and just use tab completion!

April 10, 2012  12:56 PM

Using aliases and the myth of the one-liner

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

The beginners section of the scripting games can be often answered with one pipeline of PowerShell.

Notice that I stated one pipeline not one line

Since the early days of PowerShell there has been an almost mystical reverence  paid to the concept of the “one-liner” ie boiling the PowerShell script down to a single line. That worked as a concept in PowerShell v1 where all we had was the console. When PowerShell v2 appeared with the ISEit was time to ditch the one line concept and switch our attention to what is important – using the PowerShell pipeline.

The pipeline symbol acts as a line continuation character so in ISE or any other PowerShell aware editor/environment you can split your pipeline over multiple lines of text BUT STILL HAVE A SINGLE PIPELINE.

Its more readable and easier to work with especially when debugging.

With PowerShell v3 and the changes to ISE it is finally time to kill the myth of the one liner and actually be honest about what we are trying to achieve – the one pipeline.

In a similar vein there is a lot of talk about how we should use aliases at the command prompt.

Why?

With tab completion it is almost as quick to use the full name for cmdlets and parameters especially if you have to look up the alias. If you like them fine but I prefer not to use them so that what ever I experiment with at the prompt can be copied straight into scripts.


April 9, 2012  2:44 AM

Scripting Games 2012 Comments: #2 Read the help file

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

I’m seeing a lot of scripts where code is used to perform an action that is available as a parameter on a cmdlet that is used earlier in the pipeline.

 

Read the help file for the cmdlets you are going to use to see how you can get PowerShell to do the work for you instead you having to create and test code


April 8, 2012  7:54 AM

Scripting Games 2012 Comments: #1 Line Continuation

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

As with previous games I’ll publish a series of comments on the games. I won’t deal with any event specific issues until the games events are all closed but there are some things coming through that while not affecting any gradings don’t make the best use of PowerShell.

The first one that’s jumped out is line continuation.

I’ve seen a number of examples like the following two

get-service | `
sort status  -Descending

or

get-service  `
| sort status  -Descending

Both work but the line continuation character is unnecessary

All you need to do is

get-service |
sort status  -Descending

The pipeline symbol also works as a line continuation.

A minor point maybe but let PowerShell do the work for you


April 6, 2012  7:32 AM

2012 games–5 events published

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

We’re just about at the halfway point with 5 events available – remember there is only a week to complete an event. Deadlines start on Monday.

The overall quality of submissions from what I’ve seen so far is up on last year which is an achievement. What is staggering is that we’ve already had as many entries as we had in total last year.

Its going to be a busy time for the judges Smile


April 2, 2012  12:39 PM

Scripting Games have started

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Jump over to http://blogs.technet.com/b/heyscriptingguy/

for event 1 in the beginners and advanced categories


April 2, 2012  12:33 PM

Finding the primary name of a DNS alias record

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

A forum question asked how to find the primary name from an alias or CNAME record.

Get-WmiObject -Namespace 'root\MicrosoftDNS' -Class MicrosoftDNS_CNAMEType `
-Filter "ContainerName = 'Manticore.org'" -ComputerName server02  |             
select @{N='Alias'; E={$_.Ownername}}, Primaryname            

 

use the MicrosoftDNS_CNAMEType class. Filter on the domain ie containername.  ComputerName holds the DNS server name.

Change OwnerName to Alias in a select calculated field


April 1, 2012  10:09 AM

MVP renewal 2012

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

My MVP award was renewed for another year today.

Thank you to Microsoft for bestowing the honour for the fifth year and thank you to all of the people who’ve helped me gain this award by posting questions, reading my blogs, listening to talks etc.


March 30, 2012  8:49 AM

PowerShell in Practice offer today only

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Manning have PowerShell in Practice on a half price offer today. Go to www.manning.com and use code dotd0330cc when ordering


March 29, 2012  2:57 PM

UK PowerShell Group March 2012 meeting recording

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

 

The recording, slides and demo script from the session on CIM cmdlets – Tuesday 27 March is available

https://skydrive.live.com/?cid=43cfa46a74cf3e96#cid=43CFA46A74CF3E96&id=43CFA46A74CF3E96%212955

Enjoy


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: