PowerShell for Windows Admins


July 15, 2014  2:20 AM

PowerShell Summit Europe 2014 – - update 5

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Registration is now open. Access through Events menu at powershell.org

July 14, 2014  11:41 AM

Formatting disks – - the new way

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Windows 2012

Last time I showed how to format disks using the Win32_Volume CIM class. If you need to perform this activity on a Windows Server 2012/Windows 8 or later system you can use a couple of cmdlets from the Storage module

Get-Volume | where DriveLetter -ne ‘C’ | Format-Volume -FileSystem NTFS -Confirm:$false –WhatIf

 

If you’ve not looked at the Storage module before there is a lot of useful cmdlets.


July 13, 2014  9:34 AM

Formatting disks

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, WMI

Saw a question on the forums about formatting all disks but the C: drive.  Assuming you ever need to do such a destructive activity you might want think about ths sort of approach

Get-CimInstance -ClassName Win32_Volume -Filter “DeviceId != ‘C:’” |
foreach {
Invoke-CimMethod -whatif -InputObject $psitem -MethodName Format -Arguments @{
ClusterSize = 4096
EnableCompression = $false
FileSystem = ‘NTFS’
QuickFormat = $true
}
}

 

Notice I’ve left the –whatif in for safety

More details on the Win32_Volume class at http://msdn.microsoft.com/en-us/library/aa394515%28v=vs.85%29.aspx


July 12, 2014  4:28 AM

Time to stock up your book collection?

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Active Directory, Books

Manning are offering 40% off everything – print & ebooks – www.manning.com. They have a very extensive set of PowerShell books – now would be the time to add to your collection


July 11, 2014  12:39 PM

CIM or WMI – - accessing remote machines

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, WMI

I much prefer the CIM cmdlets for accessing remote machines. The WMI cmdlets use DCOM which is firewall unfriendly and can often be unavailable of a server – cue the dreaded RPC server is unavailable error messages.

By contrast the CIM cmdlets use WSMAN.

For one off access to a remote machine use the computername parameter

Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName RSSURFACEPRO2

 

If you want to access a machine multiple times in the session create a CIM session – analagous to a remoting session

 

$cs = New-CimSession -ComputerName RSSURFACEPRO2
Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $cs

 

By default a CIM session uses WSMAN

£> $cs
Id           : 1
Name         : CimSession1
InstanceId   : 30c2b530-4ff7-448e-b68d-1f1282890e6a
ComputerName : RSSURFACEPRO2
Protocol     : WSMAN

 

though you can configure them to use DCOM if need be

$opt = New-CimSessionOption -Protocol DCOM
$csd = New-CimSession -ComputerName RSSURFACEPRO2 -SessionOption $opt
Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $csd

 

When would you need to use DCOM – if you are accessing a machine with PowerShell 2 installed. The CIM cmdlets want to use WSMAN 3 and will error if you access a machine with WSMAN 2 installed however if you include a –Filter they will work

So

Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName computer1

will fail if computer1 is running WSMAN 2 (PowerShell 2)

However, if you change the command to include a filter

Get-CimInstance -ClassName Win32_OperatingSystem -Filter “Manufacturer LIKE ‘Microsoft%’” -ComputerName computer1

 

Even if, as in this case, the filter doesn’t actually do anything


July 9, 2014  1:29 PM

PowerShell Summit Europe 2014 – - update 4

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

Registration will open next Tuesday (15th July) – that’s less than 1 week


July 7, 2014  12:45 PM

Finding a CIM class

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, WMI

I was investigating something on my disks and started to look at the partitions:

£> Get-CimInstance -ClassName Win32_Partition
Get-CimInstance : Invalid class
At line:1 char:1
+ Get-CimInstance -ClassName Win32_Partition
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : MetadataError: (root\cimv2:Win32_Partition:String) [Get-CimInstance], CimException
+ FullyQualifiedErrorId : HRESULT 0×80041010,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand

OK so my memory isn’t what it was and I got the class name wrong. How to find the correct class?

£> Get-CimClass *Partition*
NameSpace: ROOT/cimv2

CimClassName
————
CIM_DiskPartition
Win32_DiskPartition
Win32_SystemPartitions
CIM_LogicalDiskBasedOnPartition
Win32_LogicalDiskToPartition
CIM_RealizesDiskPartition
Win32_DiskDriveToDiskPartition
Win32_PerfFormattedData_HvStats_…
Win32_PerfRawData_HvStats_HyperV…
Win32_PerfFormattedData_HvStats_…
Win32_PerfRawData_HvStats_HyperV…
Win32_PerfFormattedData_VidPerfP…
Win32_PerfRawData_VidPerfProvide…

 

I’ve truncated the display horizontally as not interested in methods & properties at this point
So the class I want is Win32_DiskPartition.

Get-CimClass is one of the biggest benefits from PowerShell 3.0


July 6, 2014  3:22 PM

CIM or WMI – - using methods

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
CIM, WMI

The CIM and WMI cmdlets both provide a way to use the methods on CIM classes namely Invoke-CimMethod and Invoke-WmiMethod. The cmdlets are very similar in operation.

$vol = Get-WmiObject -Class Win32_Volume -Filter “DriveLetter = ‘D:’”

Invoke-WmiMethod -InputObject $vol -Name Chkdsk -ArgumentList $false, $true, $true, $false, $false, $false

 

The argumenst list isn’t very informative – unless you know the class, read the documentation or investigate with Get-CimClass

 

Using the CIM cmdlets is a bit more informative as to what is going on.

$vol = Get-CimInstance -ClassName Win32_Volume -Filter “DriveLetter = ‘D:’”

Invoke-CimMethod -InputObject $vol -MethodName Chkdsk -Arguments @{FixErrors=$false; ForceDismount=$false; OkToRunAtB
ootUp = $false; RecoverBadSectors = $false; SkipFolderCycle = $true; VigorousIndexCheck = $true}

 

You present the arguments as a hash table – this means you can create the hash table and pass it to the method

$margs = @{
FixErrors=$false
ForceDismount=$false
OkToRunAtBootUp = $false
RecoverBadSectors = $false
SkipFolderCycle = $true
VigorousIndexCheck = $true
}
Invoke-CimMethod -InputObject $vol -MethodName Chkdsk -Arguments $margs

 

This also means that you can create a default set of values and manipulate them in your scripts very easily

 

Using Invoke-CimMethod involves more typing but I think that’s worth it for the clarity. Of course if you are going to be using the methods of class a lot then I’d recommend that you create a CDXML module from the class – but that’s a whole different set of articles.


July 6, 2014  8:50 AM

Workflows 7: checkpointing workflows

Richard Siddaway Richard Siddaway Profile: Richard Siddaway
Workflow

Consider this workflow

workflow chkpt1 {

Get-Process

foreach ($x in 1..20){
$x
}

}

 

It will dump out the process information then output the numbers 1 to 20.  Not a particularly enlightening workflow but it forms  a nice basis for demonstrating checkpoints.

A checkpoint saves the state and data in the workflow. If the workflow is suspended or interrupted the work flow can be restarted from the most recent checkpoint rather than a complete restart from the beginning.

 

Change the workflow to give a long running activity

workflow chkpt1 {

Get-Process
foreach ($x in 1..1000){
$x
}

}

Let the process data be displayed and then stop execution once the numbers start displaying – this is easiest if you use ISE. If you want to restart the workflow you have to start it right from the beginning.

Add a checkpoint to the workflow. This can be achieved in a number of ways.

Use the Checkpoint-Workflow activity to the workflow.

workflow chkpt1 {

Get-Process
Checkpoint-Workflow

foreach ($x in 1..1000){
$x
}

}

 

or use the –PSPersist parameter

workflow chkpt1 {

Get-Process -PSPersist
foreach ($x in 1..1000){
$x
}

}

 

I prefer to use Checkpoint-Workflow as it is more obvious to me when I review the workflow.

 

if you want to checkpoint your workflows – you have to start them as a job

 

chkpt1 –AsJob

 

Then shut down ISE

Open another PowerShell session with elevated privileges. Use Get-Job to see the suspended job.

View the data in the job

Receive-Job -Id 5 –Keep

 

Restart the job

Resume-Job -Id 5

 

Once the job finishes view the data and you’ll see the process data and the list of numbers.

Use Checkpoint-Workflow as many time as necessary to protect your data in long running workflows. A checkpoint is a good idea any time that it would be expensive to restart the whole process.


July 3, 2014  2:58 PM

and finally

Richard Siddaway Richard Siddaway Profile: Richard Siddaway

If you’re old enough and seen UK TV you’ll recognise the title but this post is about using try – catch blocks.

Using try-catch this is a fairly normal construction

try {
Get-CimInstance -ClassName Win32_LogicalDisk  -ErrorAction Stop
}
catch {
Throw “something went wrong”
}

The number of commands within the try block should be minimised so that you stand a chance of knowing what you are going to catch.

if you introduce an error – for instance using the wrong classname

£> try {
Get-CimInstance -ClassName Win32_LogicalDrive  -ErrorAction Stop
}
catch {
Throw “something went wrong”
}
something went wrong
At line:5 char:2
+  Throw “something went wrong”
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : OperationStopped: (something went wrong:String) [], RuntimeException
+ FullyQualifiedErrorId : something went wrong

 

You can control what happens and even recover.

I don’t see the third element of a try-catch block being used much – that’s the finally block. The finally block will run irrespectively of whether the try block works or not. It’s your clean up block

Consider

£> try {
$cs = New-CimSession -ComputerName $env:COMPUTERNAME
Get-CimInstance -ClassName Win32_LogicalDrive  -CimSession $cs -ErrorAction Stop
}
catch {
Throw “something went wrong”
}
something went wrong
At line:6 char:2
+  Throw “something went wrong”
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : OperationStopped: (something went wrong:String) [], RuntimeException
+ FullyQualifiedErrorId : something went wrong
£> Get-CimSession
Id           : 1
Name         : CimSession1
InstanceId   : 68a4f534-d222-4e52-b6f9-ba65b1d57b3b
ComputerName : RSSURFACEPRO2
Protocol     : WSMAN

 

This try block fails but it leaves a CIM session hanging about. Not good practice. I know it will get cleaned up when you close the powershell session but that could be hours away. Better to clean up now.

£> try {
$cs = New-CimSession -ComputerName $env:COMPUTERNAME
Get-CimInstance -ClassName Win32_LogicalDrive  -CimSession $cs -ErrorAction Stop
}
catch {
Throw “something went wrong”
}
finally {
Remove-CimSession -CimSession $cs
}

Get-CimSession
something went wrong
At line:6 char:2
+  Throw “something went wrong”
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : OperationStopped: (something went wrong:String) [], RuntimeException
+ FullyQualifiedErrorId : something went wrong
no sign of a CIM session even if you try specifically.

 

£> Get-CimSession

£>

if you correct the code

try {
$cs = New-CimSession -ComputerName $env:COMPUTERNAME
Get-CimInstance -ClassName Win32_LogicalDisk  -CimSession $cs -ErrorAction Stop
}
catch {
Throw “something went wrong”
}
finally {
Remove-CimSession -CimSession $cs
}

Get-CimSession

 

You’ll find the the CIM session is still removed. A finally block will always run

When you are using try blocks think about your environment and use a finally block to clean up.


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: