PowerShell for Windows Admins


May 26, 2010  12:29 PM

PowerShell in Practice ebook deal



Posted by: Richard Siddaway
Books, PowerShell v2

I know there isn’t much of today left but if you are quick its possible to get an ebook version of PowerShell in Practice for $15.  See the deal of the day at http://www.manning.com/

May 24, 2010  3:14 PM

Query me no more



Posted by: Richard Siddaway
PowerShell v2, WMI

One of the things I noticed in the recent Scripting Games was that a lot of the scripts would do things like this

$query = "Select MaxClockSpeed from Win32_Processor"
$proc = Get-WmiObject -Query $query
Write-Host "Speed: " $proc.MaxClockSpeed

Create a query to access the Win32_Processor class to get the MaxClockSpeed.  Run the query and then use Write-Host to format and output the results.  We’ll come back to use Write-Host like this another time.

This construction is based on the way things used to be done with VBScript.  With PowerShell we have much easier ways to get to the same result.

Get-WmiObject -Class Win32_Processor | Format-List MaxClockSpeed

will produce the same answer. if you really need the formatting

Get-WmiObject -Class Win32_Processor | Format-List @{Name=’Speed’; Expression={$_.MaxClockSpeed}}

or even

Write-Host "Speed: " (Get-WmiObject -Class Win32_Processor).MaxClockSpeed

Get-WmiObject does a great job of returning the information from a WMI class. Use its power and simplicity to make your scripts quicker to write and easier to understand


May 21, 2010  12:52 PM

Quick ping



Posted by: Richard Siddaway
Automation, PowerShell v2, WMI

If you’ve used ping before you’ll know that it normally returns four replies from the target.  In PowerShell we have Test-Connection which does the same job. It also normally returns four replies.

When I’m working with remote machines I often want to check they are available before sending a command – especially a WMI command that can take a long time to time out.

001
002
003
004
005
006
007
008
"rslaptop01", "127.0.0.1" | 
foreach {
    if (Test-Connection $_ -Count 1) {
        Get-WmiObject -ComputerName $_ -Class Win32_LogicalDisk `
        -Filter "DriveType=’3′" |
        select SystemName, DeviceID, Size, FreeSpace
    }
}

To speed up the process use the –Count parameter on test-connection and only get 1 reply.  Quick test to see if he system is there and then run the rest of the code


May 18, 2010  2:09 PM

UG May 2010 Recording, Slides and demo



Posted by: Richard Siddaway
PowerShell v2, User Group, WMI

Thank you to everyone who joined the Live Meeting this evening. Hope you enjoyed the session on PowerShell events.

The slides and demo files are available from

http://cid-43cfa46a74cf3e96.skydrive.live.com/browse.aspx/PowerShell%20User%20Group/May%202010

 

The recording can be viewed on line

View Recording
Recording Details
    Subject: PowerShell Events
    Recording URL: https://www.livemeeting.com/cc/usergroups/view
    Recording ID: 39Q7T9
    Attendee Key: Q&x!_63dP


May 15, 2010  8:41 AM

hey ho hey ho its off to print we go



Posted by: Richard Siddaway
Books, PowerShell v2

PowerShell in Practice will be going to the printers next week.

Between now and 21 May 2010 you can get 40% off of PowerShell in Practice (and other Manning books that are in the final stages of production)

Use promotional code m1440 at checkout from www.manning.com


May 12, 2010  3:06 PM

WMI and the Registry



Posted by: Richard Siddaway
PowerShell v2, Registry, WMI

We can use WMI to access the registry on local and remote machines – if you remember back to VBScript it was the way to access the registry.

In PowerShell we have a couple of PowerShell drives available  through the provider

Name           Used (GB)     Free (GB) Provider      Root
—-           ———     ——— ——–      —-
HKCU                                   Registry      HKEY_CURRENT_USER
HKLM                                   Registry      HKEY_LOCAL_MACHINE

These only work with the local machine.  We can use PowerShell remoting to access the registry but if PowerShell isn’t installed we are back to WMI.

The class we need to use is StdRegprov

In Windows XP\2003 and earlier it is only found in the root\default namespace. In Windows Vista\2008 and above it is also found in the root\cimv2 namespace (which is the default namespace PowerShell uses). In order to access most machines we will work with the root\default instance. We need to use the [wmiclass] type accelerator

$reg = [wmiclass]\\.\root\default:StdRegprov

looking at $reg though get-member we see a lot of methods

CheckAccess
CreateKey
DeleteKey
DeleteValue
EnumKey
EnumValues
GetBinaryValue
GetDWORDValue
GetExpandedStringValue
GetMultiStringValue
GetQWORDValue
GetSecurityDescriptor
GetStringValue
SetBinaryValue
SetDWORDValue
SetExpandedStringValue
SetMultiStringValue
SetQWORDValue
SetSecurityDescriptor
SetStringValue

We will start looking at these next time


May 4, 2010  3:07 PM

String Substitution with WMI



Posted by: Richard Siddaway
PowerShell v2, WMI

String substitution is one of my favourite bits of PowerShell. If you’ve not seen it before the idea is that you can substitute a variable into a double quoted string.  Note that single quote strings won’t work. As an example

PS> $colour = "red"
PS> "The balloon is $colour"
The balloon is red
PS> ‘The balloon is $colour’
The balloon is $colour

One place this breaks down in when substituting properties of an object.  Consider something we’ve pulled back with WMI.

PS> $os = Get-WmiObject -Class Win32_OperatingSystem
PS> $os

SystemDirectory : C:\Windows\system32
Organization    :
BuildNumber     : 7600
RegisteredUser  : Richard
SerialNumber    : 00426-065-1155216-86852
Version         : 6.1.7600

We can pick off a couple of properties

PS> $os | select Caption, ServicePackMajorVersion | Format-List

Caption                 : Microsoft Windows 7 Ultimate
ServicePackMajorVersion : 0

 

We can use write-host

PS> Write-Host $os.Caption, $os.ServicePackMajorVersion
Microsoft Windows 7 Ultimate  0

 

and even expand it a bit

PS> Write-Host $os.Caption, "Service Pack", $os.ServicePackMajorVersion
Microsoft Windows 7 Ultimate  Service Pack 0

but if we try string substitution

PS> Write-Host "The OS is $os.Caption with Service Pack $os.ServicePackMajorVersion"
The OS is \\RSLAPTOP01\root\cimv2:Win32_OperatingSystem=@.Caption with Service Pack \\RSLAPTOP01\root\cimv2:Win32_OperatingSystem=@.ServicePackMajorVersion

Oops – thats not what we want

The problem is that we are getting the object rather than the value.  We need to use a subexpression

PS> Write-Host "The OS is $($os.Caption) with Service Pack $($os.ServicePackMajorVersion)"
The OS is Microsoft Windows 7 Ultimate  with Service Pack 0

 

All this does is say give me the result of the expression in the brackets and substitute that in the string. Easy and neat. No need to concatenate strings to create the display line in your scripts.


May 3, 2010  1:05 PM

PowerShell UG May 2010



Posted by: Richard Siddaway
PowerShell v2, User Group
When: Tuesday, May 18, 2010 7:30 PM (BST)

Where: Live Meeting 

*~*~*~*~*~*~*~*~*~*

PowerShell eventing using WMI, .NET and the PowerShell engine

Notes

Richard Siddaway has invited you to attend an online meeting using Live Meeting.
Join the meeting.
Audio Information
Computer Audio
To use computer audio, you need speakers and microphone, or a headset.
First Time Users:
To save time before the meeting, check your system to make sure it is ready to use Microsoft Office Live Meeting.
Troubleshooting
Unable to join the meeting? Follow these steps:

  1. Copy this address and paste it into your web browser:

    https://www.livemeeting.com/cc/usergroups/join

  2. Copy and paste the required information:
    Meeting ID: 39Q7T9
    Entry Code: Q&x!_63dP
    Location: https://www.livemeeting.com/cc/usergroups

If you still cannot enter the meeting, contact support

Notice
Microsoft Office Live Meeting can be used to record meetings. By participating in this meeting, you agree that your communications may be monitored or recorded at any time during the meeting.


May 2, 2010  10:06 AM

Ping, Ping, Ping



Posted by: Richard Siddaway
PowerShell v2, WMI

If you’ve used VBScript in the past you will remember using Win32_PingStatus to test the connectivity to a remote machine. In the 2010 Scripting Games we’ve seen a lot of scripts testing if a remote machine can be contacted.

Many of the scripts contain code of the form

$query = "Select * from Win32_PingStatus WHERE Address = ’127.0.0.1′"
Get-WmiObject -Query $query

There’s nothing wrong with this and it does the job so any marks for testing remote connectivity will be awarded. This code is a direct translation of the VBScript code.

The query could be given as part of the call to Get-WmiObject bit we can make it easier by doing this:

Get-WmiObject -Class Win32_PingStatus -Filter "Address = ’127.0.0.1′"

The query after the WHERE statement becomes  the filter and we give the class directly.  Bit less typing and easier to read.

if we want this as part of a loop where we will be testing multiple machines then we can refine it to this

$computer = ’127.0.0.1′
Get-WmiObject -Class Win32_PingStatus -Filter "Address = ‘$computer’"

The $computer variable could be set as part of the loop control rather than as a direct variable. One thing to be aware of is that computername parameter isn’t supported in the way most WMI classes support it

Note that this is NOT supported

Get-WmiObject -Class Win32_PingStatus -ComputerName $computer

In PowerShell v2 it gets even simpler as we have a cmdlet that wraps Win32_PingStatus for us

Test-Connection -ComputerName $computer

but it returns four pings by default so use

Test-Connection -ComputerName $computer -Count 1

All of the above work but the last one is the easiest and involves least typing (remember tab completion)


April 26, 2010  3:56 PM

Desktop of current logged on user



Posted by: Richard Siddaway
Users

 

In this post http://itknowledgeexchange.techtarget.com/powershell/current-logged-on-user/ we discovered how to find the current logged on user.  I want to extend that a bit and add the information about that users desktop.

We start with the script in our earlier post.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
## get session process
$proc = Get-WmiObject -Class Win32_SessionProcess | 
select Antecedent -First 1
$filt = ($proc -split "=")[2] -replace ‘"’,  -replace "}",""

$ltype = DATA {
ConvertFrom-StringData -StringData @’
0 = System
2 = Interactive
3 = Network
4 = Batch
5 = Service
6 = Proxy
7 = Unlock
8 = NetworkCleartext
9 = NewCredentials
10 = RemoteInteractive
11 = CachedInteractive
12 = CachedRemoteInteractive
13 = CachedUnlock
‘@

}
## get logon session
$sess = Get-WmiObject -Class Win32_LogonSession -Filter "LogonId=’$filt’"

## get user
$query = "ASSOCIATORS OF {Win32_LogonSession.LogonId=’$filt’}" `
            + "WHERE ResultClass=Win32_UserAccount"
$user = Get-WmiObject -Query  $query

$query2 = "ASSOCIATORS OF {Win32_UserAccount.Domain=’$($user.Domain)’" `
  + ",Name=’$($user.Name)’} WHERE ResultClass=Win32_Desktop"

$desktop = Get-WmiObject -Query $query2
 
Add-Member -InputObject $sess -MemberType NoteProperty -Name User `
   -Value $($user.Caption) -PassThru |
Format-List AuthenticationPackage, LogonId,
@{Name="Logon Type"; Expression = {$ltype["$($_.LogonType)"]}},
@{Name="Time"; Expression = {$_.ConvertToDateTime($_.StartTime)}},
User
"Desktop Settings:"
$desktop | Format-List BorderWidth, Caption, CoolSwitch,
CursorBlinkRate, Description, DragFullWindows,
GridGranularity, IconSpacing, IconTitleFaceName,
IconTitleSize, IconTitleWrap, Name, Pattern,
ScreenSaverActive, ScreenSaverExecutable,
ScreenSaverSecure, ScreenSaverTimeout,
SettingID, Wallpaper, WallpaperStretched,
WallpaperTiled

We add a query to get the desktop associated with the current user  – - $query2

That query returns the information about the desktop. Its displayed after the user information and I’ve selected the items I want to display.

This is a good example of extending an existing script when you find out how to do a bit more digging.

I think we’ve about exhausted the WMI information on users and groups for now – so its time to find another topic.