Monthly Archive

Categories

Monthly Archives: March 2018

PowerShell join

I looked at PowerShell split a few posts back. This time I’ll look at the opposite action – PowerShell join.

Lets look at a simple string

PS> $str = 'PowerShell for Windows and Linux'

and split it

PS> $strs = -split $str
PS> $strs
PowerShell
for
Windows
and
Linux

 

You end up with an array of strings.

Now lets put it back together again

You can just use the operator

PS> -join $strs
PowerShellforWindowsandLinux

 

but there’s no delimiter (default) between the elements as they’re joined. You can define a delimiter

PS> $strs -join ' '
PowerShell for Windows and Linux
PS> $strs -join '_'
PowerShell_for_Windows_and_Linux

 

And that’s it for join.

Beware that you can use variable substitution to effect a join

PS> "$strs"
PowerShell for Windows and Linux

 

Also be aware that if you give the join operator a comma-separated list the join will fail

PS> -join 'PowerShell', 'for', 'Windows', 'and', 'Linux'
PowerShell
for
Windows
and
Linux

 

because join has a higher operator precedence than comma

You need to wrap the list in parentheses

PS> -join ('PowerShell', 'for', 'Windows', 'and', 'Linux')
PowerShellforWindowsandLinux

or use a variable as you saw earlier
PS> $x = 'PowerShell', 'for', 'Windows', 'and', 'Linux'
PS> -join $x
PowerShellforWindowsandLinux

 

Using a delimiter also works

PS> 'PowerShell', 'for', 'Windows', 'and', 'Linux' -join ' '
PowerShell for Windows and Linux
PS> ('PowerShell', 'for', 'Windows', 'and', 'Linux') -join ' '
PowerShell for Windows and Linux

Iron Scripter 2108

Iron Scripter 2018 is the scripting competition we’re holding at the PowerShell Summit on 12 April 2018.

 

The task for the main event is still under wraps but even if you can’t make the Summit you can benefit from the competition.

 

I’ve posted 10 prequel puzzles on powershell.org. Each puzzle revolves around a task you may need to perform. There is a commentary available for each puzzle (the commentary for puzzle 1o will be published on 1 April). If you’ve not looked at the puzzles there are some very interesting parts of PowerShell you need to dig into to solve them. The commentary discusses how I solved them.

 

Starting on Sunday 8 April we’ll be publishing 4 preludes to the iron Scripter event on ironscripter.us. These are shorter puzzles that may (or may not) help you solve the main event. We won’t be publishing any commentary on them but there is the iron Scripter forum on powershell.org

 

Even if you’re not attending Summit get in touch with someone who is and offer remote assistance for the competition itself. Its on 12 April 3-4pm PDT (11-midnight BST).

Windows server futures

A blog post - https://cloudblogs.microsoft.com/windowsserver/2018/03/29/windows-server-semi-annual-channel-update/ – has clarified Windows server futures.

 

Going forward the Semi-Annual Channel (SAC) releases – Server 1803 is due very soon  - will concentrate on containers (applications and hosts) and fast innovation application scenarios. Releases will be every 6 months with an 18 month lifetime.

 

The Long Term Servicing Channel (LTSC) is for general purpose file servers, ‘traditional’ applications (whatever that means), infrastructure roles, software defined datacenter and Hyper-converged infrastructure. Releases will be every 2-3 years with the standard 5+5 lifecycle.

 

SAC will be Server Core only. if you want a GUI you need LSTC.

 

Innovations from SAC releases that occur between LSTC releases will be rolled into the next LSTC.

 

This clarification is useful and the differences between SAC and LSTC now make sense.

 

I’d recommend that you only use the SAC releases if you need them as they do introduce more churn into the environment given their short lifecycle. I wouldn’t ignore them –keep any eye on the releases as they become available as there might be a feature that makes your life much easier.

Installing Win32 OpenSSH

I’ve had a number problems Installing Win32 OpenSSH https://github.com/PowerShell/Win32-OpenSSH/wiki/Install-Win32-OpenSSH since it became available and required for SSH based remoting in PowerShell v6

 

Every time I install a new version the instructions have changed. Admittedly the installation is getting easier BUT as the project is still producing beta versions then installing over the top of an existing installation has been necessary and that’s where the problems occur.

 

Every time I’ve tried to upgrade Win32 OpenSSH I’ve had problems. I’ve come to the conclusion that the best thing to do is to completely remove the old version of OpenSSH and then re-install from scratch. Save the old config file as an easy way to get your configuration back.

 

OpenSSH is needed for remoting to/from Linux systems and is useful for remoting to non-domain machines. There needs to be a very simple install, configuration and update process that DOESN’T involve messing about with chocolately packages or the ever changing install instructions.

Windows Server 2019 preview

A Windows Server 2019 preview is available - https://cloudblogs.microsoft.com/windowsserver/2018/03/20/introducing-windows-server-2019-now-available-in-preview/

The build number is 17623 and its also the preview of the next Semi-Annual Channel release.

GA is set for H2 2018

Server 2019 is a Long term Servicing Channel release meaning it’ll be available in GUI (desktop) and Server Core versions and a full life cycle (10 years is current standard) as opposed to the Semi-Annual Channel releases which are Server Core only and have a 18 month lifetime.

One interesting feature is that this release brings the ability to do an in place OS upgrade from Server 2016 and Server 2012 R2. It doesn’t explicitly say so but I’m assuming from the wording you can’t upgrade Semi-Annual Channel machine

Now for  the bad news. Windows PowerShell is still v5.1

PS C:\Users\Administrator> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.17623.1002
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17623.1002
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Hopefully there are some bug fixes even if there’s no new functionality.

PowerShell split

The PowerShell split operator is used to split strings based on a delimiter.

 

The default delimiter is white space

PS> $str = 'AA BB CC DD EE FF GG'

PS> -split $str
AA
BB
CC
DD
EE
FF
GG

 

You can define a delimiter

PS> $str = 'AA-B-CC-DD-EE-FF-GG'
PS> $str -split '-'
AA
B
CC
DD
EE
FF
GG

 

Notice that the position of the operator has changed. The first case using the default delimiter is a special case that’s equivalent to:

PS> $str = 'AA BB CC DD EE FF GG'
PS> $str -split ' '
AA
BB
CC
DD
EE
FF
GG

 

You can define the items into which the string is split:

PS> $str = 'AA BB CC DD EE FF GG'
PS> $str -split ' ', 3
AA
BB
CC DD EE FF GG

 

In this case you get the first two splits and the rest as one big string

The delimiter is normally removed from the results but you can keep it

PS> $str = 'AA-B-CC-DD-EE-FF-GG'
PS> $str -split '(-)'
AA
-
B
-
CC
-
DD
-
EE
-
FF
-
GG

 

You have a number of options you can use

"SimpleMatch [,IgnoreCase]"

or

"[RegexMatch] [,IgnoreCase] [,CultureInvariant]
[,IgnorePatternWhitespace] [,ExplicitCapture]
[,Singleline | ,Multiline]"

which are all documented in about_split

PowerShell v6.1.0 preview 1

The first preview release of PowerShell v6.1 is available at https://github.com/PowerShell/PowerShell/releases

 

There are a few breaking changes you should check out.

 

Most of the changes are minor engine updates and bug fixes.

 

There are no big new features in this preview release

PowerShell v6.0.2

PowerShell v6.0.2 is available from https://github.com/PowerShell/PowerShell/releases

 

The only real change is that .NET core 2.0.6 is used in this release to counter the Hash Collision vulnerability - https://github.com/PowerShell/Announcements/issues/4

 

A number of changes that affect the way the project builds and releases code have also been implemented – these SHOULD be transparent to the user 🙂

 

Win32-OpenSSH also has a relatively new release – v7.6.0.0p1-Beta - https://github.com/PowerShell/Win32-OpenSSH/releases. The jump in version number is to bring it inline with the base OpenSSH code.

 

Still no simple way to install and configure OpenSSH but it is getting a bit better. Most won’t  need to run a instance of powershell in bypassexecutionpolicy mode as part of the install.  If you’re not allowing scripts to run then why bother with OpenSSH remoting?  If you’re using Allsigned then it probably makes sense. In any case it’s still too complicated.

 

The ability to release new versions like this is one of the big plus points for having PowerShell as an open source project.

Set active hours

Last time time you saw how to get the current active hours. This is how you set the active hours.

$sb = {
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Name ActiveHoursStart -Value 10 -PassThru
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Name ActiveHoursEnd -Value 22 -PassThru
}

Get-ADComputer -Filter * -Properties OperatingSystem |
where OperatingSystem -like "*Server*" |
select -ExpandProperty Name |
foreach {

Invoke-Command -ComputerName $psitem -ScriptBlock $sb -ArgumentList $psitem -HideComputerName |
select -Property * -ExcludeProperty RunSpaceId
}

 

The script block uses Set-ItemProperty to set the start and end of active hours. On Windows server 2016 you’re restricted to a 12 hour span for your active hours. Later Windows 10 builds allow up to 18 hours. I’ve used 10 for the start and 22 for the end to give me the best time spread that matches my activity – you can choose your own hours of course.

 

Getting the list of systems from AD and running the command remotely is as previously.

Get Active Hours

Windows 10 and Server 2016 (and later) have the concept of active hours. These are the hours you define as working hours in effect. This is how you get active hours for a system

$sb = {
param([string]$computerName)

$ahs = Get-Item -Path HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings

$props = [ordered]@{
ComputerName = $computerName
ActiveHoursStart = $ahs.GetValue('ActiveHoursStart')
ActiveHoursEnd = $ahs.GetValue('ActiveHoursEnd')
}

New-Object -TypeName PSobject -Property $props

}

Get-ADComputer -Filter * -Properties OperatingSystem |
where OperatingSystem -like "*Server*" |
select -ExpandProperty Name |
foreach {

Invoke-Command -ComputerName $psitem -ScriptBlock $sb -ArgumentList $psitem -HideComputerName |
select -Property * -ExcludeProperty RunSpaceId
}

 

The script block reads the registry key that contains the active hours information and outputs and object that contains the computer name, and start and end (in 24 hour clock) of the active hours.

 

I’m getting the information for all servers in the domain – use the OperatingSystem property on the computer to deselect non-servers. use Invoke-Command to run the command against the remote computer – hide the automatic computer name and runspaceid properties.