Monthly Archive

Categories

Just the date

Way back in this post https://richardspowershellblog.wordpress.com/2008/03/27/start-and-end-of-week/ I showed how to find the start of the week. I recently had a question about how to restrict the display to just the date.

 

PowerShell uses the .NET datetime class for working with dates so there will always be time information even if its set to 0. You can however restrict the display to just the date information

 

The ToShortDateString and ToLongDateString methods will give you just the date information but as a string

PS> $s = Get-Date -Hour 0 -Minute 0 -Second 0
PS> $d = $s.AddDays(-($s).DayOfWeek.value__)
PS> $d.ToShortDateString()
07/01/2018
PS> $d.ToLongDateString()
07 January 2018

 

Alternately you could create a custom format using the formatting strings found at

https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings

For example

PS> Get-Date -Date $d -Format "yyyy-MM-dd gg"
2018-01-07 A.D.

 

You could combine the code lines to give

PS> $s = Get-Date -Hour 0 -Minute 0 -Second 0
PS> Get-Date -Date ($s.AddDays(-($s).DayOfWeek.Value__)) -Format "yyyy-MM-dd gg"
2018-01-07 A.D.

 

If you do this often enough then create a function

Relevance of Scripts

I had a sudden thought today about the relevance of scripts – PowerShell Scripts -  today.

 

PowerShell v6 can’t run some of the modules that we’ve come to rely on – for instance the AD cmdlets. The Windows Compatibility Pack (see previous post) enables access to some of the underlying .NET classes that enable AD administration through PowerShell.

 

This means going back to the v1/v2 days and writing scripts – we may wrap them as advanced functions and modules these days but the basic code is the same – instead of using canned cmdlets.

 

My first two books

PowerShell in Practice - https://www.manning.com/books/powershell-in-practice

and

PowerShell and WMI - https://www.manning.com/books/powershell-and-wmi

 

supply lots of code examples for working with PowerShell Scripts including AD and WMI. If you haven’t got a copy they’ll help you get back to basics.

Windows Compatibility Pack

As reported last month the Windows Compatibility Pack for .NET core is available. This adds back some of the functionality missing from .NET core. This functionality is ONLY of relevance on Windows machines.

 

A PowerShell module based on the Compatibility Pack is in the works – this will add a number of cmdlets including the WMI cmdlets back into PowerShell v6 on Windows. There’s no ETA on the module at this time.

 

There is a module on the PowerShell gallery that will add the .NET components of the Compatibility Pack into your PowerShell v6 session.

PS>  Find-Module -Name PSCoreWindowsCompat | ft -a

Version Name                Repository Description 
 ------- ----                ---------- ----------- 
 0.1.0.2 PSCoreWindowsCompat PSGallery  Provides the Microsoft.Windows.Compatibility Pack to PowerShell Core.

 

If you want to inspect the module

PS>  Save-Module -Name PSCoreWindowsCompat -Repository PSGallery -Path C:\Source\ -Force

 

To install the module:

PS>  Install-Module -Name PSCoreWindowsCompat -Repository PSGallery -Verbose -Force 
 VERBOSE: Repository details, Name = 'PSGallery', Location = 'https://www.powershellgallery.com/api/v2/'; IsTrusted = 'False'; IsRegistered = 'True'. 
 VERBOSE: Using the provider 'PowerShellGet' for searching packages. 
 VERBOSE: Using the specified source names : 'PSGallery'. 
 VERBOSE: Getting the provider object for the PackageManagement Provider 'NuGet'. 
 VERBOSE: The specified Location is 'https://www.powershellgallery.com/api/v2/' and PackageManagementProvider is 'NuGet'. 
 VERBOSE: Searching repository 'https://www.powershellgallery.com/api/v2/FindPackagesById()?id='PSCoreWindowsCompat'' for ''. 
 VERBOSE: Total package yield:'1' for the specified package 'PSCoreWindowsCompat'. 
 VERBOSE: Performing the operation "Install-Module" on target "Version '0.1.0.2' of module 'PSCoreWindowsCompat'". 
 VERBOSE: The installation scope is specified to be 'AllUsers'. 
 VERBOSE: The specified module will be installed in 'C:\Program Files\PowerShell\Modules'. 
 VERBOSE: The specified Location is 'NuGet' and PackageManagementProvider is 'NuGet'. 
 VERBOSE: Downloading module 'PSCoreWindowsCompat' with version '0.1.0.2' from the repository 'https://www.powershellgallery.com/api/v2/'. 
 VERBOSE: Searching repository 'https://www.powershellgallery.com/api/v2/FindPackagesById()?id='PSCoreWindowsCompat'' for ''. 
 VERBOSE: InstallPackage' - name='PSCoreWindowsCompat', version='0.1.0.2',destination='C:\Users\Richard.MANTICORE\AppData\Local\Temp\51711061' 
 VERBOSE: DownloadPackage' - name='PSCoreWindowsCompat', version='0.1.0.2',destination='C:\Users\Richard.MANTICORE\AppData\Local\Temp\51711061\PSCoreWindowsCompat\PSCoreWindowsCompat.nupkg', uri='https://www.powershellgallery.com/api/v2/package/PSCoreWindowsCompat/0.1.0.2' 
 VERBOSE: Downloading 'https://www.powershellgallery.com/api/v2/package/PSCoreWindowsCompat/0.1.0.2'. 
 VERBOSE: Completed downloading 'https://www.powershellgallery.com/api/v2/package/PSCoreWindowsCompat/0.1.0.2'. 
 VERBOSE: Completed downloading 'PSCoreWindowsCompat'. 
 VERBOSE: InstallPackageLocal' - name='PSCoreWindowsCompat', version='0.1.0.2',destination='C:\Users\Richard.MANTICORE\AppData\Local\Temp\51711061' 
 VERBOSE: Catalog file 'PSCoreWindowsCompat.cat' is not found in the contents of the module 'PSCoreWindowsCompat' being installed. 
VERBOSE: Module 'PSCoreWindowsCompat' was installed successfully to path 'C:\Program Files\PowerShell\Modules\PSCoreWindowsCompat\0.1.0.2'.

 

Notice the installation path is OUTSIDE of the current version of PowerShell v6 so should remain available through any upgrades.

PS>  Import-Module -Name PSCoreWindowsCompat

 

Now you’ve got it how do you use it? The module DOESN’T have any functions – it just loads the .NET namespaces.

 

Its back to PowerShell v1 days – everything is a script instead of a cmdlet. For instance the Compatibility pack contains the System.DirectoryServices so you can script against AD.

 

Let’s say you want to see all the users in the domain:

$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() 
 $root = $dom.GetDirectoryEntry()

$search = [System.DirectoryServices.DirectorySearcher]$root 
 $search.Filter = "(&(objectclass=user)(objectcategory=user))" 
 $search.SizeLimit = 3000 
 $result = $search.FindAll()

foreach ($user in $result){ 
    $user.Properties.distinguishedname 
 }

 

Use System.DirectoryServices.ActiveDirectory.Domain to get the current domain. Create a System.DirectoryServices.DirectorySearcher object and set the filter to users. Find all of the users and display their distinguishedname

 

Its a lot more complicated than using the cmdlet:

PS>  Get-ADUser -Filter * | select DistinguishedName

 

but it gets the job done.

 

If you need to administer AD and you need the cross platform capabilities of PowerShell maybe you should use the  PSCoreWindowsCompat module (with aplogies to A-Team fans everywhere)

PowerShell arrays

An array is a collection of objects. PowerShell arrays can be created manually

PS> $a = 1,2,3,4

or

$b = @(1,2,3,4)

 

PowerShell will also create arrays automatically when needed:

PS> $ps = Get-Process

All three options are arrays:

PS> $a.GetType()

IsPublic IsSerial Name                                     BaseType 
 -------- -------- ----                                     -------- 
True     True     Object[]                                 System.Array

PS> $b.GetType()

IsPublic IsSerial Name                                     BaseType 
 -------- -------- ----                                     -------- 
 True     True     Object[]                                 System.Array

PS> $ps.GetType()

IsPublic IsSerial Name                                     BaseType 
 -------- -------- ----                                     -------- 
 True     True     Object[]                                 System.Array

 

The individual elements in an array are accessed using an index that starts at 0

PS> $a[0]
1

 

You can use a range of indices

PS> $a[1..2]
2
3

 

You can use negative indices to count from the end of the array

PS> $a[-1]
4

PS> $a[-1..-2]
4
3

 

PowerShell arrays are polymorphic by default meaning you can store any type of object in an array – and can store multiple types of objects in a single array

PS> $a += 'Hello World'

PS> $a
1
2
3
4
Hello World

 

We haven’t actually extended the array -  a new array is created that contains the old array and the new element. Any time you find yourself adding elements to an array in a loop – STOP and think about how you could do this as a pipeline.

PS> $x = @()
PS> 1..5 | foreach {$x += $_}
PS> $x -join ' '
1 2 3 4 5

 

is very inefficient compared to

PS> $y = 1..5 | foreach {$_}
PS> $y -join ' '
1 2 3 4 5

 

As you saw earlier you can add elements to an existing array. You can also remove elements from an array:

PS> $a = $a -ne 3
PS> $a
1
2
4
Hello World

 

Iterating over the contents of an array is as simple as

PS> $a | foreach {$_}

or

PS> foreach ($i in $a){$i}

 

PowerShell arrays are powerful tools that can make your coding much easier. This post has covered the most likely tasks you’ll face using arrays in PowerShell

PowerShell in 2018

So what is going to happen for PowerShell in 2018?

 

In April we have the Summit. Our biggest ever Summit with many more speakers, more sessions and new things including Iron Scripter. We’ll be starting the build up in early January so keep an eye on powershell.org.

 

PowerShell v6 will be GA in January. This is the point where you have decisions to make. Do you ignore v6; try and use v6 only or attempt some kind of dual use. Only your needs can answer what is the right solution for you but multiple PowerShell versions combined with multiple versions of Windows server – there’ll be feature updates in Match and September if plans remain the same – will definitely raise complications.

 

What should you be doing in 2018?

 

If you haven’t booked a Summit place and want to go then don’t be too late in registering. Sales have been much faster than last year and I suspect we’ll sell out early in 2018. We will have another batch of places available on alumni discount in January.

 

The Windows compatibility pack for .NET core (still seems ironic that’s its needed) will become available. That will plug some, but not all, of the gaps in functionality between v6 and v5.1. I’d recommend learning, or possibly re-learning, how to write scripts using System.DirectoryServices as it seems likely to be the only way to administer AD from v6 in the near future.

 

If you haven’t evaluated v6 then do so – side by side install with v5.1 makes that easier.

 

If you follow the PowerShell project on github you’ll see that v6.1 is already under discussion. I’d recommend that you join the discussion and help shape the future of PowerShell.

 

What would I like to see in 2018?

 

All the Windows inbuilt and RSAT modules modified to work with v6.

 

A simple and effective way to install and configure OpenSSH for PowerShell remoting on Windows – without having to install chocolaty or other third party features

 

A good set of cmdlets for managing containers

Cross platform PowerShell remoting

An interesting article on the Scripting Guy blog - https://blogs.technet.microsoft.com/heyscriptingguy/2017/12/29/cross-platform-powershell-remoting-in-action/

discusses using SSH remoting in PowerShell v6.

Some of the code needs tightening up but its a good first step for combining v6 and v5.1

2017 – a year of PowerShell

This is a good time to review what happened in the PowerShell community in 2017. It’s my perspective so is obviously biased based on my experiences.

 

The 2017 PowerShell Summit was an early highlight of the year. We sold out in early February and all registrations were for the whole f0ur days. This was fantastic and also prompted us to make the Summit a true 4 day event for 2018 and beyond. The Summit itself went very well. A few scares on the Sunday due to the flight problems caused by Delta airlines – at one point on the Sunday morning it looked like most of the speakers wouldn’t get to the event! Luckily, all but one made it so we didn’t have any major problems. The feedback we got during and after the Summit suggests that the event was very well received and enjoyed by all who attended.

 

Planning for the 2018 Summit started during the 2017 event – yes we do work that far in advance! We have to to get everything done. We’re expanding the Summit a little bit so we’ll have four full days with 4 rooms in use for break out sessions. We’ll have the team day where the PowerShell team come in and show us what they’re working on now and we’ll have the Community Lightning Demos that were so successful in 2017. We’ve also got some other exciting things happening at the 2018 Summit that we’ll start talking about in early January. Registrations have been going faster than last year so if you want a place I’d recommend making your purchase in early January.

 

The second major highlight was the publication of PowerShell in Action, third edition. The second edition was written when PowerShell v2 appeared so there is a lot of new material in the third edition. We edited down the older material as it was important it was covered but we needed to make space for the new stuff. At one point we thought we may have to do the book as two volumes.

 

The major change in PowerShell has been the rate of change and the diversification of PowerShell environments. By that I mean that PowerShell v5.1 has been modified with the feature updates for Windows 10 in March and September. There have also been changes with the introduction of Windows Server 1709. Its difficult to determine if the version of PowerShell you’re using is EXACTLY the same between these platforms. i haven’t heard of any major problems but its something to be aware of.

 

2017 also saw clarity emerging around PowerShell v6 and its positioning with regard to v5.1 (Windows 10, Server 206 & 1709 and WMF 5.1). The differences in functionality narrowed but there are still PowerShell v5.1 modules that won’t run under v6. Some of that will be addressed with the .NET core Windows compatibility pack – the thought of which has to be one of ITs biggest ironies - - a Windows compatibility pack for something that originated on Windows!! In some cases it may be necessary to go back to scripting solutions rather than supplied cmdlets – Active Directory seems a likely candidate.

 

I’d sum 2017 up from a PowerShell perspective as a year of change – change that we haven’t seen the end of.

Windows Updates CIM classes

When Windows 10 and Server 2016 were released they contained a new CIM namespace - ROOT/Microsoft/Windows/WindowsUpdate

 

This contained a CIM class MSFT_WUOperationsSession that had 2 very useful methods – ScanForUpdates and  ApplyApplicableUpdates.

 

These methods enabled you to find and install updates from the Windows Update site or a WSUS server if you’d configured the machine to use WSUS.

 

Best of all the CIM class could be accessed and used remotely which was a huge step forward over the old COM object that couldn’t be used remotely.

 

Things changed with Windows 10 Fall Creators Update (1709) and Windows Server 1709. MSFT_WUOperationsSession still exists but the methods you need to scan for updates and apply updates are now on the MSFT_WUOperations class. The great thing is that they’re static methods so using them is easier. The bad – no really, really bad – thing is that this class CAN’T BE ACCESSED REMOTELY through a Windows remoting session,  a CIM session or a SSH remoting session.

 

This takes us back to the bad old days of using COM objects. There doesn’t seem to be any reason or explanation for this decision.

 

I have managed to use the class remotely through a PowerShell direct remoting session though which means that I can force updates in my lab. Its not really an answer for production though

Test-Path -PathType

Test-Path is a useful cmdlet for testing the validity of a path. You get a True/False return depending on if the path exists or not.

 

There’s also a way to add to the test by determining if the path points to a container (folder) or a leaf (file) using the –PathType parameter.

 

Here’s some examples that show how it works:

PS> Test-Path -Path C:\Scripts\
True
PS> Test-Path -Path C:\Scripts\ -PathType Any
True
PS> Test-Path -Path C:\Scripts\ -PathType Container
True
PS> Test-Path -Path C:\Scripts\ -PathType Leaf
False
PS> Test-Path -Path C:\Scripts\foo.txt -PathType Container
False
PS> Test-Path -Path C:\Scripts\foo.txt -PathType Leaf
True

 

C:\Scripts is a folder and foo.txt in a file in that folder.

 

Test-Path –PathType is a good way to focus your test to ensure you’re dealing with a file or a folder as appropriate.

PowerShell v6: #9 Release candidate 2 features

A couple of features of PowerShell v6 release candidate 2 need commenting on.

 

Firstly, I was surprised when installing RC 2 on a Windows 10 machine (Insider build) that RC1 was removed. In the past you’ve been able to run numerous versions of PowerShell v6 side-by-side. This has consequences if the behaviour continues into the GA version and the 6.1 alpha/beta releases as you’ll have to choose between the stable, production version and the changeable new version.

 

Secondly, and this one was publicised by the PowerShell team, Pester is no longer installed by default with PowerShell v6. You can download the latest version of Pester from the PowerShell gallery. Not sure on thinking behind this decision but the download is easy so it’s not a deal breaker –you just have to remember to do it. May be best to use Save-Module for the download so you don’t have to perform the download if a new version of PowerShell v6 becomes available and overwrites the current version.

 

Next job is to install the OpenSSH optional feature and see how that goes. Be very interested to see if and how its updated as new versions of the  Windows Insider builds are released.