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 Smile

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.

Posted in PowerShell v6 | Leave a comment

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.

Posted in Powershell, Windows 10, Windows Server 2016 | Leave a comment

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 = {
   $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.

Posted in Powershell, Windows 10, Windows Server 1709, Windows Server 2016 | Leave a comment

Cmdlet parameters

I discovered another way to investigate cmdlet parameters.

If you dig into the output of Get-Command you’ll see it has a parameters property

PS> Get-Command Clear-RecycleBin | select parameters

{[DriveLetter, System.Management.Automation.ParameterMetadata], [Force, System.Management.Automation.ParameterMetada...

If you expand the parameters property:

PS> Get-Command Clear-RecycleBin | select -ExpandProperty  parameters

Key                 Value
---                 -----
DriveLetter         System.Management.Automation.ParameterMetadata
Force               System.Management.Automation.ParameterMetadata
Verbose             System.Management.Automation.ParameterMetadata
Debug               System.Management.Automation.ParameterMetadata
ErrorAction         System.Management.Automation.ParameterMetadata
WarningAction       System.Management.Automation.ParameterMetadata
InformationAction   System.Management.Automation.ParameterMetadata
ErrorVariable       System.Management.Automation.ParameterMetadata
WarningVariable     System.Management.Automation.ParameterMetadata
InformationVariable System.Management.Automation.ParameterMetadata
OutVariable         System.Management.Automation.ParameterMetadata
OutBuffer           System.Management.Automation.ParameterMetadata
PipelineVariable    System.Management.Automation.ParameterMetadata
WhatIf              System.Management.Automation.ParameterMetadata
Confirm             System.Management.Automation.ParameterMetadata

The really nice thing is that you get the common parameters listed as well.

If you want to dig into the individual parameters

PS> $params = Get-Command Clear-RecycleBin | select -ExpandProperty  parameters

PS> $params.DriveLetter

Name            : DriveLetter
ParameterType   : System.String[]
ParameterSets   : {[__AllParameterSets, System.Management.Automation.ParameterSetMetadata]}
IsDynamic       : False
Aliases         : {}
Attributes      : {__AllParameterSets, System.Management.Automation.ValidateNotNullOrEmptyAttribute}
SwitchParameter : False


PS> $params.Verbose

Name            : Verbose
ParameterType   : System.Management.Automation.SwitchParameter
ParameterSets   : {[__AllParameterSets, System.Management.Automation.ParameterSetMetadata]}
IsDynamic       : False
Aliases         : {vb}
Attributes      : {System.Management.Automation.AliasAttribute, __AllParameterSets}
SwitchParameter : True

You can see the parameter sets and aliases which is useful. The parameter type indicates the input data.

This is very useful where you haven’t installed the help files on a system

Posted in Powershell | Leave a comment

Finding special folders

Windows has a number of special folders. These can be accessed either directly through the file system – for example the Documents special folder is C:\<user>\Richard\Documents or through code. But how do you go about finding special folders.

The easiest way is to use this script

1..1000 |
ForEach-Object {
   $shell = New-Object -ComObject Shell.Application
   $sf = $shell.NameSpace($psitem)

  if ($sf) {
     $props = [ordered]@{
       Value = $psitem
       Name = $sf.Title
       Path = $sf.Self.Path

    New-Object -TypeName PSobject -Property $props

Looping through the values 1-1000 the Shell.Application COM object is used to find the namespace corresponding to that number. If it exists, the value, name and path are output.

In the Path property you’ll either get a normal looking path e.g. C:\Windows\System32 or something like this – ::{645FF040-5081-101B-9F08-00AA002F954E}   – which is the CLSID or Windows Class Identifier

Posted in COM, Powershell | Leave a comment

PowerShell while

PowerShell has a number of looping structures – do; while; for; foreach. This is how the PowerShell while loop works

The while statement has the form:

while (<condition>){<statement list>}

The while loop is probably the simplest of the PowerShell loops. For example:

$x = 0

while ($x -lt 5){
Write-Host “`$x is $x”



$x is 0

$x is 1

$x is 2

$x is 3

$x is 4

As long as the condition is true the statement list is executed

The condition is evaluated BEFORE the loop is executed meaning that it may never run

PS> $x = 10

while ($x -lt 5){
Write-Host “`$x is $x”



The value of $x is greater than 4 so the loop never executes.

Posted in Powershell | Leave a comment

Get-Date format

A common question revolves around Get-Date format. In other words how can you format the output of Get-Date. 

Standard output is

PS> Get-Date

27 February 2018 16:02:13

You can use –DisplayHint to control what’s displayed

PS> Get-Date -DisplayHint Date

27 February 2018

PS> Get-Date -DisplayHint Time


PS> Get-Date -DisplayHint DateTime

27 February 2018 16:03:17

Which is fine if you just want the date or the time

You’ve also got some methods on the DateTime object that can help

PS> (Get-Date).ToShortDateString()
PS> (Get-Date).ToShortTimeString()
PS> (Get-Date).ToLongDateString()
27 February 2018
PS> (Get-Date).ToLongTimeString()
PS> (Get-Date).ToFileTime()
PS> (Get-Date).ToFileTimeUtc()
PS> (Get-Date).ToUniversalTime()

27 February 2018 16:07:01

Universal Time is more properly known as Greenwich Mean Time

If you want a bit more control you can use the –Format parameter. A description of the format specifiers is available at https://msdn.microsoft.com/en-GB/Library/system.globalization.datetimeformatinfo(VS.85).aspx


will give a very long list of the possible formats. Unfortunately it just displays the results not the format specifier.

There are some preset formats – for example:

PS> Get-Date -Format g
27/02/2018 16:14
PS> Get-Date -Format r
Tue, 27 Feb 2018 16:14:58 GMT
PS> Get-Date -Format s

Or you can customise the format

PS> Get-Date -Format “ddMMyyyyhhmmss”
PS> Get-Date -Format “dd/MM/yyyy hh:mm:ss”
27/02/2018 04:18:03
PS> Get-Date -Format “dd/MM/yyyy HH:mm:ss”
27/02/2018 16:18:08

Read the article at the link for the full list of options. NOTE – the options ARE case sensitive

Alternatively, you could use the –Uformat parameter to use Unix formatting. This is explained in the NOTES section of the Get-Date help file.

Some examples

PS> Get-Date -UFormat “%d/%m/%Y %r”
27/02/2018 04:23:25 PM
PS> Get-Date -UFormat “%d/%m/%Y %R”
27/02/2018 16:23

Between the display hints, the methods, –Format and –UFormat you should be able to get the date into the format you need.

Posted in Powershell | Leave a comment