Category Archives: PowerShell 5.0


Quick Tip: See All The Tab-Completion Options At Once In The PowerShell Console

If you’re used to working in VS Code or the PowerShell ISE, you’ve undoubtedly enjoyed intellisense which is the feature that shows you all the tab completion options at once. That functionality is really handy, but what if you’re in the PowerShell console? The little overlayed windows don’t pop up there with your completion options. You can still tab through until you find what you want, but it’s not the same.

Don’t worry, there’s a PSReadline feature that will save you here.

Continue reading


Quick Tip: Split A PowerShell Collection Into Two Arrays

Did you know that you can use Where-Object to split a collection into two arrays? Like, if you had an array containing the numbers 1 to 10, you could split it into one array of even numbers, and another array of odd numbers? It’s pretty cool. Thanks Herb Meyerowitz for this tip!

Continue reading


Quick Tip: Copy The Output Of The Last PowerShell Command To Clipboard

I recently found myself poking around in PowerShell and going “oh, good now I want to copy and paste that output into an email/dialog box/tweet/notepad/another script/complaint box” and either trying to copy and paste it out of PowerShell or hitting the up arrow and piping whatever the last command was into Set-Clipboard. What a hassle.

So, I threw this small function into my profile.

You’ll need PowerShell 5.0 for this one (for Set-Clipboard). This just looks like gibberish though, what’s going on?

Well, clearly I’m defining a function named cc which is not a properly named PowerShell function but I’m being lazy. What does it do? Well it does r | scb.

r is an alias for Invoke-History which re-runs the last command you typed. Try it yourself.

scb is an alias for Set-Clipboard which means whatever came out of the last command will be the new contents of your clipboard.

The cool thing about this is it doesn’t just have to be text. Check out my other post about all the things Set-Clipboard can do.


Getting Started With Pester

If you don’t know what Pester is, it’s a framework for running unit tests and validating PowerShell code. Also, it’s awesome. In May I finally dipped my toe in the water with a pretty simple test for a REALLY simple function. I’m not going to go into a world of detail on how exactly all my Pester code works because there are tons of guides for that. What I’m going to do instead is provide a quick run down of what I came up with.

First things first, I need a function to validate.

I guess that will work. Write-SomeMath takes two integers and returns their sum. Hardly a breathtaking display of complexity and function but it will do just fine for this example.

Now I need to install Pester. The easiest way to do this is using the PSGet module in PowerShell 5.0 to get it from

The next thing I need is a Describe block.

This Describe block will contain and – you guessed it – describe the tests (I just used my filename) and provide a unique TestDrive (check out the getting started link).

Now I need a Context block.

I’m further grouping my tests by creating a Context here for my Write-SomeMath function. This could have been named anything.

Now, I could start with a bunch of tests, but I want to show off a particular feature of Pester that allows you to pass an array of different test cases.

All I did was define an array called $testcases which holds an array of hash tables. It’s got the first number, second number, expected result and a name of what we’re testing. Now I can pass this entire array to a test rather than crafting different tests for all of them individually.

This is an It block which is what Pester calls a test. I’ve named it “Can add <test>” and it will pull the “test” value from the hashtable and fill it in. Cool! I’m using the -TestCases parameter to pass my array of test cases to the It block. Then I’ve got parameters inside the test for my first value, second value and expected outcome. I execute Write-SomeMath with the values pulled from my test cases and pipe the result to “Should Be” to compare the outcome to my expected outcome.

Now, just one more test for fun. What if I don’t pass an integer to my function?

Another It block for detecting wrong datatypes. I pipe the result into Should throw because my function should throw an error. For this to work properly, the code I’m testing has to be wrapped in a scriptblock, otherwise the thrown error will occur and be trapped in my function.

Here’s the outcome when I run this file!

Getting Started With Pester - Results

Pester Results

Pretty cool. My first test passes, the second one fails and tells me why, the third and fourth tests pass. The fourth one is especially interesting. The function FAILED but because the test said it SHOULD FAIL, the test itself passed.

So that’s my “dip my toes in the water” intro Pester test. Stay tuned for more complicated examples.


Just Enough Administration (JEA) First Look

If you’re reading this, it means that Windows Server 2016 Technical Preview 4 is released (currently available on MSDN) and one of the new features that’s available is Just Enough Administration (JEA)! Until now, you could use DSC to play with JEA but now it’s baked into Windows Server 2016.

If you’re not sure what JEA is or does, check out this page published by Microsoft.

So how do you get started?

JEA gets put together like a module. There are a bunch of different ways to dive in, but for convenience, I’m just covering this one example. Build on it and learn for yourself how JEA can work for you specifically!

First things first, make a new directory in your modules folder and navigate to it.

So far, so easy. Now, we’re going to use the brand new JEA cmdlets to configure what is basically our constrained endpoint.

This PSSC is the first of two files we’re going to make. It’s a session config file that specifies the role mappings (we’ll get to roles in a second) and some other general config settings. A PSSC file looks like this.

If you’ve ever authored a PowerShell module before, this should look familiar. There’s only a few things you need to do here. The first is change the value for SessionType to RemoteRestrictedServer. You need to make it this in order to actually restrict the user connections.

You can enable RunAsVirtualAccount if you’re on an Active Directory Domain. I won’t get too deep into what virtual accounts do because my example is just on a standalone server.

The other important task to do is define the RoleDefinitions line. This is a hashtable where you set a group (in my case, local to my server) assigned to a “RoleCapability”. In this case, the role I’m assigning is just named “testers” and the local group on my server is named “test users”.

Save that and now it’s time to make a new directory. Roles must be in a “RoleCapabilities” folder within your module.

Now we are going to continue using our awesome new JEA cmdlets to create a PowerShell Role Capabilities file.

It’s very important to note here that the name of my PSRC file is the same as the RoleCapability that I assigned in the PSSC file above.

PSRC files look like this. Let’s point out some of the key areas in this file and some of the tools you now have at your disposal.

Think of a PSRC as a giant white list. If you don’t explicitly allow something, it’s not going to happen. Because PSRCs all act as white lists, if you have users who are eligible for more than one PSRC (through more than one group membership/role assignment in a PSSC), the access a user gets is everything that’s white listed by any role the user is eligible for. That is to say, PSRCs merge if users have more than one that apply.

Let’s skip ahead to line 25. What I’m doing here is white listing any cmdlet that starts with Get- or Measure- as well as Select-Object. Inherently, any of the parameters and values for the parameters are whitelisted, too. I can hear you worrying, though. “What if a Get- command contains a method that allows you to write or set data? I don’t want that!” Well, rest assured. JEA runs in No Language mode which prevents users from doing any of those shenanigans.

Also in line 25, I’m doing something more specific. I’m including a hashtable. Why? Because I want to allow the New-Item cmdlet but only certain parameters and values. I’m allowing the ItemType parameter but only if the user sets it to Directory. I’m allowing Force, which doesn’t take a value. I’m also allowing the Path attribute, but, only a specific path. If a user tries to use the New-Item cmdlet but violates these rules, the user will get an error.

On line 19, I can import specific modules without opening up the Import-Module cmdlet. These modules are automatically imported when the session starts.

On line 28, we can make specific functions available to connecting users.

Line 31 is interesting. Here I’m making an individual script available to the connecting user. The script contains a bunch of commands that I haven’t white listed, so, is the user going to be able to run it? Yes. Yes they are. The user can run that script and the script will run correctly (assuming other permissions are in place) without having the individual cmdlets white listed. It is a bad idea to allow your restricted users to write over scripts you make available to them this way. 

On line 37, you can basically configure a login script. Line 40 lets you define custom aliases and line 43 lets you define custom functions that only exist in these sessions. Line 46 is for defining custom variables (like “$myorg = ‘ThmsRynr Co.”) which can be static or dynamic.

With these tools at your disposal, you can configure absolutely anything about a user’s session and experience. Sometimes, you might have to use a little creativity, but anything is possible here.

Lastly, you need to set up the JEA endpoint. You can also overwrite the default endpoint so every connection hits your JEA config but you may want to set up another unconstrained endpoint just for admins… just in case.

That’s it. You’re done. Holy, that was way too easy for how powerful it is. Now when a user wants to connect, they just run a command like this and they’re in a session limited like you want.

If they are in my local “Test Users” group, they’ll have the “testers” role applied and their session will be constrained like I described above. You’ll need to make sure your test users have permissions to remotely connect at all, though, otherwise the connection will be rejected before a JEA config is applied.

I can think of a bunch of use cases for JEA. For instance…

1. Network Admins
I’d like my network admins to be able to administer DHCP and DNS on our Windows servers which hold these roles without having carte blanche admin rights to everything else. I think this would involve limiting the cmdlets available to those including *DHCP* or *DNS*.
2. Certificate Management
We use the PSPKI module for interacting with our Enterprise PKI environment. For this role, I’d deploy the module and give users permissions to use only the PSPKI cmdlets. I’d use the Windows CA permissions/virtual groups to allow or disallow users manage CA, manage certificates, or just request certificates.
3. Code Promotion
Allowing people connecting via JEA to read/write only certain areas of a filesystem isn’t practical. The way I’d get around this is to allow access to run only one script which performed the copy commands or prompted for additional info as required. You could mix this in with PowerShell Direct and promote code to a server in a DMZ without opening network holes or allowing admin access to a DMZ server.
4. Service Account for Patching
We have a series of scripts that apply a set of rules and logic to determine if a server needs to be patched or not. All it needs to do is perform some WMI queries, communicate with SCCM (which has the service installed to actually do the patching) and reboot the server. Instead, right now, that service account has full admin rights on the server.
5. Help Desk
Everybody’s help desk is different but one job I’d like to send to my help desk is some limited Active Directory management. I’d auto-load the AD module and then give them access to very restricted cmdlets and some parameters. For instance, Get-ADUser and allow -Properties but only allow the memberof, lockedout, enabled and passwordlastset values. I might also allow them to add users to groups but only if the group was in a certain OU or matched a certain string (ie: if the group ends in “distribution list”).
6. Print Operators
We have a group of staff on-site 24/7 that service a giant high speed print device. There are a number of servers that send it jobs and many are sensitive. I’d like to give the print operators group permissions to reach out and touch these servers only for the purposes of managing print jobs.
7. Hyper-V Admins/Host Management
These guys need the Hyper-V module and commands within it as well as some limited rights on the host, like Get WMI/CIM objects but not the ability to set WMI/CIM objects.

Get playing!

The possibilities of what you can do with JEA are endless. While the DevOps mentality is flourishing, the need to enable access to different systems is growing. With JEA, you can enable whatever kind of access you need, without enabling a whole bunch of access you don’t. That’s probably why it’s called “Just Enough Administration”.


New Stuff: Get-Clipboard And Set-Clipboard – New In PowerShell 5.0

Predictably, there are lots of new cmdlets coming in PowerShell/Windows Management Framework 5.0. Two of them that just came out in build 10105 are the Get-Clipboard and Set-Clipboard cmdlets. The help docs aren’t all written at the time I’m writing this post but I wanted to introduce them and highlight a couple neat use cases I immediately thought of.

New Get-Clipboard and Set-Clipboard cmdlets

New Get-Clipboard and Set-Clipboard cmdlets (click for larger)

Back in the old days of PowerShell 4.0, you had to pipe output to clip.exe or use the PowerShell Community Extensions to interact with your clipboard. Not anymore!

Looking at the Get-Clipboard syntax, it’s quickly apparent that you can do more than just get the clipboard’s text content but let’s start with that anyway. So, what if I go and select some text, right click and copy it. What can I do with the Get-Clipboard cmdlet?

Not exactly mind blowing. Similarly, you can use the Set-Clipboard cmdlet to put text on the clipboard.

I’m probably not blowing your mind with this one either. Where this gets fun is when you consider the possibilities the using the -Format parameter. I can put more than just text on my clipboard, right? Let’s see what I get when I copy three files in my c:\temp directory to my clipboard. If I try to just use Get-Clipboard without any additional parameters or info like I did in the above examples, I won’t get anything returned, but what I can do is this.

Now we’re doing cool things. And what kind of objects are these?

FileInfo! We can do all the same things with this array of files that we would do to the results of a Get-ChildItem command. This means we can go the other way too and use the Set-Clipboard cmdlet to put a bunch of files onto the clipboard.

Note with all of the above examples, you can use the -Append parameter to simply add on to whatever is already on the clipboard.

I won’t cover the other formats (Image and Audio) or the text format types because you need something to discover for yourself. The last thing I’ll point out is that you can easily clear the clipboard, too.

I’m not going to cover every new cmdlet that comes out with PowerShell 5.0 but this one is very accessible and I think I’ll be able to use it all over the place.