Monthly Archive

Categories

Monthly Archives: August 2019

Pet peeves

Back in July I mentioned the using ? instead of Where-Object was a pet peeve. I’ve been asked a few times since for other pet peeves. The order of peevishness changes over time but these three will probably be always near the top.

 

In no particular order.

 

Peeve – the use of aliases in scripts. Aliases are fine for interactive use but when coding scripts or modules you should ALWAYS use the full cmdlet name and parameter names. If you use VScode or ISEsteroids you’ll find warning messages about the use of aliases. The problem with using aliases is that it makes the code harder to maintain especially for new comers. if you want to write impenetrable code that no one can read then switch to Perl. PowerShell has verb-noun cmdlet naming conventions and good (usually) parameter names for a reason. It makes the code easier to read and therefore understand and maintain. I guarantee that you’d rather inherit some code that uses full names rather than all aliases – been there, done that and its painful.

 

Peeve – the use of posh as an abbreviation for PowerShell. Its not needed and doesn’t add anything to the conversation. Just don’t.

 

Peeve – the use of multiple calls to Add-Member to create an object. You had to do this back in PowerShell v1. You should use New-Object or create a class to define your object. Its more efficient and easier to maintain. Don’t keep using outdated techniques just because there are still examples on the Internet.

 

I’ll publish more peeves sometime in the future.

Foreach-Object -parallel

The introduction of Foreach-Object -parallel in PowerShell v7 preview 3 brings some much needed parallelisation options back into PowerShell.

 

PowerShell workflows are available in Windows PowerShell but are quirky (to be kind) and can be difficult to use. Workflows were removed in PowerShell v6.0

 

In PowerShell v7 preview 3 Foreach-Object receives a –parallel parameter that takes a scriptblock as its value.

 

As a simple example consider this simple counting example from the PowerShell team blog:

PS> (Measure-Command -Expression {1..50 | ForEach-Object {Start-Sleep -Milliseconds 100}}).TotalSeconds
5.4960846

 

Now using the parallel option

PS> (Measure-Command -Expression {1..50 | ForEach-Object -Parallel {Start-Sleep -Milliseconds 100}}).TotalSeconds
2.2523929

 

The time to execute is significantly reduced.

 

A few caveats are needed.

Firstly, the parallel option is an experimental feature so must be enabled

Enable-ExperimentalFeature -Name PSForEachObjectParallel

 

Secondly, not all tasks are suitable candidates for parallel execution. Expect more discussion on this topic in the near future including contributions on the PowerShell team blog.

Testing Windows activation

Testing Windows activation from PowerShell involves a little dive into CIM (WMI).

At its simplest a function like this

function test-activation {

$ta = Get-CimInstance -ClassName SoftwareLicensingProduct -Filter "PartialProductKey IS NOT NULL" |
Where-Object -Property Name -Like "Windows*"

if ($ta.LicenseStatus -eq 1) {$true} else {$false}
}

 

Checks the SoftwareLicensingProduct class for instances with a Partial product key. Where-Object filters on the Name of the product. It has to start with Windows.

 

If the LicenseStatus equals 1 then Windows is activated – otherwise it isn’t

Get-AdUser in PowerShell Core

There has been a problem with Get-ADUser in PowerShell core such that

Get-ADUser -Identity Richard -Properties *

 

Throws an error.

 

The problem is in .NET Core and affects a small number of properties including ProtectedFromAccidentalDeletion

 

The underlying .NET Core issue has been fixed and PowerShell v7 preview 3 on Windows 10.0.18362 will successfully run the command

Windows Terminal v0.4.2382.0

Windows Terminal v0.4.2382.0 has ben released to the Microsoft store. if you have Windows Terminal installed it should automatically update for you.

 

Copying out of a window using the keyboard shortcuts now works – thank you – that makes the whole thing much more usable.

 

I can’t seem to find a way to make the font have a bold face which is really good for demonstrations.

 

Windows terminal automatically picks up my Windows v6.2 and Windows PowerShell v5.1 instances as well as WSL and the command line. PowerShell v7 previews are ignored but could be configured manually. Given the rate of change in the preview versions not sure that its a good idea to add them to the terminal setup.

 

So far the experience is reasonably positive for a product still under development.

 

I’d recommend you give it a try if you haven’t already done so.

Experimental features

PowerShell core has recently. v6.2, had the concept of experimental features added. An experimental feature is new or changed functionality that may be a breaking change or about which the PowerShell team want feedback before finalising the code.

My PowerShell v6.2.2 instance has the following experimental features

PSImplicitRemotingBatching
PSUseAbbreviationExpansion
PSCommandNotFoundSuggestion
PSTempDrive

 

of which I’ve enabled PSCommandNotFoundSuggestion and PSTempDrive. Experimental features are disbaled by default in PowerShell v6.2

 

My PowerShell v7 preview 3 instance has the following experimental features

PSImplicitRemotingBatching
PSForEachObjectParallel
PSCommandNotFoundSuggestion

 

of which PSForEachObjectParallel and PSCommandNotFoundSuggestion

PSUseAbbreviationExpansion and PSTempDrive and now full features in PowerShell v7

 

If don’t have any PowerShell v6.2 experimental features enabled OR don’t have v6.2 installed and then install PowerShell v7 preview 3, or later, all experimental features will be enabled by default. If you’ve enabled any experimental features in PowerShell v6.2 then PowerShell v7 respects the settings and doesn’t enable all experimental features.

 

You can view the settings controlling experimental features (among other things) at

Get-Content –Path $home\Documents\PowerShell\powershell.config.json

 

The single settings file is used for PowerShell v6.2 and PowerShell v7 previews

PowerShell v7 preview 3

PowerShell v7 preview 3 is now available from https://github.com/PowerShell/PowerShell/releases

 

Breaking changes seem to be confined to non-Windows platforms with the removal of the kill alias on Stop-Process and support for pwsh as a login shell

 

The big new item is the –parallel parameter on Foreach-Object – more on this later.

 

In this preview version and future preview versions all experimental features will be enabled going forward

Out-GridView is back

Out-GridView is finally back in PowerShell core - https://devblogs.microsoft.com/powershell/out-gridview-returns/.

 

The project is hosted on github - https://github.com/powershell/GraphicalTools

 

Install the module from the gallery -

PS> Install-Module -Name Microsoft.PowerShell.GraphicalTools

 

Currently, Out-GridView is the only command in the module though adding Show-Command and Show-Object are planned.

 

The module works cross-platform not just Windows.

 

You need PowerShell v6.2 or later to build or presumably run the module.

PowerShell v2

Just seen a question about PowerShell v2. PowerShell v2 was a huge step forward when it appeared in October 2009 as part of Windows 7 / Server 2008 R2

 

Windows 7 support finishes 14 January 2020

Windows Server 2008 R2 support finishes 14 January 2020

 

That’s less than 6 months.

 

PowerShell v2 isn’t mentioned in the Microsoft documentation which starts at PowerShell v3

 

If you’re still using PowerShell v2 its beyond time to move to a later version.

Test if a transcript is running

PowerShell has the ability to create a transcript of the commands you run at the console and the results displayed in the console. But how can you test if a transcript is running?

It used to be that you could only have a single transcript running but Windows PowerShell v5.1 and PowerShell v6.x and later allow multiple transcripts to be running in the same session.

Only way I can think of testing if transcript has been started is to use

Get-History | where CommandLine -like 'Start-Transcript*'

that doesn’t tell if its still running for which you need

Get-History | where CommandLine -like 'Stop-Transcript*'

PS> (Get-History | where CommandLine -like 'Start-Transcript*').Count - (Get-History | where CommandLine -like 'Stop-Transcript*').Count

should give a result of zero if no transcripts are running. A positive result indicates transcripts are running. A negative result indicates problems.

The test can be wrapped in a function

function test-runningtranscript {
$starts = (Get-History | Where-Object CommandLine -like 'Start-Transcript*').Count
$stops = (Get-History | Where-Object CommandLine -like 'Stop-Transcript*').Count

$trans = $starts - $stops

switch ($trans){
0 {$false}
{$_ -gt 0} {$true}
{$_ -lt 0} {Throw "Error!!! Can't have negative transcripts"}
}
}

You’ll get True return if there is a transcript running and False if there isn’t.