Change login screen language in MDT / SCCM (Server Core)

I came across an interesting (if very frustrating) issue recently when a client provided me with an updated version of Windows Server 2012 R2. Prior to being handed the new media, I was using my own copy of Server 2012 R2 which is Build 6.3.9600.16384. I set up my MDT build which had a task sequence for each version of Server 2012 R2, Standard, Standard Core, Datacenter and Datacenter Core.  Everything was fine and the UI language was configured correctly throughout.

I received the new media which was Build 6.3.9600.17415 and replaced my original copy of Server with this new version. All appeared to be fine until I tried to log in to the two Server Core versions where my password wasn’t being accepted. It transpires that these have some kind of bug / difference whereby the Input Locale doesn’t change to the configured language. In my case, I had an American (en-us) keyboard and I wanted to use an English (en-gb) keyboard. Weirdly, this was only the case for the core versions; the GUI versions were fine.

I spent a good deal of time scouring the internet for a fix to this and it appears quite a few people had the same issue, eg:
https://social.technet.microsoft.com/Forums/windowsserver/en-US/d82dd905-e346-4a94-87e6-a78d59f4941c/keyboard-layout-wrong-on-logon-screen-but-fine-on-desktop?forum=windowsserver2008r2general
or
http://windowsitpro.com/systems-management/how-do-i-configure-default-keyboard-layout-during-login

This one was also interesting but the application of the fix wasn’t explained clearly and I gave up on it.

Mostly, the ‘fix’ was to change the HKEY_CURRENT_USER\Keyboard Layout\Preload setting to the proper value and this does seem to work if you log on and change this manually in the registry. However I could not get this setting to stick when I applied it through any scripting mechanism.

I eventually found a solution though through group policy which I applied during the build. The steps below are for MDT but the same can easily be applied for SCCM.

Create a new GPO and browse to Computer Configuration\Policies\Admin Templates\System\Locale Services
Change Disallow copying of user input methods to the system account for sign in to Enabled.
Create a backup of the policy and copy it to your deployment share. Rename it from {GUID} to LogonKB. I created a custom directory to store this in called Custom2012R2. Under this I had a directory called GPOBackup which contain any GPOs I need to apply.
Download a copy of lgpo.exe and stick it in your tools\%architecture% directory (in practice you want the x64 version)
Create a TS step just before the Tattoo step called Copy GPOs Locally as below
Command line: xcopy “%DEPLOYROOT%\Custom_2012R2\GPOBackup” C:\Windows\Temp /e /i

6. Next, create another step to apply the GPO, directly after the copy step and call this Apply GPO logon keyboard.
Command line:

“%DEPLOYROOT%\Tools\%ARCHITECTURE%\lgpo.exe” /g “C:\Windows\Temp\LogonKB”

It is important these two steps are early in the task sequence as the ‘damage’ is already done if you apply them too late. What is actually happening is that the GPO you have applied is preventing the Input Locale from being copied over to the login screen keyboard locale. You can see this before and after by running up the systeminfo command from a command prompt. On a machine without the application of the GPO the Input Locale will show up as:

Input Locale: en-us;English (united States)

and this will get copied over to the login screen language during build time. The GPO prevents this from happening and keeps the setting at en-gb.

I hope this will save others many hours of frustration.

New OSD Task Sequence Not Displaying

Recently been testing an upgrade scenario from ConfigMgr 2012 SP2 to Current Branch 1702 and during the course of putting together the legacy environment I came across a strange issue I’d not seen before. Essentially it goes like this:

A new OSD task sequence is created (doesn’t matter whether it is MDT-infused or not) and is deployed to All Unknown Computers. In my case I was using boot media to reach the WinPE environment on my test VM but there were no task sequences displayed. Checking the smsts.log file in the WinPE environment, it suggests that no policies are found.

The first time this happened the task sequence eventually appeared after about an hour or so. The next day I created a new one and exactly the same thing happened, with just the old TS showing up. I then saw this thread and changed my new task sequence availability time back 1 day. Et voila, the task sequence appeared.

Hope this helps anyone else scratching their head…

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.

Sign PDF Documents with the Surface Pen

In my occasional series on Microsoft Surface-related posts, I thought I’d just do a quick one on signing a document. This seems like the type of thing you’d want to use the Surface pen for, right? Well it’s probably the single most useful thing I would want to use it for anyway. The trouble is, by default at least, when you open a PDF it opens up in Edge and you are unable to use the pen to sign with…

You’ll also probably find it doesn’t seem to work in Adobe Reader and many other PDF readers. However not to worry – there is a built in reader app that can help with this very task! I feel a little stupid for only just realising this but try opening the app in Drawboard PDF and you can make adjustments with your pen to your heart’s content – and then save them. Great.

You’re probably thinking I can’t believe he only just found that out and frankly, after owning my Surface for 10 months I’m kind of thinking the same. I can only assume that I’m not the only one to realise this late in the day and hopefully I can help others see the light.

WSUS / SUP : System.Net.WebException: The request failed with HTTP status 401: unauthorized.

I noticed recently that after an extended period of being switched off, the Software Update Point in SCCM lab looked extremely poorly. I’m not sure why this was or if it had anything to do with being switched off for several days but in any case here is the scenario:

WSUS lives on a separate server to my site server and SQL is on another separate box (I know, better to install it on the same box as site server but I find few customers these days that’ll let me do this so I keep it this way to replicate their environments as far as possible). Anyway I digress; the setup is as follows:

Comms: HTTPS / SSL throughout  for SCCM and for WSUS.
Version: Current Branch 1606
OS: Server 2012 R2  (WSUS 6.2, commonly referred to as WSUS 4.0)

After noticing some errors in my component status messages with regard to WSUS, I checked the WSUSCtrl.log and saw the following message appearing every minute or so:

System.Net.WebException: The request failed with HTTP status 401: Unauthorized.~~ at Microsoft.UpdateServices.Administration.AdminProxy.CreateUpdateServer(Object[] args)~~ at Microsoft.UpdateServices.Administration.AdminProxy.GetUpdateServer()~~ at Microsoft.SystemsManagementServer.WSUS.WSUSServer.ConnectToWSUSServer(String ServerName, Boolean UseSSL, Int32 PortNumber)
Failures reported during periodic health check by the WSUS Server UT1.BC.LOCAL. Will retry check in 1 minutes

Furthermore, if I ran WSUSUtil checkhealth on the SUP, my Application Log read as follows:

The Reporting Web Service is not working.
 The API Remoting Web Service is not working.
 The Server Synchronization Web Service is not working.
 The Client Web Service is not working.
 The SimpleAuth Web Service is not working.
 The DSS Authentication Web Service is not working.
 On 13/10/2016 19:56:06, component SMS_WSUS_CONTROL_MANAGER on computer UT1.TEST.LOCAL reported: WSUS Control Manager failed to configure proxy settings on WSUS Server "UT1.TEST.LOCAL".

Possible cause: WSUS Server version 3.0 SP2 or above is not installed or cannot be contacted.
 Solution: Verify that the WSUS Server version 3.0 SP2 or greater is installed. Verify that the IIS ports configured in the site are same as those configured on the WSUS IIS website.You can receive failure because proxy is set but proxy name is not specified or proxy server port is invalid.

Not good. Fortunately the fix was straightforward:

I ran c:\Program Files\Update Services\Tools\wsusutil.exe configuressl ut1.test.local
and then I saw URL: https://ut1.test.local:8531 appear on the screen.
Then restarted the IIS services (IISAdmin, WWW) and all sprang to life. An IISReset would probably have done the same thing. After this the log should start to look like that below.

wsuslog

(Open image in a new tab to see more clearly)

Assuming you are configured for SSL and for some reason you see something like URL: http://ut1.test.local:8530 instead, then most likely the SSL settings for WSUS are probably incorrect. Ensure you have the settings below in place in IIS:

1. WSUS Administration. SSL Settings should be unchecked / ignore.
2. ApiRemoting30. SSL settings should be checked / ignore.
3. aspnet_client. SSL settings should be unchecked / ignore.
4. ClientWebService. SSL settings should be checked /ignore
5. Content. SSL settings should be unchecked / ignore.
6. DSSAuthWebService. SSL settings should be checked/ ignore.
7. Inventory. SSL settings should be unchecked / ignore.
8. ReportingWebService. SSL settings should be unchecked / ignore.
9. SelfUpdate. SSL settings should be unchecked / ignore.
10. ServerSyncWebService. SSL settings should be checked / ignore.
11. SimpleAuthWebService. SSL settings should be checked / ignore.

Securing Web Services

One of the main criticisms of using web services is that they’re inherently insecure. By default anyone can access them and if they have functions to actually change anything then one must proceed with caution.

My current client was somewhat skeptical about their introduction and the only way I could bring them round to the wonderful gifts that they offer was to promise that we’d investigate a secure way to present them. There was some trial and error but I think we came up with a pretty good solution which I shall share here.

Why use web services at all?

There are an awful lot of reasons so I’ll keep it to why I like to use them. They’re a cheap and cheerful way to provide functionality by proxy.  They can be used to off-load many tasks which, if you don’t have the budget for something like the wonderful System Center Orchestrator product, can make a great shoe-in. OK a little more explanation…

From a deployment perspective they can provide a mechanism to access Active Directory, MDT and SCCM without a client OS necessarily being part of AD. For example, they could be called from a WinPE session to update a database or query/update an OU. They’re relatively easy to write if you possess basic programming skills but if not, then I fully recommend you check out Maik Koster’s toolset here.  Installation instructions are provided but do fall a little short on security, so let me crack on.

Securing the Web Services

First of all, if you run a PKI infrastructure, let me recommend you you change the URL to run under HTTPS. I am not going into detail in this respect here as there are plenty of how-to’s on this topic elsewhere on the web. Suffice to say it’s a no-brainer if you’re truly concerned about security, particularly if there are any services which need to pass confidential information such as passwords.

Next, ensure you have read Maik’s security blog for his web services. They’re basic but a good start. Now to secure it properly:

Securing the website via pass-through authentication

Follow these steps to lock down page to an AD group. I won’t go into detail on  clicky-clicky, I assume if you have come this far you’ll know this stuff from within IIS and from the screen shots provided. If enough people tell me otherwise, I’ll review this though.

  1. Before changing anything, this is the expected configuration:

2. Install url authorisation feature and windows authentication features from server manager or Powershell.

3. After installation, change authentication model as follows (apologies, image is a little blurry, I’ll try to update in due course).

4. Update Authorisation rules. Note that All Users verbs have been changed to POST. This prevents the web page appearing at all without a login prompt (ie the initial GET action is prevented from running) for all users other than those in that are members of the specified AD group.

 

5. Providers should remain at their defaults:

6. Update local Intranet sites. If the site isn’t trusted you may need to add this to local intranet sites to prevent a login box appearing.

 

You should now have full pass-through authentication for your web service, dependent on membership of the AD group of your choice.

Headaches of an SCCM Admin