Category Archives: Powershell

Error Code 1 – Using Invoke-MbamClientDeployment.ps1 in SCCM OSD (and remove postpone from mbamclientui when selecting pin)

I know I’m not alone in the misery of getting this less-than-perfect script to work during OSD and after a good couple of weeks of on-off testing I can finally say I got my desired result and it most certainly deserved a post. Please note, you may need to click on the pictures to see them fully.

GOAL:

Fully encrypt disk with XTSAES256 encryption and escrow keys in MBAM/SCCM database during SCCM OSD task sequence. I also need a PIN to be requested automatically at first logon, with NO POSTPONE available to the user.

I’m not going to detail the ins and outs of what I tried because this post will be far longer than necessary so I’ll concentrate on the steps that finally got it working for me. Don’t get me wrong, this is a buggy script that should really have been updated by Microsoft by now.  Error code 1 is an extremely common problem and can result for any number of reasons.
I originally published similar steps at the  a few years ago and they were the steps I needed at the time to get it working  in that particular environment. The following steps are updated and can be used with ConfigMgr. They will probably work with the old MBAM too as the port to SCCM really is a lift and shift.

High Level:

  1. Pre-provision bitlocker (if required)
  2. Install The MBAM Client
  3. Stop the MBAM Service
  4. EncryptionMethodWithXtsOs
  5. Remove Startup Delay
  6. Start MBAM Service
  7. Force User To Select A New Pin On First Logon
  8. Run Invoke-MBAMClientDeployment Script
  9. GPO Settings

1. Pre-provision bitlocker (if required)

Set this early on just after formatting the disk. If you want full disk encryption, you can leave this step out completely. Be aware , full disk encryption will add the best part of 30m on a build with a 240GB laptop SSD.

2. Install the MBAM Client.

Just because ConfigMgr is now the vessel through which MBAM/Bitlocker is deployed, nothing has really changed. The installation binaries are simply copied down locally when the ConfigMgr client is installed. So not built into the client as you might have expected. Create an MBAM section (because it is still being referred to as such) at the end of your task sequence and as a first step create a RUN COMMAND LINE action:

Command line:

MSIExec.exe /i MBAMClient.msi /qn

Start in:

C:\Windows\CCM

3. Stop the MBAM Service

Another RUN COMMAND LINE action:

net stop mbamagent

4.EncryptionMethodWithXtsOs

Set EncryptionMethod – technically this should be achieved by adding the method as a parameter in the InvokeMBAMClientDeployment.ps1 Script. However I have found this to be somewhat inconsistent depending on the model of computer you’re trying to deploy. Instead, set it here and add UNSPECIFIED as the script parameter. This will set up the disk for XTS-AES256 (see here for other values). Note, use this instead of EncryptionMethod setting for any Win10 OS 1511 and newer (which should be all by now).

Another RUN COMMAND LINE action:

REG ADD HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\FVE /v EncryptionMethodWithXtsOs /t REG_DWORD /d 7 /f

5.Remove Startup Delay

We want to minimise startup delay for the MBAM client service- let’s change it to 1 minute.  Depending on the size of your environment you may wish to extend this. See here for official info on this setting. Without this set, there will be a random delay of up to 90m. There are other settings in this link you may wish to add for the purpose of testing in a lab environment.

Another RUN COMMAND LINE action:

REG ADD HKLM\Software\Microsoft\MBAM /v NoStartupDelay /t REG_DWORD /d 1 /f

6.Start the MBAM Service

Another RUN COMMAND LINE action:

net start mbamagent

7.Force User To Select New PIN at First Logon

By default, the PIN screen will appear in the first 90m after logging in. This can be changed via GPO (see further down). In my experience, admins often want this to happen when users log on. If this is you then you’ll need to update the default user profile.  This will force users to enter a PIN right away.

Note, for this to fire, you must have a fully-active ConfigMgr client and (if you want to avoid the postpone option) the machine must be in receipt of the policy below (9).

Another RUN COMMAND LINE action:

powershell.exe -ExecutionPolicy Bypass -command "reg load HKLM\DefaultUser C:\Users\Default\NTUSER.DAT; new-item -path HKLM:\Defaultuser\Software\Microsoft\Windows\CurrentVersion\RunOnce; New-ItemProperty -force -Path 'HKLM:\Defaultuser\Software\Microsoft\Windows\CurrentVersion\RunOnce' -Name PromptForPIN -Value '""C:\Program Files\Microsoft\MDOP MBAM\MBAMClientUI.exe"""' -Type String; [gc]::collect(); Start-Sleep -Seconds 2; reg unload HKLM\DefaultUser"

8.Run InvokeMBAMClientDeployment.ps1 Script

This is where much of the magic happens, when you can get it to work properly.

There are a couple of steps you need to do for this. First, download the script from the MSFT site. Second, create a ConfigMgr (legacy) package with no program containing the script above, and distribute contents.

This time, add a RUN POWERSHELL SCRIPT action:

NAME: Run Invoke-MbamClientDeployment Script

PACKAGE: <Script Package>

SCRIPTNAME: InvokeMBAMClientDeployment.ps1

PARAMETERS:

-RecoveryServiceEndpoint "https://<SiteServerFQDN>/SMS_MP_MBAM/CoreService.svc" -EncryptionMethod UNSPECIFIED -EncryptAndEscrowDataVolume -IgnoreEscrowOwnerAuthFailure -IgnoreReportStatusFailure -WaitForEncryptionToComplete

PS EXECUTION POLICY : Bypass

Finally add an extra step to restart the computer.

The above will get you as far as MBAMClientUI.exe requesting you either postpone or enter a PIN. But we don’t want the postpone option do we?

To go straight to the enter PIN screen, you’ll need to EITHER configure the GPOs below OR set a compliance policy in MEMCM:

Note, non-compliance grace period needs to be set to 0 days. Obviously, you must make sure your targeted machines are in a collection with the Bitlocker policy applied.

Create a GPO, add the settings below and make sure it applies to your machine. One other issue I noticed – at one point my ConfigMgr client wasn’t fully up and running when I logged in and when this was the case, the MBAMClientUI didn’t fire. Be sure you have a fully up and running client before logging in. It’s worth giving it a little while to download policies, etc.

9.GPO SETTINGS

As a minimum, set the GPO below. There are others you may need but this is the bare minimum.
Windows Components/MDOP MBAM (BitLocker Management)/Operating System Drive
Policy Setting Comment
Encryption Policy Enforcement Settings Enabled
Configure the number of noncompliance grace period days for operating system drives: 0

That’s it. One would assume much of this legwork should automatically be taken care of by the script itself but unfortunately that doesn’t appear to be the case. Don’t forget, you will also need to make sure that no MBAM policies are in place when the script runs. This isn’t a problem with SCCM as GPOs will be suppressed but if you’re using native MDT this can be an issue.

Simon

OSD Scripting Hacks Part 4 – Renaming NICs

In a new series of short posts I’m going to show how to get around some frustrations I have had with the lack of GPO support for some common requirements plus a few other issues I have come across which have crept up recently.

More for a bit of fun really but this was another serious request I have had where a machine contained several adaptors, they should all be sequentially named to specification, in this case NIC1, NIC2, NIC3 ,etc.

Here’s the script. It renames the adaptor numerically and outputs to a logfile:

# Rename NICs
$number=0
ForEach($nic in (Get-NetAdapter -Name *)) {
$number += 1
Get-NetAdapter -Name $nic.Name | Rename-NetAdapter -NewName NIC$number - PassThru | Out-File %WinDir%\Temp\NicName.log -Append
 }

For MDT users I recommend using a commandline action as follows:

powershell.exe -ExecutionPolicy Bypass -command "$number=0; ForEach($nic in (Get-NetAdapter -Name *)) { $number+=1; Get-NetAdapter -Name $nic.Name | Rename-NetAdapter -NewName NIC$number -PassThru | Out-File %WinDir%\Temp\NicName.log -Append }"

That concludes this series for now until such time as another request comes my way…

 

OSD Scripting Hacks Part 3 – Disable NETBIOS in Powershell

In a new series of short posts I’m going to show how to get around some frustrations I have had with the lack of GPO support for some common requirements plus a few other issues I have come across which have crept up recently.

Another requirement that came up in my recent project was to disable the NETBIOS over TCP/IP setting function under the network adaptor settings | IPv4 properties | Advanced. The issue here is that there are multiple GUIDs present in the registry that must be changed and these can’t be easily predicted. Fortunately Powershell is kind to us and allows the use of a wildcard (*) to just hit them all. This is achieved with the following script:

 # Disables NETBIOS over TCP/IP
set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\NetBT\Parameters\Interfaces\tcpip* -Name NetbiosOptions -Value 2

For MDT users, I recommend using a commandline action as follows:

powershell.exe -ExecutionPolicy Bypass -command "set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\services\NetBT\Parameters\Interfaces\tcpip*' -Name NetbiosOptions -Value 2"

Next, renaming NICs!

OSD Scripting Hacks Part 2 – Performance Settings

In a new series of short posts I’m going to show how to get around some frustrations I have had with the lack of GPO support for some common requirements plus a few other issues I have come across which have crept up recently.

In part 2, I will show you how to change the performance settings via a script which can be run from a task sequence step. Like the file extensions in Part 1, this was another area that (at the time of writing) seems frustratingly missing from group policy. I was creating an MDT task sequence recently to build some servers and one of the requirements was that the Visual Effects setting was specifically set for ‘Best Performance’ as opposed to Let Windows choose…

Anyway, the script:

# VisualFX - Best Performance
$RegKey ="HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects"
Set-ItemProperty -Path $RegKey -Name VisualFXSetting -Type DWORD -Value 2

For MDT, you may wish to run this as a commandline as follows:

powershell.exe -ExecutionPolicy Bypass -command "set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects' -Name VisualFXSetting -Type DWORD -Value 2"

In the above I set the value to 2 for best performance. Other values can be:
0 – Let Windows choose what’s best for my computer settings.
1 – for Adjust for best appearance settings.
2 – for Adjust for best Performance settings.
3 – for Custom settings.

OSD Scripting Hack Part 1 – Enable file extensions for all users

In a new series of short posts I’m going to show how to get around some frustrations I have had with the lack of GPO support for some common requirements plus a few other issues I have come across which have crept up recently.

First in the series is a build fix for file extensions. By default, these aren’t enabled and at the time of writing there isn’t a GPO that can be applied that applies them for users when they log on so they have to be enabled manually. Personally I find it frustrating that I can’t see what kind of file something is and it is usually the first thing I change when  I log into a new computer. Anyway, among others, this became a requirement for a recent project I was on and after a bit of playing around and further research I came up with the following Powershell script:

reg load HKLM\DefaultUser C:\Users\Default\NTUSER.DAT
 $path = "HKLM:\Defaultuser\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
 New-ItemProperty -Path $path -Name HideFileExt -Value "0" -Type DWord
 reg unload HKLM\DefaultUser

This should be run as a task sequence step but depending on your deployment tool of choice, Powershell commands can occasionally be a little fussy. If you are using MDT, you might find the following works better if set up as a commandline:

Powershell.exe -ExecutionPolicy Bypass -command "reg load HKLM\DefaultUser C:\Users\Default\NTUSER.DAT; New-ItemProperty -Path 'HKLM:\Defaultuser\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name HideFileExt -Value 0 -Type DWord; reg unload HKLM\DefaultUser"

The above should also work fine for SCCM although SCCM isn’t as picky as stand-alone MDT so either might work there.

Next time, Performance settings.

Can’t run PowershellInstance.invoke() from C# (but code is fine)

I recently wrote a GUI to duplicate MDT database roles based on the excellent Powershell commandlets written by Michael Niehaus:
http://blogs.technet.com/b/mniehaus/archive/2009/05/15/manipulating-the-microsoft-deployment-toolkit-database-using-powershell.aspx.
Although the Powershell code worked fine when executed directly in a Powershell window, I was seeing mixed results when executing the same code in C# through PowershellInstance.invoke(). Specifically, when I compiled the executable I was able to run the powershell code through the utility without issue, whereas it failed for my colleagues for some reason.

THE FIX

It seems that what I needed to do was ensure that the code was compiled specifically for the platform I was running it on as opposed to ‘any CPU’. In my case this was for x64. You can set this under the project properties in Visual Studio:

Platformx64

However, after making this change, I found I was getting compilation errors along the lines of:
An attempt was made to load an assembly with an incorrect format: [path to exe]

To fix this, I needed to change Generate serialization assemply to Off and everything compiled as expected. More on this here.

New-CMBoundary IPSubnet Doesn’t work

CM2012 introduces to us the ability to easily script many labour-intensive tasks. I was recently adding numerous boundaries to a ConfigMgr implementation for a client so decided the best approach was to automate this procedure.  I fired up the Powershell session from within ConfigMgr and checked the syntax for New-CMBoundary. Now, I had a spreadsheet with a bunch of IP subnets in CIDR notation so it made sense to use this for my script. Running Get-Help New-CMBoundary I got the following:

Example 1: Create a new IP Subnet site boundary
PS C:\>New-CMBoundary -DisplayName "IPSubNetBoundary01" -BoundaryType IPSubNet -Value "172.16.50.0/24"
BoundaryFlags: 0
BoundaryID: 6338009
BoundaryType: 0
CreatedBy: Contoso\PFuller
CreatedOn 6/10/2012 1:17:42 PM
DefaultSiteCode:
DisplayName: IPSubNetBoundary01
GroupCount: 0
ModifiedBy:
ModifiedOn:
SiteSystems:
Value: 172.16.50.0/24

Looks straightforward enough but no. This simply doesn’t work as stated. The problem seems to be that it doesn’t understand the ‘/24’ part (in this example). Instead, what you first need to do is to find the subnet ID which is associated with your address. If you’re unsure what this is then I’d recommend you use something like http://www.subnet-calculator.com/cidr.php:

cidrcalc

 

 

In the example above we have a CIDR range of 10.13.160.0/23. You can see from the calculator that this produces a network ID of 10.13.160.0. Therefore the correct syntax for New-CMBoundary is as follows:
New-CMBoundary -DisplayName “IPSubNetBoundary01” -BoundaryType IPSubNet -Value “10.13.160.0”
All that said, I’d personally avoid IPSubnet boundaries completely. Instead, just go for a range, far simpler to understand. The CIDR calculator is again helpful for this and displays the range at the bottom.
Thankfully, the IPRange syntax is correct so you shouldn’t have any issues.