PowerShell for Windows Admins


January 12, 2016  4:45 AM

European PowerShell conference 2016

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

PowerShell Conference EU combines the former “Deutsche PowerShell Konferenz” and “PowerShell Summit EU” into one great big 3-day PowerShell event for Admins and DevOps in Europe and takes place April 20-22 in Hannover/Germany. With more than 40 international speakers including PowerShell inventor Jeffrey Snover, and more than 60 sessions, you are cordially invited to join this massive European PowerShell event. The agenda is up on www.psconf.eu, and registration is open. Seats and hotel capacity are limited so don’t wait and register!

Psconf.eu is partnering with powershell.org and psconf.asia, and together we want to ensure that you have a comprehensive local PowerShell conference in your region of the

January 11, 2016  10:34 AM

Testing against an arrays contents

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

You may need to test if a value is a member of an array. PowerShell provides 2 operators for testing array membership  – –   -in and –contains.

Simple usage is like this

PS> $colours = ‘red’, ‘orange’, ‘yellow’, ‘green’, ‘blue’, ‘indigo’, ‘violet’

PS> ‘blue’ -in $colours
True
PS> $colours -contains ‘blue’
True

Note the order of value and array changes between the operators.

You  can also use these operators in Where-Object

PS> $testcolours = ‘blue’, ‘pink’, ‘yellow’

PS> $testcolours | where {$_ -in $colours}
blue
yellow
PS> $testcolours | where {$colours -contains $_}
blue
yellow

Often the value we want is a property of an object

PS> $to = New-Object -TypeName PSObject -Property @{Colour = ‘green’}
PS> $to1 = New-Object -TypeName PSObject -Property @{Colour = ‘pink’}

PS> $to, $to1 | where Colour -in $colours

Colour
——
green
PS> $to, $to1 | where {$colours -contains $_.Colour}

Colour
——
green

The –in operator can be used in the simplified Where-Object syntax (it was introduced for that purpose) but –contains has to use the full, original syntax

For testing non-membership you also get –notin and –notcontains

PS> $to, $to1 | where Colour -notin $colours

Colour
——
pink
PS> $to, $to1 | where {$colours -notcontains $_.Colour}

Colour
——
pink


January 8, 2016  1:49 PM

WMI discovery

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, Powershell, WMI

I’ve been working with System Center Configuration Manager this week. SCCM uses a lot of WMI. However, WMI discovery is still a bit of an art.

I needed to find the SMS_SCI_Component class.

If you know the namespace you can easily find the classes in that namespace but namespaces are hierarchical so you need to work down the tree.

The root namespace is at the top of the namespace tree so

C:\Scripts> Get-CimInstance -ClassName __NAMESPACE -Namespace root

Name
—-
subscription
DEFAULT
SCCMDP
CIMV2
msdtc
Cli
nap
MicrosoftIISv2
SECURITY
CCMVDI
NetworkModel
RSOP
SMS
ccm
StandardCimv2
WMI
AccessLogging
directory
Policy
InventoryLogging
Interop
Hardware
ServiceModel
Microsoft
aspnet

After a bit of digging I found I needed the sms namespace

PS C:\Scripts> Get-CimInstance -ClassName __NAMESPACE -Namespace ‘root\sms’

Name
—-
site_PS1

which leads to:

Get-CimInstance -ClassName SMS_SCI_Component -Namespace ‘root\sms\site_PS1’

 

What if you only know the class?

There’s a little trick using Get-WmiObject

Get-WmiObject -Namespace root -Recurse -List -Class SMS_SCI_Component
NameSpace: ROOT\SMS\site_PS1

Name
—-
SMS_SCI_Component

The trick is to start with the root namespace and use the –Recurse (search through all child namespaces) and –List (just give class details) parameters.  You’ll see a listing by namespace for each instance of the class discovered.


January 4, 2016  9:29 AM

Starting to use PowerShell

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

A common question goes along the lines of  “I’ve leant PowerShell (from class, book etc) but what do I do next?”

The usual answer is to pick a problem in your organisation and solve it.

I’ve provided an example in this UK TechNet blog post

http://blogs.technet.com/b/uktechnet/archive/2016/01/04/starting-your-powershell-journey.aspx

Its the second one of a series on PowerShell


January 2, 2016  10:34 AM

2015 December Scripting Games Puzzle

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

The December 2015 puzzle was based on the 12 Days of Christmas song.  Starting with this here-string.

$list = @”
1 Partridge in a pear tree
2 Turtle Doves
3 French Hens
4 Calling Birds
5 Golden Rings
6 Geese a laying
7 Swans a swimming
8 Maids a milking
9 Ladies dancing
10 Lords a leaping
11 Pipers piping
12 Drummers drumming
“@

A here-string is a multiline string. It is NOT an array – its a single string. The first task is to  split into an array of individual lines:

## split into individual lines
$s = $list -split ‘\n’

Each line of the multiline here string ends with a new line – so that becomes the split point.

The array can be sorted by length of line. Ascending or descending wasn’t specified so here’s both options:

‘Sort by length ascending’
$s | Sort-Object -Property Length

“`n ”
‘sort by length descending’
$s | Sort-Object -Property Length -Descending

Removing the numbers to give justthe text and sorting by length of text. I trmmed the strings as some empty spaces had appeared in the arrays. I think because I copied the here-string

“`n ”
‘remove numbers sort by length ascending’
$s.Trim() -replace ‘\d{1,2}\s’, ” | Sort-Object -Property Length #| group length | ft -a -wrap

“`n ”
‘remove numbers sort by length descending’
$s.Trim() -replace ‘\d{1,2}\s’, ” | Sort-Object -Property Length -Descending

Create objects. Split on white space and restrict output to 2 elements – number and text in this case. Create object using New-object

“`n ”
#’create objects’
$items = @()
$s.Trim() | foreach {
$item =  $psitem -split ‘\s’,2
$items += New-Object -TypeName PSObject -Property @{
Count = $item[0] -as [int]
Item = $item[1]
}
}

Count the number of birds

“`n ”
‘count of birds’
$birdcount = ($items -match ‘(Partridge|Doves|Hens|Birds|Geese|Swans)’ | Measure-Object -Property Count -Sum).Sum
$birdcount

Count all items

“`n ”
‘count of items’
$itemcount = ($items | Measure-Object -Property Count -Sum).Sum
$itemcount

If you treat the song as stating the gifts are cumulative then how many gifts are given in total.  Each item is given (13 – the day on which its given) times i.e. 12 to 1 times respectively.  The total number of items can be calculated like this

“`n ”
‘cumulative count of items’
$total = 0
$items | foreach {$total += $psitem.Count * (13-$psitem.Count) }
$total

As a bonus here’s how you calculate the cumulative number of each type of item.

“`n ”
‘cumulative number of each item’
$totalitems =@()
$items | foreach {
$totalitems += New-Object -TypeName PSObject -Property @{
Count = $psitem.Count * (13-$psitem.Count)
Item = $psitem.Item
}
}
$totalitems


January 2, 2016  6:43 AM

Happy New Year 2016

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

A new year and a number of things to which we can look forward.

The re-release of WMF 5.0. The WMF 5.0 download was pulled because a bug was over writing the module path. Look fot the download being available again soon.

Windows Server 2016 – Containers and Nano server give lots of new options for deployment and lots of new PowerShell to play with. There may even be other PowerShell changes – who knows given the new release processes.

In early April we have the PowerShell + DevOps Summit in Seattle. Late April sees the European PowerShell Conference in Hanover (tracks in German and English). Registration for both events is open.

The UK PowerShell group is reviving. After meetings in London and Manchester planning is underway for the next meetings – look for more info soon.

PowerShell in Action, third edition will appear.  Its already in early release and will complete this year.

A few other projects are in the pipeline which may or may not come to fruitition.

One prediction I can confidently make is that 2016 will NOT be the year that Unix/Linux conquers the desktop. 🙂


December 23, 2015  6:45 AM

Objects, properties and values

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Powershell

One thing that seems to keep causing confusion is using Select-Object to pick off one or more properties from a set of objects:

PS> Get-CimInstance -ClassName Win32_Share | select Path

Path
—-
C:\WINDOWS
C:\

C:\windows\system32\spool\drivers
C:\Users

The gap in the output is because the IPC$ share doesn’t have a path defined.

What you have is a ‘Selected’ version of the original object

PS> Get-CimInstance -ClassName Win32_Share | select Path | Get-Member

TypeName: Selected.Microsoft.Management.Infrastructure.CimInstance

Name        MemberType   Definition
—-        ———-   ———-
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
Path        NoteProperty string Path=C:\WINDOWS

Very often you’ll only want the value of the property. In which case you need to use the –ExpandProperty parameter on Select-Object

PS> Get-CimInstance -ClassName Win32_Share | select -ExpandProperty Path
C:\WINDOWS
C:\

C:\windows\system32\spool\drivers
C:\Users


December 23, 2015  6:39 AM

Infrastructure as Code article

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
DevOps, Powershell

My Infrastructiure as Code article – part of an introducing DevOps series – has gone live http://ed-baker.com/devops-practices-infrastructure-as-code/

You can also link to it through http://blogs.technet.com/b/uktechnet/ where you’ll find the first in my series of article on PowerShell. Second one will be coming in the New Year


December 22, 2015  9:36 AM

BinaryMiLog cmdlets

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, Powershell, WMI

It’s not often I come across soemthing brand new in PowerShell but yesterday when I was investigating New-CimInstance I discovered 2 cmdlets in the CimCmdlets module I hadn’t noticed before. These are:

Export-BinaryMiLog

Import-BinaryMiLog

The cmdlets are used to export, or import, CIM instances as a binary encoded file.  Think of them as  Export-Clixml and Import-Clixml but for CIM instances.

Their usage is very simple:

Get-CimInstance -ClassName Win32_OperatingSystem |
Export-BinaryMiLog -Path testfile.bmil

This creates a   30 KB binary file – its definitely not human readable!

You don’t need to use a bmil extension (its the one in the help file) and you can use a CIM instance object instead of the pipeline

$os = Get-CimInstance -ClassName Win32_OperatingSystem
Export-BinaryMiLog -InputObject $os -Path testfile2.stuff

Getting the data back is performed by Import-BinaryMiLog

$os1 = Import-BinaryMiLog -Path .\testfile.bmil
$os2 = Import-BinaryMiLog -Path .\testfile2.stuff

The results appear to be a standard CIM object

Compare-Object -ReferenceObject $os -DifferenceObject $os1 -IncludeEqual
Compare-Object -ReferenceObject $os -DifferenceObject $os2 -IncludeEqual
Compare-Object -ReferenceObject $os1 -DifferenceObject $os2 –IncludeEqual

These cmdlets give you way to persist CIM objects to disk so that they can be referenced at a later date. If you need to test for changes to a system this could be a useful technique


December 21, 2015  3:36 PM

New-CimInstance cmdlet and the–Key parameter

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, Powershell, WMI

I was asked a question about the –Key parameter on New-CimInstance today. I wasn’t sure of the answer so I’ve done some experimentation.

I tend to avoid New-CimInstance if I can preferring to use the Create method on the CIM class – however not all CIM classes have a create method so need to fall back on New-CimInstance.

I started by looking at the documentation. The help file for New-CimInstance says:

-Key<String[]>

Specifies the properties that are used as keys. CimSession and ComputerName cannot be used when Key is specified.

That then leads to the question how do I discover the Key or Keys of a CIM class.  You can’t use the –Qualifier parameter in Get-CimClass because that works at the class level and Key is a property qualifier.  Means you need to use some code

function Get-CimClassKey {

param (

[string]$CIMnamespace = ‘ROOT/cimv2’,

[string]$CIMclass

)

$class = Get-CimClass -Namespace $CIMnamespace -ClassName $CIMclass

foreach ($property in $class.CimClassProperties) {

$property | Select-Object -ExpandProperty Qualifiers |
foreach {
if ($_.Name -eq ‘key’){
$property
}
}

}
}

The Key property of a class HAS to be given a value when a new instance of the class is created.

The New-CimInstance help file shows an example using Win32_Environment.  Adapring the example:

PS> New-CimInstance -ClassName Win32_Environment @{Name=’RStest1′; VariableValue=’test1′; UserName=’RSSURFACEPRO2\Richard’}

Name             UserName                                            VariableValue
—-             ——–                                            ————-
RStest1          RSSURFACEPRO2\Richard                               test1

Using our function to discover the Keys of Win32_Environment

PS> Get-CimClassKey -CIMclass Win32_Environment
Name               : Name
Value              :
CimType            : String
Flags              : Property, Key, NullValue
Qualifiers         : {read, key, MappingStrings, Override…}
ReferenceClassName :

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

Adding the –Key parameter

PS> New-CimInstance -ClassName Win32_Environment @{Name=’RStest2′; VariableValue=’test2′; UserName=’RSSURFACEPRO2\Richard’} -Key ‘Name’, ‘UserName’

Name             UserName                                            VariableValue
—-             ——–                                            ————-
RStest2          RSSURFACEPRO2\Richard                               test2

Using Win32_Environment you can use the Key parameter, or not, as long as you define values for the Name and Username properties.

Another example in the New-CimInstance help file uses the Win32_Process class.  The key for that class is the Handle property

PS> Get-CimClassKey -CIMclass Win32_process
Name               : Handle
Value              :
CimType            : String
Flags              : Property, Key, ReadOnly, NullValue
Qualifiers         : {key, MaxLen, read}
ReferenceClassName :

the Handle is appears to be identical to the ProcessId in value as far as I can determine

This now gets  messy:

Just the Handle.  BTW exmple 3 in the documentation has an error as Handle is a string not an integer

PS> New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′}
New-CimInstance : Provider is not capable of the attempted operation
At line:1 char:1
+ New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (Win32_Process:CimInstance) [New-CimInstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80041024,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand

Add the Key parameter

PS> New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′} -Key Handle
New-CimInstance : Provider is not capable of the attempted operation
At line:1 char:1
+ New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′} -Key …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (Win32_Process (Handle = “0”):CimInstance) [New-CimInstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80041024,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand

The only way it works is if you use –ClientOnly to make an in memory CIM instance that only exists in your PowerShell session

PS> New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′} -Key Handle -ClientOnly

Handle PSComputerName
—— ————–
0

You can remove the –Key parameter

PS> New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′} -ClientOnly

Handle PSComputerName
—— ————–
0

Win32_Process has a Create method that takes these parameters

PS> $class.CimClassMethods[‘Create’].Parameters

Name                       CimType Qualifiers                                 ReferenceClassName
—-                                 ——- ———-                                 ——————
CommandLine                 String {ID, In, MappingStrings}
CurrentDirectory            String {ID, In, MappingStrings}
ProcessStartupInformation Instance {EmbeddedInstance, ID, In, MappingStrings}
ProcessId                   UInt32 {ID, MappingStrings, Out}

Using Invoke-CimMethod

PS> Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine=’notepad.exe’}

ProcessId ReturnValue PSComputerName
——— ———– ————–
2648           0

Now trying New-CimInstance

PS> New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′; CommandLine=’notepad.exe’} -Key Handle
New-CimInstance : Provider is not capable of the attempted operation
At line:1 char:1
+ New-CimInstance -ClassName Win32_Process -Property @{Handle=’0′; Comm …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (Win32_Process (Handle = “0”):CimInstance) [New-CimInstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80041024,Microsoft.Management.Infrastructure.CimCmdlets.NewCimInstanceCommand

Other variants of not including the Handle property and changing the handle value all fail with same error

Botton line is that New-CimInstance is a bit of a mess to use – with or without the –Key parameter (which doesn’t seem to do much).

If the CIM class hasa create method Id recommend that you use that as a lot of CIm classes (or their providers) don’t work with New-cimInstance. In reality given that many of the CIM classes are effectively read only – you can’t create a new instance of Win32_ComputerSystem for example – it probably doesn’t matter.

 


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: