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
Connect-Msol
#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…

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" }
Else
{ 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

PowerShell 3 for Windows 7, Server 2008 R2, Server 2008 and Vista

Following up on my post of a few years ago on PowerShell 2 being available, Microsoft have now released the bits needed to give you PowerShell 3 on Windows 7, Server 2008 R2, Vista and Server 2008. Sadly no PowerShell 3 lovelyness for XP, but then who really cares. I can barely remember how to use XP now I’m using Windows 8…

So without further a-do here is the download link for PowerShell 3:
http://www.microsoft.com/en-us/download/details.aspx?id=34595

PowerShell 2 for XP, Server 2003, Vista and Server 2008 is available!

Microsoft are calling it the “Windows Management Framework” but in reality this is PowerShell 2.0 and it’s now available for download: http://support.microsoft.com/kb/968929

If you install over the top of PowerShell 1.0 on XP the startmenu link will go but you’ll be left with the documentation links. So it might be better to uninstall 1 then install 2. Not sure yet.
Part of this is the new ISE (Integrated Scripting Environment) too and it’s wonderfully good. Just go start, run, then type: powershell_ise

Note: it supports only XP SP3, Server 2003 SP2, Vista SP1+, and Server 2008 SP2.
Windows 7 and Server 2008 R2 have PowerShell 2 built-in of course.

Update on 7th Sep 2012: If you want PowerShell 3 click here

Exchange 2007 SP2 has been released

And so to the insignificant clash of tiny mouse sized symbols Exchange 2007 Service Pack 2 has finally been released: http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID;=4c4bd2a3-5e50-42b0-8bbb-2cc9afe3216a

According to a little very sketchy investigation I’ve done there’s a schema change and support for PowerShell 2 – in fact they are recommending it! According to this blog post (link) PowerShell 2 is already in Windows 7 and Server 2008 R2, and sure enough if you run powershell and type $psversiontable and that proves it 🙂
[yes i’ve been running Win7 Enterprise x64 RTM for the last 2 weeks, hehe]