Monthly Archive

Categories

Active Directory cmdlets in PowerShell v6.1.1

Just discovered that you can run the Active Directory cmdlets in PowerShell v6.1.1 BUT there is a huge caveat.

 

The Windows 10 October 2018 (Windows 10 1809) update includes the RSAT tools (including the AD tools) as optional features. This means that you can easily install the AD tools:

Add-WindowsCapability -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0 –Online

 

The AD PowerShell module now has a 1.0.1.0 version with the PSEdition set as Core,Desk

 

I’m running the Windows 10 Insider Preview build 18282 which has moved on a bit from Windows 10 1809 and PowerShell Core v6.1.1.

 

The AD module can be imported and the commands that I’ve tried have worked.

 

For the AD cmdlets to work in PowerShell Core looks like you need Windows 10 October 2018 update or later and PowerShell v6.1.1 or later. I’m going to say you should upgrade to v6.1.1 if you have v6.1 as the later version fixes a .NET security bug.

 

This is a big step forward for PowerShell Core being an acceptable replacement for Windows PowerShell though there are still a few gaps to be filled.

Reverse an array

Ever needed to reverse an array?

If its sorted then sorting in the opposite direction will work. Most arrays aren’t sorted so you need to use the Reverse static method of the array class

 

Here’s some examples

$carray = 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'
$carray -join ','
[array]::Reverse($carray)
$carray -join ','

 

$iarray = 1,2,3,4,5,6,8,9,10
"$iarray"
[array]::Reverse($iarray)
"$iarray"

 

$psa = Get-Process p*
$psa
[array]::Reverse($psa)
$psa

 

The thing to note is that the array is reversed rather than creating output so if you do this

$iarray = 1,2,3,4,5,6,8,9,10
$newary = [array]::Reverse($iarray)

$iarray is reversed and $newary is empty!

 

If you need the original and reversed arrays take a copy of the original and then reverse one of them.

Hyper-V book now available

My Hyper-V book now available.

 

Ebook direct from the publisher: https://www.apress.com/gb/book/9781484241158#otherversion=9781484241165

 

The Kindle version is on Amazon UK:

https://www.amazon.co.uk/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=hyper-v+2019&rh=i%3Aaps%2Ck%3Ahyper-v+2019

Presumably other Amazon sites will follow soon

 

The paper back version is on pre-order from Apress and Amazon to be available on 25 December 2018 – Happy Christmas

Finding the minimum and maximum values

Finding the minimum and maximum values in a set of numbers is ridiculously easy with PowerShell.

I’ve created a function in line with the other techniques I’ve shown but in reality could be be done equally well as a single line of code:

function get-minmax {
[CmdletBinding()]
param (
[int[]]$iarray
)

$mm = $iarray | Measure-Object -Minimum -Maximum

New-Object -TypeName PSobject -Property @{
Minimum = $mm.Minimum
Maximum = $mm.Maximum
}
}

 

Just pipe the array into Measure-Object and use the –Minimum and –Maximum parameters as shown. I created an output object for easier handling if you want to do anything else to the array.

 

You can also get the sum and average of the array with Measure-Object. PowerShell v6.1 adds the Standard Deviation and an –Allstats parameter so you don’t need to specify each individual option:

PS> $iarray = 1,2,3,4,23,5,6,7,8,9,10,23,11,12,13,7,14,15,16,17,18,20,21,22,11,23,24,25
PS> $iarray | Measure-Object -AllStats

Count : 28
Average : 13.2142857142857
Sum : 370
Maximum : 25
Minimum : 1
StandardDeviation : 7.46030057411125
Property :

Windows 10 install wasting my time

I’ve just made the mistake of installing Windows 10 Insider preview build 18272 from the iso. The only thing I can say is that Windows 10 install wasting my time.

 

The install proceeds as you would expect but then once the basic OS installation is complete it crawls, at the speed of a overloaded truck with no engine, through a whole series of questions about settings.

 

If Windows got out of my way and let me perform the settings changes they’d have been done in a few minutes instead the windows install wasted the best part of 30 minutes taking me through its ridiculous setup dialog.

 

What’s worse is that its the Enterprise edition I was installing!

 

Microsoft please get out of my way and let me make changes. Every edition of Windows since Vista has made it harder and harder to actually make changes. The continuously changing settings menus mean that the settings you need are buried further and further under meaningless dialogs and when you do get the bottom you’re often using the old control panel!

 

The continuous feature update promised by Windows 10 is failing because its actually getting harder to do things. Contrary to your belief Microsoft you don’t know better than me how I want my machines configured – you’re applying a blanket best guess set of settings that are becoming more difficult to unravel.

Find a missing integer–alternative solution

In my recent post about finding a missing integer in an array of numbers I didn’t spell out the assumptions. In this post I’ll explain those assumptions and show you how to Find a missing integer–alternative solution.

The assumptions were:

The sequence of numbers in the array starts at 1

The values increment by 1

 

If the sequence doesn’t start at 1 the technique fails as the expected sum being n(n+1)/2 breaks down.

As an alternative you can calculate the expected sum by finding the average of the numbers in the sequence and multiplying by the number of expected entries in the sequence.

function get-missinginteger {
[CmdletBinding()]
param (
[int[]]$iarray,

[int]$expectedlength
)

#$expectedSum = ($expectedlength * ($expectedlength + 1) ) / 2

# don't know if array is in numeric order
$sarray = $iarray | sort

$expectedSum = $expectedlength * (($sarray[0] + $sarray[-1]) / 2)

$actualsum = 0
foreach ($n in $iarray) {
$actualsum += $n
}

$missingnumber = $expectedSum - $actualsum
$missingnumber
}

 

I’ve changed the function name. The only other change is to sort the array and calculate the expected sum using the average

$sarray = $iarray | sort
$expectedSum = $expectedlength * (($sarray[0] + $sarray[-1]) / 2)

 

The examples from the previous post work as does

PS> $iarray = 6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,22,23,24,25

get-missinginteger -iarray $iarray -expectedlength 20

19

Finding and removing duplicates

Continuing the thoughts about techniques for dealing with integer arrays – this is how to go about finding and removing duplicates from the array.

First – to find any duplicates use Group-Object

function get-duplicate {
[CmdletBinding()]
param (
[int[]]$iarray
)

$iarray | Group-Object |
where Count -gt 1 |
foreach {
New-Object -TypeName PSobject -Property @{
DuplicateNumber = $_.Name
Count = $_.Count
}
}
}

 

If the count is greater than 1 it means you have duplicates so create an output object and display the integer value and the total number of occurrences.

 

Removing duplicates is a bit more tricky

function remove-duplicate {
[CmdletBinding()]
param (
[int[]]$iarray
)

$dupcount =@{}

$duplicates = get-duplicate -iarray $iarray

$dedup = $iarray | foreach {
if ($_ -in $duplicates.DuplicateNumber) {
if ( -not $dupcount["$_"]) {
$dupcount += @{"$_" = 1 }
$psitem
}
}
else {
$psitem
}
}

$dedup
}

 

Get the duplicates as before. Iterate over the input array. If the value is found in $duplicates.DuplicateNumber – your using the object property as a property of the array to effectively get an array of the duplicate values – test to see if its in the $dupcount hashtable. If it isn’t add an entry to the hashtable and output the value. If it is in $dupcount do nothing and therefore skip that value.

 

If the value isn’t in $duplicates.DuplicateNumber emit the value.

 

You’ll notice that any values output by the foreach cmdlet go straight into $dedup array – this builds that array automatically and is the most efficient way to get the values into the array.

 

Final step is to output the de-duplicated array.

Find a missing integer

I stumbled across a set of programmer interview questions recently. They raised some interesting problems that I thought would be fun to show a PowerShell answer. This is the first of them – find a missing integer in an array.

Consider an array of integers. It should have 10 members:

$iarray = 1,2,3,4,5,6,7,8,9,10

 

But what if one is missing

$iarray = 1,2,3,4,5,6,8,9,10

In this case the number 7 is missing.

 

This problem assumes that there is a regular increment between members of the array – in this case 1. In mathematical terms its a series.

function get-missingnumber {
[CmdletBinding()]
param (
[int[]]$iarray,

[int]$expectedlength
)

$expectedSum = ($expectedlength * ($expectedlength + 1) ) / 2

$actualsum = 0
foreach ($n in $iarray) {
$actualsum += $n
}

$missingnumber = $expectedSum - $actualsum
$missingnumber
}

 

The solution is to find the expected sum of the series which is found using

(n * (n + 1)) / 2

where n is the expected length of the series. 1 is the increment between members of the series. You can generalise this for any increment but that’s left as an exercise for you.

 

Then calculate the actual sum by looping through the array and summing the values.

 

The missing number is the difference between the expected sum and the actual sum

 

Here’s some examples

PS> ## 10 integers - number 7 missing
PS> $iarray = 1,2,3,4,5,6,8,9,10
PS> get-missingnumber -iarray $iarray -expectedlength 10
7

PS> ## 25 integers - number 19 missing
PS> $iarray = 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,21,22,23,24,25

PS> get-missingnumber -iarray $iarray -expectedlength 25
19

 

A quick way to generate the array to play with:

PS> $r = Get-Random -Maximum 26 -Minimum 1
PS> $iarray = 1..25 | where {$psitem -ne $r}
PS> get-missingnumber -iarray $iarray -expectedlength 25
22
PS> $r
22

Managing errors

If you try to do a directory listing through C:\Windows\system32 you’ll get some access denied errors. I’m going to show you how to do this while managing errors that arise. The code will also highlight a few of the PowerShell error handling techniques.

 

$epath2 = $null

Get-ChildItem -Path C:\Windows\System32 -Recurse -Force -Directory -ErrorVariable epath2 |
foreach {
if ($?) {
Out-File -InputObject $_.FullName -FilePath c:\test\paths.txt -Append
}
}

if ($epath2) {
$epath2 |
foreach {
($_.Exception -split "'")[1] | Out-File -FilePath c:\test\errors.txt -Append
}
}

 

Set $epath2 to $null to clear any data.

 

Use -ErrorVariable epath2 to define the variable into which errors are directed.

 

Get-ChildItem will recurse through the folder structure – use –Directory to ignore files.

 

In the foreach statement check $? which holds True or False depending on if last statement succeeded. Append the full path to the folder to the paths.txt file.

 

If $epath2 has a value then iterate over the values splitting out the folder paths from the error statement. Write to errors.txt

Test-Connection cmdlet

The Test-Connection cmdlet wasn’t included in PowerShell v6.0 but did make a come back in v6.1.

 

The v6.1 version of Test-Connection has some serious issues as I’ve described before.

 

Work is being done at the moment to remedy those issues – hopefully for v6.2

 

This is your chance to comment on a cmdlet and help determine how it will work.

 

The issues to comment on are:

https://github.com/PowerShell/PowerShell/issues/7685

https://github.com/PowerShell/PowerShell/issues/6557

 

PowerShell v6 is community driven.  This is an opportunity to help drive the PowerShell you want to see.