Microsoft

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.

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 testuser@contoso.com
}

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'){
  $CheckUser++
  start-sleep -s 10
  $running = Enable-CsUser -Identity testuser -SipAddress testuser@contoso.com
}
}

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'){
  $CheckUser++
  start-sleep -s 10
  $running = Enable-CsUser -Identity testuser -SipAddress testuser@contoso.com
}else{
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.

Remove Microsoft Account or Work Account

If you’re using Office 365 and/or Azure, you may have run into this scenario. If you want detailed information about Microsoft Accounts vs Work or school accounts, read this comprehensive article.

For people who set up a Microsoft Account on a work email address, and then configured it for Office 365/Azure, you’d be used to seeing this screen every time you log in:

It’s necessary, but annoying when you’re signing in a lot. I’m not sure how long this has been around, but you can change the email address associated with your Microsoft account, and move it away from your work email address.

And you may notice, there’s that ‘Tired of seeing this?’ message. My brain blocked that out, so you can follow that link too 🙂

Atwork have a writeup on how to change the email address (the first link gives a 404 message, but you’re still in the right place to make the changes). I tested this on my own account, and within a few minutes I was no longer seeing the choice between Work or Personal when signing into Office 365/Azure services.

Combine that with ADFS or Azure AD Connect Pass-Through Authentication to make your Microsoft sign-ins a quicker process!

Microsoft StaffHub General Availability

Microsoft StaffHub has now globally been released (General Availability). StaffHub is a very simple web and smartphone app based scheduling system, primarily designed for shifts.

It lets admins set and modify member’s shifts, and gives simple day/week/month overviews. I quite like this simplistic approach, sometimes these solutions can be a bit overwhelming when it’s linked to several other Office 365 features that you haven’t used yet.

Microsoft StaffHub

I was honestly up and running with this in 5 minutes, including the tutorial. I’ve invited other staff members as part of adding them, and both web and smartphone views are clean and easy to read. The product itself doesn’t really do anything else – there’s chat options for the app, and file sharing, but it’s perfect for staff that don’t do much (or any) of their work on computers; or just staff that want to be able to see what shift they’re on quickly.

One point of confusion I noticed, was the invite it sends out to staff you invite only wants them to use the smartphone app, and that link won’t work from a browser. They’ll need to manually go to https://staffhub.office.com for the browser experience.

Microsoft have a great starter page along with video showing how it works. There doesn’t seem to be any integration with other systems – It’d be nice to be able to send shifts as calendar appointments and maybe we’ll see that in the future.

It’s part of the Office 365 suite, so if you already have a license you should be able to go to http://staffhub.ms/ and start playing.

Searching Multi-Valued Properties in PowerShell

I’ve been playing with Office 365 commands in PowerShell and had to do a search. Sounds simple, but depending on what you’re searching, some scenarios are less basic than others.

Everything in PowerShell is an object. Usually, a property in PowerShell has a single value, such as:

UserPrincipalName: afowler@contoso.com

which is one of the results from Get-MsolUser. However, another property is different:

AlternateEmailAddresses: {microsoft@contoso2.com}

Visually, the difference is just the {} braces that contain the value. These braces mean that the property has been built to contain multiple items, rather than a single item.

If I wanted to see a list of all UserPrincipalNames, I’d use this command:

Get-MsolUser -all | select UserPrincipalName

A nice list of UPNs would display on the screen. However, that same command against AlternateEmailAddress, all that comes up is a bunch of blank lines.

To make this work, we need to select the value and show all the expressions of each value:

get-msoluser -all | select @{Name=“AlternateEmailAddresses”;Expression={$_.AlternateEmailAddresses}}

To then search on those values with the ‘where’ command, you’d have to write it like this:

get-msoluser -all | select @{Name=“AlternateEmailAddresses”;Expression={$_.AlternateEmailAddresses}} | where {$_.AlternateEmailAddresses -like "*contoso*"}

The good news is, for a where search by itself, you can forget all that and go back to basics:

Get-MsolUser -all | Where AlternateEmailAddresses -like "*contoso*"

Because of this requirement on the Select command, it lead me down the wrong path for a bit. There’s other reading on how to list all the values of a multi-valued property

If you’re still lost and want to get started with PowerShell, try checking out this PowerShell Basics video