PowerShell for Windows Admins


January 24, 2012  4:07 PM

Recording–UK PowerShell group January 2012



Posted by: Richard Siddaway
PowerShell 3, User Group

The recording of tonight’s meeting together with the slides and demo scripts are available from

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

 

download the zip file from the 2012 January PowerShell v3 CTP2 overview folder

 

Enjoy

January 23, 2012  1:24 PM

Get-CimClass



Posted by: Richard Siddaway
PowerShell 3, WMI

Get-CimClass is used to dig into the information available within a WMI class.

At its most basic level we get a set of information like this

PS> Get-CimClass -ClassName Win32_OperatingSystem | fl *

ClassName           : Win32_OperatingSystem
SuperClassName      : CIM_OperatingSystem
CimSuperClassName   : CIM_OperatingSystem
SuperClass          : Microsoft.Management.Infrastructure.CimClass
CimSuperClass       : Microsoft.Management.Infrastructure.CimClass
Namespace           : ROOT/cimv2
Properties          : {Caption, Description, InstallDate, Name…}
CimClassProperties  : {Caption, Description, InstallDate, Name…}
Qualifiers          : {Locale, UUID, dynamic, provider…}
CimClassQualifiers  : {Locale, UUID, dynamic, provider…}
Methods             : {Reboot, Shutdown, Win32Shutdown, Win32ShutdownTracker…}
CimClassMethods     : {Reboot, Shutdown, Win32Shutdown, Win32ShutdownTracker…}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties

 

We get a few parameters to work with

PS> Get-Help Get-CimClass

NAME
    Get-CimClass

SYNTAX
    Get-CimClass [[-ClassName] <string>] [[-Namespace] <string>] [-OperationTimeoutSec <UInt32>] [-ComputerName
    <string[]>] [-MethodName <string>] [-PropertyName <string>] [-QualifierName <string>]  [<CommonParameters>]

    Get-CimClass [[-ClassName] <string>] [[-Namespace] <string>] [-OperationTimeoutSec <UInt32>] -CimSession
    <CimSession[]> [-MethodName <string>] [-PropertyName <string>] [-QualifierName <string>]  [<CommonParameters>]

 

Want to know which WMI classes have a method called create

PS> Get-CimClass -MethodName Create

   NameSpace: ROOT/cimv2

ClassName                 Methods              Properties
———                 ——-              ———-
Win32_ShadowStorage       {Create}             {AllocatedSpace, DiffVolume, MaxSpace, UsedSpace…}
Win32_ScheduledJob        {Create, Delete}     {Caption, Description, InstallDate, Name…}
Win32_DfsNode             {Create}             {Caption, Description, InstallDate, Name…}
Win32_BaseService         {StartService, St… {Caption, Description, InstallDate, Name…}
Win32_SystemDriver        {StartService, St… {Caption, Description, InstallDate, Name…}
Win32_Service             {StartService, St… {Caption, Description, InstallDate, Name…}
Win32_TerminalService     {StartService, St… {Caption, Description, InstallDate, Name…}
Win32_Share               {Create, SetShare… {Caption, Description, InstallDate, Name…}
Win32_ClusterShare        {Create, SetShare… {Caption, Description, InstallDate, Name…}
Win32_ShadowCopy          {Create, Revert}     {Caption, Description, InstallDate, Name…}
Win32_Process             {Create, Terminat… {Caption, Description, InstallDate, Name…}

 

or a property called Size

PS> Get-CimClass -PropertyName Size

   NameSpace: ROOT/cimv2

ClassName
———
Win32_DiskDrive
Win32_CDROMDrive
CIM_LogicalDisk
Win32_LogicalDisk
Win32_MappedLogicalDisk
Win32_DiskPartition
Win32_PrintJob

We can dig deeper into a class

Get-CimClass -ClassName Win32_OperatingSystem | select -ExpandProperty Properties

provides an output like this for every property

Name               : CSName
Value              :
CimType            : String
Flags              : Property, ReadOnly, NullValue
Qualifiers         : {CIM_Key, MaxLen, Propagated, read}
ReferenceClassName :

 

Likewise methods

Get-CimClass -ClassName Win32_OperatingSystem | select -ExpandProperty Methods

 

or if you want detail on a particular method

PS> Get-CimClass -ClassName Win32_OperatingSystem | select -ExpandProperty Methods | where name -eq SetDateTime | fl *

Name       : SetDateTime
ReturnType : UInt32
Parameters : {LocalDateTime}
Qualifiers : {Implemented, Privileges, ValueMap}

 

And no thats not a typo on the where statement – its a new PowerShell v3 feature I’ll cover another day

Get-CimClass -ClassName Win32_OperatingSystem  | select -ExpandProperty Qualifiers

and

Get-CimClass -ClassName Win32_OperatingSystem  | select -ExpandProperty CimSystemProperties | fl *

do what you would expect

Finding the key property for a class is a useful exercise

Get-CimClass -ClassName Win32_Process | select -ExpandProperty Properties | where {$_.Qualifiers -like "*key*"}

returns a number of properties – some are like this

Name               : CreationClassName
Value              :
CimType            : String
Flags              : Property, ReadOnly, NullValue
Qualifiers         : {CIM_Key, MaxLen, read}
ReferenceClassName :

 

and have the CIM_Key qualifier but the one we are really interested in is this one

Name               : Handle
Value              :
CimType            : String
Flags              : Property, Key, ReadOnly, NullValue
Qualifiers         : {key, MaxLen, read}
ReferenceClassName :

 

Lots of useful information to be gained from this cmdlet. Don’t leave home to explore WMI without it.


January 22, 2012  7:58 AM

January meeting reminder



Posted by: Richard Siddaway
PowerShell 3, User Group

Just a quick reminder that on Tuesday 24 January the UK PowerShell Group presents a Live Meeting looking at PowerShell v3 CTP2

 

Details from here

http://msmvps.com/blogs/richardsiddaway/archive/2012/01/02/uk-powershell-group-january-2012.aspx


January 21, 2012  7:28 AM

SMART disk failure data



Posted by: Richard Siddaway
Disks, PowerShell, WMI

We can access the SMART disk failure data using

Get-WmiObject -Namespace root\wmi -Class MSStorageDriver_FailurePredictData

 

The important properties are:

Active           : True
InstanceName     : IDE\DiskST9250320AS_____________________________HP07____\5&b0fd174&0&1.0.0_0
Length           : 512
VendorSpecific   : {10, 0, 1, 15…}

 

The data we want is in the VendorSpecific property. On my system its an array of 512 numbers – not very useful but we can (hopefully) decode this

function get-diskstatus {            
[CmdletBinding()]            
param (            
 [string]$computername = $env:COMPUTERNAME            
)            
            
$items = "Unknown1","Unknown2", "Attribute", "Status", "Unknown3", "Value", "Worst", "Raw1", "Raw2", "Unknown4","Unknown5","Unknown6"            
            
$data = Get-WmiObject -Namespace root\wmi -Class MSStorageDriver_FailurePredictData -ComputerName $computername             
            
#$data | select InstanceName, Active            
            
$values = $data.VendorSpecific            
$flb =  $values.Count - ($values.Count % 12) -1            
            
for ($i = 0; $i -le $flb-11; $i += 12  ){            
            
$obj = New-Object -TypeName PSObject            
            
for($j = 0; $j -le 11; $j++) {             
$obj | Add-Member -MemberType Noteproperty -Name $($items[$j]) -Value $($values[$i + $j])            
}            
$obj            
}            
}            

 

We can use this as

get-diskstatus | ft * –a

 

I only have a single disk in my system so this works – I’ll need to modify the function to deal with multiple disks

 

But this is what I get back

 

Unknown1 Unknown2 Attribute Status Unknown3 Value Worst Raw1 Raw2 Unknown4 Unknown5 Unknown6

——– ——– ——— —— ——– —– —– —- —- ——– ——– ——–

      10        0         1     15        0   114    99   62  168       88        4        0

       0        0         3      2        0    99    99    0    0        0        0        0

       0        0         4     51        0    99    99   95    5        0        0        0

       0        0         5     51        0   100   100   17    0        0        0        0

       0        0         7     15        0    81    60  227   94      126        8        0

       0        0         9     50        0    90    90  132   34        0        0        0

       0        0        10     19        0   100   100    0    0        0        0        0

       0        0        12     51        0    99    99  248    4        0        0        0

       0        0       184     51        0   100   100    0    0        0        0        0

       0        0       187     50        0   100   100    0    0        0        0        0

       0        0       188     50        0   100    99   11    0        0        0        0

       0        0       189     58        0   100   100    0    0        0        0        0

       0        0       190     34        0    56    51   44    0       20       45        0

       0        0       191     50        0   100   100   54    0        0        0        0

       0        0       192     50        0   100   100    0    0        0        0        0

       0        0       193     50        0    96    96  166   34        0        0        0

       0        0       194     34        0    44    49   44    0        0        0       16

       0        0       195     26        0    51    49   62  168       88        4        0

       0        0       196     51        0   100   100   17    0        0        0        0

       0        0       197     18        0   100   100    0    0        0        0        0

       0        0       198     16        0   100   100    0    0        0        0        0

       0        0       199     62        0   200   200    0    0        0        0        0

       0        0       254     50        0   100   100    0    0        0        0        0

       0        0         0      0        0     0     0    0    0        0        0        0

       0        0         0      0        0     0     0    0    0        0        0        0

       0        0         0      0        0     0     0    0    0        0        0        0

       0        0         0      0        0     0     0    0    0        0        0        0

       0        0         0      0        0     0     0    0    0        0        0        0

       0        0         0      0        0     0     0    0    0        0        0        0

       0        0         0      0        0     0     0    0    0        0        0        0

       0        0         0      0      200     2     0  115    3        0        1        0

       2       92         3      0        0     0     0    0    0        0        0        0

       0        0         0      0        0     0     0    0    4        1        1        1

       1        1         1      1        1     0     0    0    0        0        0        0

       0        1         0      0        0     0     0    0    0        0        0        0

      54        0         0      0       33   186   100  101  238       28        0        0

       0        0         0      0        1     0   189    1  172      221      133      205

      35        0         0      0      154    12   230  180  219        1        0        0

       0        0         0      0        0   187    32    0    0        0        0        0

       0        0         0      0      105    36     0    0    0        0        0        0

       0        0         0      0        0     0     0    0    0        0        0        0

       0        0         0      0        0     0     0    0    0        0        0        0

 

Next job is to decode some of this information


January 20, 2012  2:58 PM

SMART disks



Posted by: Richard Siddaway
Disks, PowerShell, WMI

A question on the forum about using WMI to work with SMART disks got my digging into the subject.  SMART disks – http://en.wikipedia.org/wiki/S.M.A.R.T – detect and report on disk problems (hopefully) before they cause a catastrophe. While vendors’ implementations vary there are some things we can access.

The WMI classes are in the root\wmi namespace

PS> Get-WmiObject -Namespace root\wmi -List MSStorageDriver_Failure* | select Name

Name
—-
MSStorageDriver_FailurePredictEvent
MSStorageDriver_FailurePredictFunction
MSStorageDriver_FailurePredictData
MSStorageDriver_FailurePredictThresholds
MSStorageDriver_FailurePredictStatus

 

The most immediate concern is – what is the status of our disks

function test-diskstatus {            
[CmdletBinding()]            
param (            
 [string]$computername = $env:COMPUTERNAME            
)            
            
Get-WmiObject -Namespace root\wmi -Class MSStorageDriver_FailurePredictStatus -ComputerName $computername |            
select InstanceName, Active, PredictFailure, Reason            
            
}

The InstanceName is long so the best display is list

PS> test-diskstatus | fl


InstanceName   : IDE\DiskST9250320AS_____________________________HP07____\5&b0fd174&0&1.0.0_0

Active         : True

PredictFailure : False

Reason         : 0

 

The PredictFailure is the the important property & we worry when it is true!


January 18, 2012  1:54 PM

WMI associations through CIM cmdlets



Posted by: Richard Siddaway
PowerShell 3, WMI

The CIM cmdlets that introduced in PowerShell v3 give us a different API for working with WMI. We can still work with associations just in a slightly different way.

 

NOTE – this done on a different machine to the previous one so the adapters are different

 

We get the instances of a WMI class like this

Get-CimInstance -ClassName Win32_NetworkAdapter

 

we can filter to a specific instance

Get-CimInstance -ClassName Win32_NetworkAdapter -Filter "DeviceId=7"

 

if we put that in a variable

$nic = Get-CimInstance -ClassName Win32_NetworkAdapter -Filter "DeviceId=7"

 

then we can see all of the associated classes like this

Get-CimAssociatedInstance -CimInstance $nic

 

You might think that we would do this to get a specific associated class

Get-CimAssociatedInstance -CimInstance $nic -Association Win32_NetworkAdapterConfiguration

 

Nope – we don’t just to be different.

We need to back track a minute. When two classes are linked there is normally a linking class (reference) the shows the links. We can see this by running

Get-CimClass -ClassName *NetworkAdapter*

which shows a class Win32_NetworkAdapterSetting

so if we try

PS> Get-CimInstance -ClassName Win32_NetworkAdapterSetting

Element                                                     Setting
——-                                                     ——-
Win32_NetworkAdapter (DeviceID = "0")                       Win32_NetworkAdapterConfiguration (Index = 0)
Win32_NetworkAdapter (DeviceID = "1")                       Win32_NetworkAdapterConfiguration (Index = 1)
Win32_NetworkAdapter (DeviceID = "2")                       Win32_NetworkAdapterConfiguration (Index = 2)
Win32_NetworkAdapter (DeviceID = "3")                       Win32_NetworkAdapterConfiguration (Index = 3)
Win32_NetworkAdapter (DeviceID = "4")                       Win32_NetworkAdapterConfiguration (Index = 4)
Win32_NetworkAdapter (DeviceID = "5")                       Win32_NetworkAdapterConfiguration (Index = 5)
Win32_NetworkAdapter (DeviceID = "6")                       Win32_NetworkAdapterConfiguration (Index = 6)
Win32_NetworkAdapter (DeviceID = "7")                       Win32_NetworkAdapterConfiguration (Index = 7)
Win32_NetworkAdapter (DeviceID = "8")                       Win32_NetworkAdapterConfiguration (Index = 8)
Win32_NetworkAdapter (DeviceID = "9")                       Win32_NetworkAdapterConfiguration (Index = 9)
Win32_NetworkAdapter (DeviceID = "10")                      Win32_NetworkAdapterConfiguration (Index = 10)
Win32_NetworkAdapter (DeviceID = "11")                      Win32_NetworkAdapterConfiguration (Index = 11)
Win32_NetworkAdapter (DeviceID = "12")                      Win32_NetworkAdapterConfiguration (Index = 12)

 

Which is cool – we can see the links

A quicker way to discover this linking class is to do

Get-CimClass -ClassName *NetworkAdapter* -Qualifier "Association"

Now how do we use this link

Get-CimAssociatedInstance -CimInstance $nic -Association Win32_NetworkAdapterSetting

ServiceName      DHCPEnabled      Index       Description
———–      ———–      —–       ———–
netvsc           False            7           Microsoft Virtual Machine Bus …

 

which we know from the output above is the correct link

Same answer as WMI using a WQL query or GetRelated – just a different route


January 18, 2012  1:29 PM

Running a function



Posted by: Richard Siddaway
PowerShell

Most of my scripts end up being functions because I will eventually combine them into modules

My recent script

function get-logedonuser {                        
param (                        
 [string]$computername = $env:COMPUTERNAME                        
)                        
Get-WmiObject -Class Win32_LogonSession -ComputerName $computername |                        
foreach {                        
 $data = $_                        
                        
 $id = $data.__RELPATH -replace """", "'"                        
 $q = "ASSOCIATORS OF {$id} WHERE ResultClass = Win32_Account"                        
 Get-WmiObject -ComputerName $computername -Query $q |                        
 select @{N="User";E={$($_.Caption)}},                         
 @{N="LogonTime";E={$data.ConvertToDateTime($data.StartTime)}}                        
}                        
}

Prompted a comment about how could you run this script.

First off I would save it to a file – get-logedonuser.ps1

You can then either

Open PowerShell Integrated Scripting Environment (ISE) and the open the file. if you run the file the function is added into memory and you can run it as get-logedonuser

 

OR

open the PowerShell console, change to the folder where you saved the file, and run . ./get-logedonuser.ps1

This “dot sources” the script and leaves the function in memory. Then run get-logedonuser as before


January 18, 2012  1:18 PM

Associated Classes



Posted by: Richard Siddaway
PowerShell v2, WMI

If I run

Get-WmiObject -Class Win32_NetworkAdapter

I get a list of the Network Adapters in my system plus some information about the adapter.  What I don’t get is the IP addressing and other configuration information because it is stored on the Win32_NetworkAdapterConfiguration class.

 

The key property on Win32_NetworkAdapter is DeviceId.  My wireless card is DeviceId 11.

 

There is an association between the Win32_NetworkAdapter class and the corresponding Win32_NetworkAdapterConfiguration class. The Win32_NetworkAdapterConfiguration  class uses Index to identify the card and

Win32_NetworkAdapter.DeviceId = Win32_NetworkAdapterConfiguration.Index

So I could  do this

Get-WmiObject -Class Win32_NetworkAdapter -Filter "DeviceID=11"

Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "Index=11"

 

A better way is work through the association

$nic = Get-WmiObject -Class Win32_NetworkAdapter -Filter "DeviceID=11"
$nic
$q = "ASSOCIATORS OF {Win32_NetworkAdapter.DeviceID=$($nic.DeviceID)} WHERE ResultClass = Win32_NetworkAdapterConfiguration"
Get-WmiObject -Query $q

 

I tend to use WQL but there is an alternative

$nic = Get-WmiObject -Class Win32_NetworkAdapter -Filter "DeviceID=11"
$nic
$nic.GetRelated("Win32_NetworkAdapterConfiguration")

 

The WMI object has a GetRelated() method

if you just do

$nic.GetRelated()

you will get all associations – its the equivalent of

$q = "ASSOCIATORS OF {Win32_NetworkAdapter.DeviceID=$($nic.DeviceID)} "
Get-WmiObject -Query $q

 

One slight problem is that if you do

$nic | Get-Member

you won’t see the method – you will need to do this

$nic | Get-Member -View base

 

Which one should you use?  Its your choice. I tend to use WQL out of habit but GetRelated() is less typing.


January 17, 2012  3:00 PM

Get the logged on users



Posted by: Richard Siddaway
PowerShell v2, Users, WMI

Do you know which users are logged on to your systems?

Want to find out?

function get-logedonuser {            
param (            
 [string]$computername = $env:COMPUTERNAME            
)            
Get-WmiObject -Class Win32_LogonSession -ComputerName $computername |            
foreach {            
 $data = $_            
            
 $id = $data.__RELPATH -replace """", "'"            
 $q = "ASSOCIATORS OF {$id} WHERE ResultClass = Win32_Account"            
 Get-WmiObject -ComputerName $computername -Query $q |            
 select @{N="User";E={$($_.Caption)}},             
 @{N="LogonTime";E={$data.ConvertToDateTime($data.StartTime)}}            
}            
}

 

Use the Win32_LogonSession class and then find the associated Win32_Account classes.  It does work for domain and local accounts


January 16, 2012  2:43 PM

CIM sessions



Posted by: Richard Siddaway
PowerShell 3, WMI

When we last looked at the CIM cmdlets we saw that by default they use WSMAN to access remote computers but this only works if the remote computer is running PowerShell v3 with version 3.0 of the WSMAN stack.

We can force the CIM cmdlets to use DCOM by configuring a CIM session. These are analogous to PSsessions we create when using PowerShell remoting.

CIM sessions default to WSMAN – everything with CIM defaults to WSMAN unless you are accessing the local machine

PS> $sw = New-CimSession -ComputerName webr201
PS> $sw

Id           : 1
Name         : CimSession1
InstanceId   : 91ad5f5e-d5a9-4776-9965-3c520f8bb9a0
ComputerName : webr201
Protocol     : WSMAN

 

Get-CimInstance -CimSession $sw -ClassName Win32_ComputerSystem

 

Now returns the result over the session. Using a session or using

Get-CimInstance -ClassName Win32_ComputerSystem -computername webr201

 

both return an object of type

Microsoft.Management.Infrastructure.CimInstance#root/cimv2/Win32_ComputerSystem

 

So how do we create a session using DCOM?

 

PS> $opt = New-CimSessionOption -Protocol DCOM
PS> $sd = New-CimSession -ComputerName server02 -SessionOption $opt
PS> $sd

Id           : 2
Name         : CimSession2
InstanceId   : 3066aa29-7062-423d-a0ab-13b29cd86013
ComputerName : server02
Protocol     : DCOM

 

This session is used in the same way as a WSMAN session

Get-CimInstance -CimSession $sd -ClassName Win32_ComputerSystem

 

and returns the same object type.

We can even mix and match CIMsessions over WSMAN and DCOM

 

PS> Get-CimInstance -CimSession $sw, $sd -ClassName Win32_ComputerSystem | Format-Table Name, TotalPhysicalMemory –AutoSize

Name     TotalPhysicalMemory
—-     ——————-
SERVER02         17108066304
WEBR201            536403968

 

The CimSession parameter takes pipeline input so we can do this

Get-CimSession | Get-CimInstance -ClassName Win32_ComputerSystem | Format-Table Name, TotalPhysicalMemory –AutoSize

 

which has to be a cool way to access remote machines.


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: