Author: Adam Fowler

How To Grep in PowerShell

For those who have lived in the Linux/Unix command line, the ‘grep‘ command is a commonly used way of finding something that you want in a chunk of data.

Øyvind Kallstad did a great writeup of comparing a bunch of ways to use PowerShell instead of grep which is worth reading.

The article covers a bunch of scenarios, and is centered around starting with the ‘grep’ command and working with it. However, there’s the other common use case of running a different command, then piping those results to grep to search for something.

This blogpost was triggered by Janet who asked me this fair question:

As with poor cute cats, there’s more than one way to skin PowerShell.

I had to do some research and asking around on this, because normally I’d filter out the property of the object I was looking at, and work with that. Using the get-process example:

get-process | where ProcessName -like "*foo*

That works, but it’s still a lot clunkier than what a grep user would expect. An easier way would be to use the ‘findstr‘ program (which also has a bunch of useful swtiches):

get-process | findstr foo

I say program because ‘findstr’ is not a PowerShell cmdlet, but it’s still native to Windows and works perfectly fine. It’s case sensitive though, so you need to use -i for case insensitive results.

That’s great for simple stuff, but we’re sort of breaking what PowerShell does. You’re no longer dealing with a standard PowerShell object, so further piping and processing won’t really work.

The ‘proper’ PowerShell way would be to use the ‘Where-Object’ command:

Get-Process | Where-Object {$_ | Select-String "foo"}

A bit longer, but you can shorten ‘Where-Object’ to ‘Where’. Although more involved, it’s good to get into the habit of doing it this way, so when you’re piping this to the next command, it still says as a standard object that can be read and manipulated.’

(Update 24th Feb 2017) As Steve_N points out in the comments section, there’s a much shorter way of doing this:

ps *foo*

That’s it. Many PowerShell commands have inbuilt aliases, including ‘get-process’. You can see what this is with the command ‘get-alias -definition get-process’

This shows that ‘gps’ and ‘ps’ are both aliases to the command  ‘get-process’. You can also create your own aliases with the ‘set-alias‘ command.

The ‘*foo*’ part works because the command assumes the -name switch has been used, which lets you define what criteria to search and show in the ProcessName field. This is the same way that many commands don’t need the -identity switch used, because it’s written to assume you’re going to tell it what identity/username/upn to work with.

This can also be piped to something else, so it’s a winner. It’s less ideal for scripts though, because it’s much harder to read, and you can’t assume that everyone will know the short alias of a full command.

(Update ends)

PowerShell isn’t a Linux/Unix command line, but Microsoft have incorporated many of the concepts from bash. If you still can’t bear to use PowerShell on Windows, there’s always the Linux Bash Shell on Windows.

Thanks again to Steve Mclnerey for the grep advice 🙂

Why Haven’t You Deployed LAPS Yet?

LAPS – Local Administrator Password Solution is an official Microsoft solution for doing exactly what it’s called – managing local administrator passwords on the computers you manage (both desktops and servers).

The solution is fairly simple – have a tiny client rolled out on each PC, that gets told by Group Policy to generate a random password. The local admin account gets set to that password, and Active Directory also gets told what that password is. That changes on a 30 day cycle

The end result is that anyone who obtains local admin access through that account, can’t access anything beyond that single computer – and, that’s only for 30 days maximum before it gets changed. Even if the computer is taken off the domain, your Active Directory will have a record against the computer of what the last set password was.

There’s a great overview, demo, and install files available from TechNet with Jessica Payne going into great detail on how it all works and showing you exactly what to do which I highly recommend after watching it personally.

As she says, it only takes 10 minutes or so to set up, and it’s that much more secure than using Group Policy to set everyone’s local administrator account to the same password (which by the way, doesn’t securely save the password in the Group Policy anyway) and running into issues when someone needs the local administrator password for one reason or another.

Oh, there is a tiny AD schema update, but it’s a single command and nothing to worry about 🙂

Once you’ve got LAPS set up, you use the LAPS UI program to view passwords:

Chris Brown has also written up a nice ‘how-to’ guide on setting up LAPS from end to end which is worth following too.

LAPS is easy to deploy, easy to manage and provides several security benefits… and it’s free. If you’re not using LAPS yet, it’s time to do it! Grab it from Microsoft here.

Gaming PC Build 2017

My 5+ year old PC was finally ageing – Battlefield 1 was maxing out the Intel i5 CPU! It’s time to upgrade to a whole new kit. After some research and help from PC Part Picker, this is what I bought:

Intel Core i7-7700K 4.2GHz Quad-Core Processor

Deepcool Gammaxx 400 CPU Cooler

MSI Z270 GAMING M5 ATX LGA1151 Motherboard

Corsair Vengeance LPX 16GB (2 x 8GB) DDR4-3200C16 Memory

Intel 600p Series 512GB M.2-2280 Solid State Drive

Corsair 300R ATX Mid Tower Case Windows Edition

Corsair CS650M Modular 80 Plus Gold ATX Power Supply

You may notice there’s no GPU. I’ll be re-using my NVIDIA GTX970 as that was more recently updated. If I didn’t have that, I would have probably chosen a GTX1070. I also added in an old DVD drive and 1.5TB HDD because why not.


Notes from during the build:

Lining up the motherboard back panel into the case, and then getting the motherboard to line up with it. It looked like it was in place, but not enough to have the screws in the case line up with all the holes in the motherboard.

CPU Fan – Completely my fault, I put the wrong brackets on. I was still thinking of my old 1155 pin CPU when I followed the back of the box instructions, rather than the 1151 pins that my new CPU was. Then I had to work out how the weird clips worked, as there was a single line of instruction: “Well note: turn before push”. Apparently that means don’t turn at all, which took some trial and error to discover.

Working out how to install M.2 SSDs – this wasn’t really a problem, just something I hadn’t done before. It’s held in place with a screw and screw holder, which I eventually found already in the motherboard, but in a hole designed for the largest M.2 card possible.

This case is pretty good for HDDs and DVD Drives – it’s a screwless solution for both, but you do need to access both sides of the case. Both sides also come off easily with 2 thumb screws.

I did a bit of cable management, which previously I hadn’t bothered with as I’d be changing things around every couple of months (I remember adding my 9th 320GB HDD to my PC years ago, and then trying to juggle SATA and power cables around to make it all work). The case again was pretty good for this, I just fed the cables through to the bottom side of the motherboard, then brought them back out again where they needed to go.

CPU was just a drop in the right way, have the arrows line up job. Pushing the bracket back onto the CPU to hold it into place is a little worrying, more force is required then I was comfortable applying.

PSU is modular, so you can have just the cables you need coming out of it which reduces clutter. 650w is overkill I’m sure for this, as I could have bought a 550w for half the price but it wouldn’t have been modular, and I also like keeping my options open for future changes. Installation of the unit was sliding in and putting a couple of screws on.

The GPU I already had fits in with lots of room – it looks like they’ve changed the design of the PCI-E slot which used to have a plastic tab to bend to insert or remove the card – that’s changed to a tab that’s the same style as the RAM sockets.

RAM hasn’t changed at all installation wise 🙂 The only trick is to make sure you populate the right slots – check the manual, but usually it’s also on the motherboard too (which it was in this case).

Idling temps after install were around the 39oC – but after overclocking and leaving it a few days, it seemed to settle lower at 37oC.


Getting the software going:

Thankfully after getting it all together and installing Windows 10, there were no issues. Lucky I installed that DVD drive, as the network device wasn’t installed with a default driver, and I had to load it off the included CD-ROM. Yep, 2017 and we’re still loading base drivers that way.

The amount of utilities provided by MSI is a bit silly, and it’s really hard to tell what any of them do until you install them. I’ve got one that claims to give a fast boot – the few seconds it takes without that is fast enough already. The MSI Command Center is useful as it shows CPU/RAM settings and speeds, as well as system temp. The MSI Gaming App was the one that let me turn off the motherboard’s LED, rather than setting it to ‘breathe’ where it would fade in and out in one of 7 amazing colours.

I also used the motherboard’s inbuilt overclocking ‘gaming mode’ option – it upped the CPU from 4.2Ghz to 4.8Ghz. I found another option around the RAM where I set that to 3200Mhz, and it did it’s thing on changing settings to match that RAM speed. If you’re not going to do this by the way, don’t get the ‘K’ series Intel I7, or RAM faster than 2400Mhz because that’s all it will run at out of the box.

Also, if you have a look at some comprehensive reviews you’ll see that there’s barely any benefit in the 7th generation Kaby Lake Intel CPUs vs the 6th generation Skylake (don’t ask me why Skylake is one word, and Kaby Lake is two words either), if you aren’t using the onboard GPU which gets the biggest gains. Right now, the price is pretty much identical between the 6700K and 7700K which is why you might as well go the newer one – there’s no negatives there.

This setup is very quiet too, there’s minimal noise from any fans which is great.


Here’s some pictures of the build process. I’m happy to report that after a few days and testing Battlefield 1, I’ve had zero blue screens, and CPU sits around 60% max when playing.





PowerShell – ‘While’ Loop Statement

There’s a lot of different ways to loop commands in PowerShell, and here’s one I just learnt (thanks Nathan Kewley for spending the time talking me through this!):

Scenario: You create a brand new user in Active Directory, but need to wait for things to sync before you make a change to the user. If you want to automate these steps, you want to check that the user exists before running more commands against it.

Answer: The ‘While‘ statement. This lets you loop a command ‘while’ something is a certain value. For example, you may want a script to loop for two minutes, or until a certain value is true or false.

With my script below, it will check if the value $running is nothing (null), which it is because we just made it up. Because it’s true, it’ll then continue on to do whatever is in the curly brackets. Here, I’m running a command the enable a user in Skype for Business, but also setting the result of that as the variable $running.

If the command works, $running now has a value of the created user, so as it loops again to see if $running is null, it won’t be, and the ‘while’ statement is done.

If the command fails however, and shows the dangerous red warning around the user not existing, nothing gets set to the $running variable. That means, when it loops again, $running will still be null so it’ll try again and again and again.

while($running -eq $null){
 $running = Enable-CsUser -Identity testuser -SipAddress

That’s rather dangerous of course, what if it’s forever $null? It’ll run forever, so we’d better put in some failsafes.

while($running -eq $null){
 if($CheckUser -le '10'){
  start-sleep -s 10
  $running = Enable-CsUser -Identity testuser -SipAddress

OK, this time we’re doing a couple more things. We’ve got two curly bracketed things to run now, the first is an ‘If’. If $CheckUser is less or equal to 10, then do the next curly bracket thing. The first time this runs that value again doesn’t exist because we just made it up, and nothing is less or equal to 10. The If statement is true, so it moves onto the next segment.

The $CheckUser++ command just adds ‘1’ to the value of $CheckUser – starting off at null or 0, so will turn into 1. As the statement loops, that number will increment all the way up to 11. Once it’s 11, the If statement is no longer true, so bombs out.

We’ve also added the start-sleep command, which is just a 10 second wait before doing anything. If we didn’t have that there, the 11 loops before it fails would be over incredibly quickly.

The last thing we can add is an event to occur once the ‘If’ statement is no longer true:

while($running -eq $null){
 if($CheckUser -le '10'){
  start-sleep -s 10
  $running = Enable-CsUser -Identity testuser -SipAddress
Throw "Unable to create SfB User"

All we’ve done here is added the ‘Else’ section, which only runs when the ‘If’ isn’t true. Once the $CheckUser variable hits 11, the ‘Else’ command runs and throws up an error, with the aptly named ‘Throw’ command.

Hopefully this is enough to explain the basics of the ‘While’ command.

Security Quality Rollup Confusion – Windows Updates

Since October 2016, Microsoft have updated their Windows Updates model (for Windows 7, 8.1, Server 2008 R2 SP1 and Server 2012 R2) to a more cumulative approach. To their credit, they had this communicated months before it started, and the word got around long before the first patch rolled out.

At the time I talked to Tom Walat who was reviewing what people thought of this model. There’s been a bit of confusion and changes in the model, including a new one for February 2017 where Internet Explorer will be seperated and have it’s own rollup. If you manage WSUS, you need to be across these changes.

There’s a great detailed blogpost on TechNet about the history and changes, as well as this really useful table:

Windows Updates for 7 and 8.1 table for Feb 2017 (source)

Here;s the TLDR version which is still long, sorry;

Since October 2016 to January 2017, there has been two main update rollups – a Security Monthly Quality Rollup which contains ‘all the patches’. In WSUS, this will have a name like “January, 2017 Security Monthly Quality Rollup for Windows 7”. There is a separate rollup for Windows 7, 8, Server 2008 R2 and 2012 R2. These are cumulative – each Rollup includes all previous rollup patches, but nothing that’s before October 2016. This is the recommended package.

There’s also the similarly named Security Only Quality Update which has just been ‘all the security patches’. This will have a very similar name, e.g. “January, 2017 Security Only Quality Update for Windows 7” again having a separate update for each OS. These are not cumulative, and each needs to be installed seperately. These updates are only required if you’re not doing the monthly rollup for some reason (e.g. one of the updates breaks something in the rollup).

Those both included Internet Explorer, but as of February 2017 that will be it’s own separate set of updates. The IE update set will be cumulative – including all older updates in each new package.

That separate IE set of patches is the Cumulative Security Update for Internet Explorer will be cumulative like the Rollups, where you only need the latest one.

These are big changes and it’s worth getting your head around it all – the end goal is to have only monthly updates for anything older than Windows 10.

There may be future changes as to how this model works, so make sure you keep up to date with what Microsoft is doing in this space.

Azure Active Directory – Assigning Groups to Applications in PowerShell

Azure Active Directory Applications have been around for a while, but it’s I’ve found it hard to find good information on them beyond the biggest benefit of Marketplace Apps.

Along with my Azure AD B2B journey (still in preview at time of writing), the option of pushing out something like a SharePoint Online site as an app is one of the jigsaw pieces required to make the whole B2B process work – as a version of the apps page is displayed as the default link to anyone who accepts an Azure AD B2B invite and logs in for the first time.

MyApps – an externally invited user will only see the apps they have access to (by default, none)

I’m trying to gloss over details here, as there’s a lot of steps with different parts of the Microsoft world to get a process automated end to end for inviting external users to a SharePoint Online site – but the last step of assigning a user or group to an application has no documentation I could find, that showed how to achieve this via PowerShell.

All I want to do here, is create an Application in Azure AD, then assign a group to it. Members of the group will then see the application on MyApps.

Two different modules are required – Azure Active Directory V2 PowerShell module and Azure Resource Manager.

What we can do with these two modules is first create the application with the New-AzureRMADApplication command:

New-AzureRmADApplication -DisplayName "SharePoint Online Site A" -HomePage "" -IdentifierUris ""

Easy, now you have an application that will point to the URL entered in Azure Active Directory. Assigning a group to it is a bit trickier…

First, a few values need to be obtained:

$app = Get-AzureRmADApplication | where displayname -eq "SharePoint Online Site A"
$appid = $app.ApplicationId
$fullgroup = get-msolgroup -all | where displayname -eq "SharePoint Online Site A"

This is getting the two objects as variables – the Application itself, and the group that you want to add onto it.

Then a new Service Principal needs to be created based on the Application, as this is required when adding the group onto the application:

New-AzureADServicePrincipal -AppId $appid

Another variable is needed, which is the new Service Principal we just created:

$servicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$appId'"

Finally, we can assign the group to the application:

New-AzureADGroupAppRoleAssignment -objectid $fullgroup.objectid -principalid $fullgroup.objectid -resourceid $serviceprincipal.objectid -id ([Guid]::Empty)

You can check that this has applied by the Azure Active Directory portal too, by going to your Active Directory section, choosing ‘Applications’ and finding your app, then go into ‘users and groups’ and find the group. You should see a ‘yes’ in the assigned field.

If there’s any interest in documenting the entire SharePoint Online and Azure AD B2B invite process and script, let me know. It’s a great way of sharing data with clients via a portal.

Ancient Technology

My father handed me a crate the other day as part of a cleanup, to see if I wanted anything he’d found.

I didn’t think the bits would be as old as they were, and thought it’d be great to share what they were. I’ve used a PS4 controller for reference as I couldn’t find a banana.

First up is a very long ISA card, from an XT PC. This was purely an IDE controller – giving you the ability to add on a floppy drive or hard drive to your PC. The board itself actually says the year of manufacture – 1985.

1985 XT PC ISA Controller Card

There’s two cables, each allowing 2 devices. This goes back to the primary and secondary days of drives, where you needed to set the jumpers correctly on the back for them to be detected properly. I measured it, and it’s 35cm long!

Next up is a 3 button serial mouse. On the back is a switch to toggle between 2 and 3 buttons, which was to work around incompatibilities between the two configurations, as mentioned on the Wikiepedia article. Of course this is an old ball mouse… and someone opened up a Microsoft Serial Mouse if you want to see the ball and wheel components.

3 button Serial PC Mouse

This one’s a bit harder to date – it’s probably XT PC era too with the 3 button switch, and long before the PS/2 mouse came out in the late 1980’s.

Here we have some hard drives. They’re 3.5″ but much chunkier than the ones of today, about double the thickness. I believe they’re both 20MB – yes megabyes! At the time of this, 360KB 5 1/4 floppy disks were the norm – About the equivalent of 55 floppies could be stored on a 20MB HDD.

20MB IDE HDDs, XT PC era (198X)

The data connector on this fits the cables on the ISA card from earlier. I remember in my childhood having a 40MB HDD bought for $600AU in the early 1990s. Back in 1990 accordign to this US copy of InfoWorld, these 20MB HDDs would have cost US$699 as an addon when buying a PC.

Last up was something I was much less familiar with – a 5 1/4 inch HDD. I found a page selling the same model if you want to buy one for yourself. I couldn’t tell from looking at the unit, but based on all the links it seems to have a capacity of 42MB.

Mitsubishi 5 1/4″ HDD back (Centre)

Mitsubishi 5 1/4″ HDD front (Centre)

There is a date on this one, 1989. Because many computers had slots for 5 1/4 inch floppy drives, it made sense to have hard drives at the same size. They fell out of fashion , and the 3 1/2 inch size became the new standard, matching the 3 1/2 inch floppy disks and drives of the time. Again this one has the same connectors as the other hard drives I have. Also, those molex power connectors survived a very long time in the PC world!

Also on the back of this drive, notice the amount of switches you need to set correctly – 14 in total. I’d be surprised if anyone misses troubleshooting an incorrectly set HDD with that many combinations of options, and slow startup times.

That’s the lot – always fun to go back over the old technology and see what was normal.