Security Compliance Manager 4.0 – Download Resources

Back in July 2016 Microsoft released Security Compliance Manager 4.0 with support for Windows 10 and Server 2016. For some reason (at the moment) it seems to be hard to find so here are all the bits one might need to get started.

Solution Accelerator Article about SCM4:
Security Compliance Manager (SCM)

A TechNet blog announcing SCM4 availability:
Security Compliance Manager 4.0 now available for download!

An article about the security baselines available and links to download them:
Windows Security Baselines

Download: Windows 10, version 1607 and Windows Server 2016 security baseline
Download: Microsoft Security Compliance Manager 4.0

SQL is needed to install it (yay) and it comes with SQL Express 2008, but here’s a link to SQL 2016 Developer with SP1, which is free now:
MSDN article: Developer Guides for SQL Server
Download: SQL Server Management Studio 16.5.3
Download: SQL 2016 Developer with SP1 (2,590MB ISO)


Detecting the Administrative Context in PowerShell

I was writing a PowerShell script and it needed to know whether or not it was running in the administrative context. It’s a bit fiddly but here’s a one-liner that sets a Boolean variable for it:

$currentIdentity = New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())
$adminContext = $currentIdentity.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)

Run that and $adminContext will be True if the script is running as admin, and False if not.

Migrating all Office 365 students/users to the new Education Plus license

Microsoft recently renamed the free license that academic institutions on Office 365 get (if you have an active EA) to “Office 365 Education Plus for students”. At the same time they added in the Office Pro Plus license option to allow our students (and staff) to get Office 2013 (soon to be 2016).

Of course what they didn’t do was give us a simple way to migrate all our users away from the Student Advantage license onto the new licensing option.

So here’s some powershell to help with doing that:

#connect to 365 prompting for credentials
#collect the new license we wish to assign
$newLicense = (Get-MsolAccountSku | ? AccountSkuId -Like "*STANDARDWOFFPACK_IW_STUDENT").AccountSkuId
#find the old Student Advantage license
$oldLicense = (Get-MsolAccountSku | ? AccountSkuId -Like "*OFFICESUBSCRIPTION_STUDENT").AccountSkuId
#find all users with teh Student Advantage license
$needNewLic = (Get-MsolUser -All | Select UserPrincipalName,Licenses | %{if($_.Licenses.AccountSkuId -contains $oldLicense){$_}})
#loop through all users with old license and replace it with new one
$a = 0; foreach ($user in $needNewLic) {$a++; echo "$a of $($needNewLic.Count): $($user.UserPrincipalName)";
Set-MsolUserLicense -UserPrincipalName $user.UserPrincipalName -RemoveLicenses ($user.Licenses).AccountSkuId -AddLicenses $newLicense

Some caveats with the above code:
– it doesn’t work for users that already have some element of the new Education Plus license as the code assumes it has not been applied to your users yet
– it removes all existing licenses from the user and adds the new licenses in their place, so if you have extra licenses you want to keep then the code will need to modified to handle that
– as with all these things, I take no responsibility for the above code blatting your tenancy! it worked for me but please test it beforehand on your own ‘test’ tenacy – like we all have one of those…

Reporting Web Service for Office 365

There’s an interesting web service that could be used to pull reporting data from Office 365, assuming you can authenticate using your tenancy’s service admin. Here the URL for the service:

Microsoft provide a plug-in to Excel that uses this service and it can be used to pull mail protection statistics from your Office 365 tenancy:

File extension for Windows Language Packs

For some reason I have a mental block and can’t seem to remember this, but instead of using dism to install language packs on Windows 7 or above, like this…

dism /online /add-package /packagepath:<path to language pack .cab file>

…you can also simply rename the .cab language pack file to have the .mlc file extension and double-click it.

There’s yet another way too, and that’s to run the lpksetup.exe utility and point it at your .cab file I think. Haven’t tried that though as I think the .mlc method is easier.

Find a computer’s model using PowerShell

Interestingly this blog’s most popular post is one where I demonstrate how to find the serial number of a PC in a batch file so you can write a script that does different things for different computer models.

I pretty much don’t write batch code any more, instead using PowerShell as much as possible. So I thought I’d add a post explaining how to get your computer model in PowerShell as well. If you’ve any experience using PowerShell then you know this could be a very short post…

And the answer?

(Get-WmiObject -Class:Win32_ComputerSystem).Model

Extending that to a specific model to allow us to work on something specific we have many options to play with. My preferred method if I’m only dealing with one model would be to filter at the point of making the query, like so:

Get-WmiObject -Class:Win32_ComputerSystem -Filter:"Model LIKE '%H77ITX%'" -ComputerName:localhost

Notice I’ve filtered the query using the LIKE operator which in WMI queries requires the % character as the wildcard indicator, not *. I’ve also specified the ComputerName as localhost in the above commands. Usually WMI commands operate on network objects, even if you only have the one PC, and as a result can take a little time to respond. If you specify localhost it speeds up the command and ensures you only get a result from the PC where you run your script. Of course if you want to do this on remote PCs then you’d use the ComputerName to specify one or more remote PCs.

Anyway that command is only going to return the object if we are running the query on the right PC model. That’s not too useful on its own so we need to make it return something like True or False, then we can work inside an If statement perhaps. Actually we don’t need to bother! If handles a returned object as if that means True, and no returned object as meaning False.

For example:

If(Get-WmiObject -Class:Win32_ComputerSystem -Filter:"Model LIKE '%H78ITX%'" -ComputerName:localhost)
{ Write-Host "Found an H78ITX model" }
{ Write-Host "Model not found" }

OK so what do we do if we’ve got different models and we want to do different things on different models? Easy, go back to the first command, and use its output with the Switch statement.

$pcModel = (Get-WmiObject -Class:Win32_ComputerSystem).Model
Switch -wildcard ($pcModel)
    "*Latitude*" { # install special apps for a Dell }
    "*Elite*"    { # install special apps for an HP }
    default      { # install other things for everything else }

There’s plenty you can do with the switch statement, even using regex. There’s a good explanation of it here.

Of course you might want to do things for specific models, and also things for all models from a particular vendor. We can achieve that by being less specific with our initial command and just select different properties of the object from the variable like this.

$computerSystem = (Get-WmiObject -Class:Win32_ComputerSystem)
Write-Host $computerSystem.Manufacturer
Write-Host $computerSystem.Model

Hopefully that shows you how to get the model and manufacturer, then you can construct some logic around both.

Finally, something else to consider is that if you want to drill down using the serial number of a machine we need to make use of a different WMI object, namely Win32_BIOS, like this:

(Get-WmiObject -Class:Win32_BIOS).SerialNumber

Orca 5 for Windows 8

Now that Windows 8 has hit RTM there is a slightly newer version of Orca the MSI editing tool available. This one is version 5.0.9200.0, but when it’s installed, in the Programs and Features dialog it’ll show up as 8.59.25584.

To grab yourself a copy get the Windows SDK for Windows 8, install using the option to ‘download for installation on a separate computer‘, and make sure only ‘Windows Software Development Kit‘ is selected in the features list. You won’t be able to de-select the .NET 4 download.

After your download is complete you can either install Orca from the download directory, or collect up the files you need to keep a copy for use later on. The files you’ll need are listed here and are linked directly to Microsoft download location for ease of collection:

To install Orca just double-click on Orca-x86_en-us.msi and allow it to install. Job done!

Secrets of configuring DHCP policies for Lync handsets alongside other vendors

After battling with a non-Microsoft DHCP server to get it to configure multiple vendors of handset I figured out some very useful undocumented ‘habits’ of Lync handsets which might help someone else…

1. Lync handsets (e.g. the Polycom CX600) use TWO vendor IDs during their DHCP requests

The first vendor ID that is used during negotiation of an IP address is “CPE-OCPHONE”. This is the legacy ID that was used during the OCS 2007 days. Despite being legacy it is actually the first one that appears on the wire. Knowing this if you are struggling with getting Lync handsets to do vlan tagging you’ll hopefully realise that CPE-OCPHONE is the vendor ID you need to be using in option 60 for the vlan tagging configuration policy in DHCP.

The second vendor ID used is the modern Lync handset ID, namely “MS-UC-Client”. This is the one you use in option 60 when you provide the configuration to the phones.

2. If you have to use a non-Microsoft DHCP server (e.g. QIP) and you are in the middle of migrating from an IP-PBX (e.g. Alcatel) over to Lync but need to use the same voice vlans for both handset vendors, make life easy and use Vendor Class policies.

Using Vendor Class policies assigned to your voice networks means you can have multiple DHCP policies available on a single subnet! This way you can have non-voice clients that get a standard policy, and multiple vendor handsets that can get their own configuration sets. You could configure each individual IP address to have a single DHCP policy and statically assign phones to pre-configured IPs, but that doesn’t scale and it’s horrible to deal with.

Microsoft use vendor classes, and for good reason, so make sure you do your best to configure your non-Microsoft DHCP to use them too. Having to use multiple vendors’ phones is a pretty rare thing so you may not be able to get much support from anywhere.

3. Get hold of a simple network hub and use this with wireshark on a laptop to monitor DHCP traffic. It’s much easier than guessing what settings are (or are not) working.

4. If your network switches support LLDP-MED for goodness sake use it!

LLDP-MED is so much easier to handle and can be assigned to all ports on a switch instead of having to assign a specific voice vlan for a specific port. That and if you can use LLDP-MED you will not need to configure the phone to know what vlan to use for tagging because the LLDP protocol will do that for you.

5. When you’re stuck with a non-Microsoft DHCP server, read this article and this one from TechNet. The info you’ll need is there, they just haven’t really explained it too well.

I plan to do a deep dive into the stages a Lync handset goes through at boot-up and initial configuration in a later article, so if you find any of this of use you may wish to watch out for it.

Long startup and logon delays with a shared Windows 7 desktop

I’m writing with reference to a colleague’s blog post where he has found a very useful fix for a very annoying start up and log-on delay issue in Windows 7 SP1. Here’s his post, worth a read:

We were finding that computers in shared areas which had been logged on by many users (i.e. 50+ user profiles) were experiencing massive delays starting up and logging on. Until he found the fix the only solution was to leave the computers on all the time, or get them to start up really early in the morning.

One fix we tried was removing all the user profiles from the computers, and this only worked some of the time. Then my colleague found the right hot-fix and all of a sudden our startup and logon times dropped back to a few minutes. Big relief!

Here’s the relevant hotfix:

See the blog entry (linked above) for a detailed explanation.