Deploy simultaneous Windows to Go Devices with PowerShell

The code in this blog post is the tidied-up script which I used in my sessions at TechEd New Zealand and TechEd Australia, on deploying multiple Windows to Go devices in parallel.

Because I work quite a bit with Ironkey, and Ironkey Windows to Go devices have the nice feature of each having a unique serial number, I wanted to create a script which would produce fully customised deployments, but each deployment had to happen in parallel.

The script is designed for use with the Ironkey W300 device, which is a certified Windows to Go device which does not have an encrypted secure disk, unlike the W500.  The script was initially designed to cater for both W300 and W500 devices at the same time, but the process of unlocking the secure disk on the W500 in such a way as to keep the PowerShell script robust still needs some refining.  When I’m happy with it, I’ll update the script.

Of course, not everyone is going to be using Ironkey W300 devices.  Never fear, this script will work on pretty much any certified Windows to Go device.  If your device of choice doesn’t have a unique identifier which can be queried programatically, then you’ll need to strip out or disable the sections of the script which deal with extracting the serial number, setting the device type and creating a unique computer name.  If your device does, then all you’ll need to is modify the Get-W300Serial function to something appropriate for your hardware platform.

Alternatively, try using an Ironkey W300, because all the work has been done for you :-)

A few more points about the script functionality:

  1. The script incorporates Offline Domain Join, so it assumes that it is being run from a domain-joined workstation which has the Active Directory PowerShell module installed and available for import;
  2. The Offline Domain Join section also brings in the necessary GPO for DirectAccess.  If you don’t have DA in your environment, remove this bit;
  3. Because the W300 has no embedded cryptochip, the script enables BitLocker for drive encryption. However this method precludes the use of MBAM management, which is preferable.  To perform the encryption using MBAM, import the GPO as part of the Offline Domain Join.

The script has been a significant undertaking for me, as I had to learn a lot of PowerShell to bring it this far. Many thanks to David O’Brien for handling my questions at all hours of day and night.

I’m sure that there are parts of the script which could be handled with better logic or greater elegance, and I’m more than happy for feedback and suggestions.  One thing I’d really like to get working is a better way of monitoring the active PowerShell jobs than simply running Get-Job ever five minutes – if anyone has some good ideas for this, I’m all ears.

Download the script here: Create-WTGDevice

Create a new user in Azure AD with all licenses assigned

I’ve done some work with a customer recently where there was a requirement to provision new users in Azure Active Directory and assign all available licenses during the provisioning process (e.g. Office 365, Windows Intune).

It’s fairly straightforward to do with PowerShell.  The code below looks for the Azure subscription’s default domain (*.onmicrosoft.com) but you can obviously change that.  It’s also designed to provision one user at a time, prompting the administrator for the first and last name.  Remove the parameters and you can use the rest of the code to create users in bulk.

param (
   [Parameter(Mandatory=$False)]
   [ValidateNotNullOrEmpty()]
   [string]$userFirstName = $(Read-Host -Prompt 'Please Enter the First Name'),
 
   [Parameter(Mandatory=$False)]
   [ValidateNotNullOrEmpty()]
   [string]$userLastName = $(Read-Host -Prompt 'Please Enter the Last Name')
   )
 
$domainName = (Get-MsolDomain | Where-Object {$_.Name -like '*.onmicrosoft.com'}).Name
 
$userDisplayName = $userFirstName + ' ' + $userLastName
$userPrincipalName = $userFirstName + '.' + $userLastName + '@' + $domainName
$userPrincipalName = $userPrincipalName -replace ' ',''
 
$userTempPassword = 'P@ssw0rd'
$userUsageLocation = 'AU'
 
New-MsolUser -FirstName $userFirstName `
  -LastName $userLastName `
  -UserPrincipalName $userPrincipalName `
  -DisplayName $userDisplayName `
  -Password $userTempPassword `
  -UsageLocation $userUsageLocation | Out-Null
 
$licenses = Get-MsolAccountSku
 
foreach ($license in $licenses){
  Set-MsolUserLicense -UserPrincipalName $userPrincipalName -AddLicenses $license.AccountSkuId
}
 
Get-MsolUser -UserPrincipalName $userPrincipalName | Format-Table DisplayName,UserPrincipalName,Licenses -AutoSize

Session recordings from TechEd New Zealand 2014 are live!

The two sessions I delivered at TechEd New Zealand 2014 are now live and available on MSDN Channel 9:

Session: Deep Dive – Deploying and Managing Windows To Go

Session: Automated Compliance, Auditing and Remediation for the Enterprise Datacenter

As always, it was great to attend TechEd New Zealand – the event organisers and track owners did a great job as they always do, and the audiences are always engaged and ready to skewer an unsuspecting presenter with difficult questions :-)

Create an OS Deployment Task Sequence in Configuration Manager 2012 with PowerShell

This code is designed to create the framework for the Windows 8.1 OSD Task Sequence used in Chapter 11 of “Learn ConfigMgr 2012 in a Month of Lunches“.

The PowerShell cmdlet doesn’t perform the full amount of customisation which the reader does in the book’s lab environment, but it sets up the structure of the Task Sequence quite well, leaving very little post-script customisation to perform.

You can download the script directly from http://www.jamesbannanit.com/wp/files/manning/CMTaskSequence.zip.

# Define Configuration Manager variables
 
$CMSiteCode = 'P01'
$CMSiteServer = 'LAB-CM01.mol.sccmlab.net'
$CMNameSpace = "rootSMSsite_$CMSiteCode"
 
# 1.0 Get Deployment Objects
 
$BootImageID = (Get-CMBootImage -Name 'Custom Boot Image (x64)').PackageID
$OSImageID = (Get-CMOperatingSystemImage -Name 'Windows 8.1 x64 Enterprise Gold').PackageID
$ClientPackageID = (Get-CMPackage -Name 'Configuration Manager Client Package').PackageID
 
 
# 1.1 Create Task Sequence
 
New-CMTaskSequence -InstallOperatingSystemImageOption `
  -TaskSequenceName 'Deploy Windows 8.1 x64 Enterprise' `
  -BootImagePackageId $BootImageID `
  -OperatingSystemImagePackageId $OSImageID `
  -OperatingSystemImageIndex '1' `
  -ClientPackagePackageId $ClientPackageID `
  -JoinDomain DomainType `
  -DomainName 'mol.sccmlab.net' `
  -DomainAccount 'MOLCM_JD' `
  -DomainPassword 'P@ssw0rd' `
  -DomainOrganizationUnit 'LDAP://OU=Workstations,OU=SCCMR2Lab,DC=mol,DC=sccmlab,DC=net' `
  -PartitionAndFormatTarget $true `
  -LocalAdminPassword 'P@ssw0rd'

Create a Package in ConfigMgr 2012 R2 with PowerShell

This PowerShell code is designed to create a new Configuration Manager Package for Notepad++ as well as an installation Program for the new Package, as per Chapter 8 in “Learn ConfigMgr 2012 in a Month of Lunches“.

While the code is specific for the lab environment, it will work for any Program in Configuration Manager 2012 R2.

# Define Configuration Manager variables
 
$CMSiteCode = 'P01'
$CMSiteServer = 'LAB-CM01.mol.sccmlab.net'
$CMNameSpace = "rootSMSsite_$CMSiteCode"
$PackageName = 'Notepad++ 6.6.9'
 
# 1.0 Create new Package
 
New-CMPackage -Name $PackageName -Path '\lab-cm01SourcesSoftwareNotepad++6.5.2'
 
# 1.1 Create new Program
 
New-CMProgram -PackageName $PackageName 
  -StandardProgramName 'Install - Notepad++ 6.6.9' 
  -CommandLine 'npp.6.6.9.Installer.exe /S' 
  -RunType Hidden 
  -RunMode RunWithAdministrativeRights 
  -UserInteraction $false 
  -ProgramRunType WhetherOrNotUserIsLoggedOn 
  -DriveMode RenameWithUnc