Group Policy Preference Drive Maps closing

I’ve been dealing with an issue where users that leave Windows File Explorer windows open for extended periods find that they close now and then.

This seems to be a common problem with later versions of Windows (8.1, 10) and is caused by the Replace setting being used on the Group Policy Preference Drive Map.

The File Explorer windows close because Replace causes the drive map to be removed and re-added. You want to use Replace because you also want to use the option to Remove this item when it is no longer applied. And also because Update will not change a drive mapping that has been done manually by a user.

Part of the fix is to set the following group policy:

Computer Configuration/Administrative Templates/System/Group Policy/Configure Drive Maps preference extension policy processing
Allow processing across a slow network connection: Enabled
Process even if the Group Policy objects have not changed: Disabled
Background priority: Idle

The key setting being Process even if the Group Policy objects have not changed, set to Disabled.

This will stop File Explorer closing on every group policy refresh.

This is only part of the solution though. You might think that this would cause the drive maps preference to only be processed if a drive map preference within the GPO has changed. That would seem sensible, right? Well, no. If you have other stuff in the GPO, and any of that changes, the drive maps will still be processed (i.e. removed and re-added) even though they’ve not changed.

You can see this by looking in Event Viewer, in the Microsoft-Windows-GroupPolicy/Operational log, and information event 4016. The text will say:

Starting Group Policy Drive Maps Extension Processing. 

List of applicable Group Policy objects: (Changes were detected.)

Your GPO Name

So what I’ve now done is to move my GP Pref drive mappings into a dedicated GPO, which I’ll hardly ever have to change. Thus the group policy engine will hardly ever detect any changes, and thus users will hardly ever see their File Explorer windows closing.

Posted in Windows | Tagged , , , , , , , , , , , , , , , , , , | Leave a comment

Don’t display last username if C drive encrypted with BitLocker

I’m moving from encrypting laptops with a third party disk encryption product to BitLocker. The third party product uses a pre-boot username & password prompt, and only boots into Windows if the credentials are correct. Users then have to log on to Windows using the Active Directory credentials. The last username is remembered so they just type in their AD password and the desktop loads.

With BitLocker I’m using the Trusted Platform Module (TPM) in the laptops to tie the disk to the laptop, rather than giving users and extra set of credentials to remember. When they turn on, BitLocker checks the TPM and the laptop hardware for changes, and if all is normal Windows will boot and present the user with the logon screen. However, currently this means that a lost or stolen laptop will boot and display the name of the last user, which I don’t want. If the username isn’t displayed, there are now two pieces of information required to get past the Windows Logon screen.

I’ve achieved this using a Group Policy Preference, targeted with a WMI query. The GPPref sets the dontdisplaylastusername policy registry value if the C: drive is encrypted, or removes the value if the drive is not encrypted – i.e. during the transition phase, users with the old disk encryption won’t be forced to type in their AD username at the Windows logon screen, they’ll still be remembered from their previous logon.

The configuration is as follows:
Computer Configuration – Preferences – Windows Settings – Registry
General tab:

Action: Replace
Key Path: SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system
Value: dontdisplaylastusername
Value type: REG_DWORD
Value Data: 00000001

Common tab:

Remove this item when it is no longer applied: ticked
Item-level targeting: ticked

WMI query:

Query: select IsVolumeInitializedForProtection from Win32_EncryptableVolume where DriveLetter = 'C:' and IsVolumeInitializedForProtection = True
Namespace: root\CIMv2\Security\MicrosoftVolumeEncryption
Property: IsVolumeInitializedForProtection
Posted in Security, Storage, Windows | Tagged , , , , | Leave a comment

PowerShell: BitLocker Encryption Progress Bar

When enabling Bitlocker I want to know how far through the process of encrypting the drive it has got.

The script gets the encryption status from the manage-bde.exe command, parses it using a regular expression to get the percent complete, and goes into a loop updating a progress bar until the progress gets to 100%. Then the script quits.

Here’s the script:

function Get-BDEPercent{
    $BDEStatus = & manage-bde.exe -status c:
    $BDEStatus = $BDEStatus -join " "
    $Matches = $null
    $BDEStatus -match '\:\s([\d]{2,})\.\d\%' | Out-Null

$Loop = $true

    [int]$PercentComplete = Get-BDEPercent
    if($PercentComplete -ne 100){
        Write-Progress -Activity "Bitlocker Drive Encryption Status" -Status "Encrypting" -PercentComplete $PercentComplete
        Start-Sleep -Seconds 5
        Write-Progress -Activity "Bitlocker Drive Encryption Status" -Completed
        $Loop = $false
Posted in PowerShell, Storage, Windows | Tagged , , , , , , , , | Leave a comment

Storage Replica in Windows Server 2016

What is Storage Replica?

Block level synchronous or asynchronous, volume based data replication.

What does it do?

Replicates storage data from a disk attached to one instance of Windows Server to another disk attached to a different instance of Windows Server. Because it works at the block level, it doesn’t care about open files. It operates way down the driver stack:

It allows you to create stretch clusters (clusters that don’t have shared storage), or you can just use it to replicate data from one place to another.

How do you get it?

Storage Replica is new in Windows Server 2016. You need the Datacenter edition, but your Hyper-V/vSphere hosts are probably licensed for that anyway, right? It’a available in the “full” editions (i.e. with desktop or core) and also nano. It’s just a Windows Feature, so enable it with Server Manager or PowerShell:

Install-WindowsFeature -Name Storage-Replica

Synchronous vs Asynchronous

It’ll do both, you just need to pick the appropriate one. Firstly, is your network latency between the two servers greater than 5ms?  In which case you shouldn’t use Synchronous replication, the performance impact will be too great. If it’s 5ms or less, you can choose either, based on your needs.

Synchronous replicationstorage-replica-synchronous-replication

This works pretty much the same as oldskool SAN replication, kit like the EMC Clariion’s MirrorView feature does exactly the same thing (but for somewhat more than the cost of a Windows Server licence and some cheap server hardware – which is entertaining as certain models of Clariion actually ran Windows Server internally!). The key point with Synchronous replication is that the write is not confirmed on the source storage system until it has been written to the log disk on both the source and destination storage systems. This gives you peace of mind that your data is safe, at (usually) the expense of performance.

Asynchronous replication

See diagram for Synchronous replication, but confirm the write after step 2 – in other words, once the data has been written to the source log disk. The data is written to the destination log disk separately.

How Storage Replica changes your disk IO

On a volume that is being replicated via Storage Replica, all write activity happens to the Log disk. This data is then “destaged” to the Data disk, which thus only ever handles Because the Log disk is a log, the writes to this are sequential. Despite this, it’s recommended that you make the log disk an SSD – writes tend to slower than reads, and Windows (and applications, e.g. SQL Server, Exchange) can cache data for read operations in RAM. Write operations have to be securely written to disk, and so if the write speed of the log disk isn’t fast enough it’ll become the point of contention.

Is it safe to use now?

Probably – Microsoft has had customers running this technology on production systems since 2014. I plan on using it right now.

Want to know more?

Watch Ned Pyle’s excellent, informative, hilarious Ignite session video (where I stole the diagrams above from!). Hipsters beware…!

Posted in Storage, Uncategorized, Windows | Tagged , , , , , , , , | 1 Comment

Fix PowerShell WinRM remote connection errors

I’ve had two annoying PowerShell errors today, both for the same server:

Enter-PSSession : Connecting to remote server failed with the
following error message : The client cannot connect to the destination specified in
the request. Verify that the service on the destination is running and is accepting
requests. Consult the logs and documentation for the WS-Management service running
on the destination, most commonly IIS or WinRM. If the destination is the WinRM
service, run the following command on the destination to analyze and configure the
WinRM service: "winrm quickconfig". For more information, see the
about_Remote_Troubleshooting Help topic.

The standard “internet” response to this is to open an Administrator command prompt and run

winrm qc

(or winrm quickconfig). Or open an Administrator PowerShell prompt and run:


But these are quite annoying solutions if you know that it should be working, and indeed is working on all your other servers, because you’ve configured it via Group Policy! There’s no harm in running the commands anyway, but most likely they’ll just come back and say “already configured” or words to that effect.

So the fix (for me) for the above error was to check what IP addresses the listener was listening on using:

netstat -aon | find "5985"

where 5985 is the default port used by WinRM. You should see the system process (ID 4) listening on like this:


However on my problem server it was listening on This can be confirmed using:

netsh http show iplisten

and you’ll only see in the list.
On the problem server itself you’ll find that using:

Enter-PSSession -Computername localhost

works, whereas:

Enter-PSSession -Computername

does not.
localhost is the name for the loopback address whereas the fully qualified server name will give you the IP address of the server as seen from your network.
The fix for this is to delete the loopback address from the http listener, which then makes it listen on all valid addresses:

netsh http delete iplisten

Check what addresses it is now listening on (plus the port) by using:

winrm e winrm/config/listener

Problem solved. Or not, I then got this error:

Enter-PSSession : Connecting to remote server failed with
the following error message : The WinRM client sent a request to an HTTP server and 
got a response saying the requested HTTP URL was not available. This is usually
returned by a HTTP server that does not support the WS-Management protocol. For
more information, see the about_Remote_Troubleshooting Help topic.

Which it turns out can be caused by having IPv6 enabled on the server.
In the netstat output (see above) I also had some IPv6 addresses showing as listening on port 5985.
I don’t use IPv6 but it’s on by default in Windows and will auto-assign itself a link local address (starts with fe80:). So I disabled IPv6 and the error went away. There’s also a workaround using the hosts file if you don’t want to disable IPv6.

Posted in PowerShell, Windows | Tagged , , , , , , , , , , , | Leave a comment

Extract private key from Microsoft CA-issued certificate

I wanted to use my internal Active Directory Certificate Services server to create a certificate for a Synology NAS. The Synology needs the private key and the certificate to be in separate files.

I created the certificate by using the CA web interface https://my-ad-cs/certsrv and then choosing the following options:

  • Request a certificate
  • advanced certificate request
  • Create and submit a request to this CA
  • Template: Web Server (5 years) – note that this is a custom certificate template that I created that allows the private key to be exported. This enables the Mark keys as exportable option, which needs to be ticked.
  • Fill in the identifying information, and leave all other options as default

Once the certificate was created, I installed it. I then opened certmgr.msc, found the certificate (under Personal – Certificates).

Next, I right-clicked the certificate, and chose All tasks – Export. I chose to export the private key, and under the .pfx option ticked Include all certificates in the certification path if possible. I set a password and saved the file.

Then I downloaded the latest version of OpenSSL and extracted the zip file.

I copied the pfx file into the folder where I’d extracted OpenSSL to, and opened a command prompt in that folder. I used the following two command lines to extract the private key and certificate from the pfx file.

openssl pkcs12 -in extracted.pfx -nocerts -out privatekey.pem -nodes

openssl pkcs12 -in extracted.pfx -nokeys -out cert.pem

These two files were then uploaded to the Synology from Control Panel, Security, Certificate.

Once the certificate was installed, I selected it and clicked Edit, then ticked Set as default certificate. Finally, I clicked Configure and changed each of the services to use the new certificate. Upon clicking OK, the web services restarted and are now using my CA certificate.


Posted in Security, Storage | Tagged , , , , , , , , , , , , | Leave a comment

Windows Server 2016

Lots of good stuff. This video about Storage Replica from the guy who heads the Storage team up, Ned Pyle, is definitely worth watching. Informative and funny.

There’s also a free eBook: Introducing Windows Server 2016

Posted in Free training, Storage | Tagged , , , , , , | Leave a comment

Create a PFX file from separate private and public key certificate files

Whilst installing ADFS I needed to import my wildcard certificate. This proved fiddly as Microsoft need it to be in pfx format, and I only had separate private .key and public .crt files.

PFX is a Microsoft certificate format that combines the public and private keys into one file, but is different from the combined format used by (e.g.) OpenSSL. I found that I had to go through several steps to achieve this.

Your CRT public key file should start with the following (open it in notepad to check):


Convert the public key into a PVK file

If you open your public key file (e.g. in notepad) and it says


then you’ll need to convert it into a PVK file. a PVK file is a binary file, so it’ll look have lots of non-alphanumeric characters in it. To do the conversion, I used a utility called pvk written by Dr Stephen N Henson (thank you!). The command line for pvk.exe is:

pvk.exe -in rcmtech_private.key -out rcmtech_private.pvk -topvk

You’ll be prompted for a password, and you do need to specify one or the next step in the process will fail.

Download the Windows SDK

Now you need a utility called pvk2pfx. Annoyingly this only comes as part of the Windows SDK, so you need to download that first – you just need to tick the Windows Software Development Kit option when selecting the features to install. Once you’ve pulled it down (it is several GB), you’ll find pvk2pfx in the following folder (you are using a 64-bit OS, right?):

C:\Program Files (x86)\Windows Kits\10\bin\x64\pvk2pfx.exe

Create the PFX file

The command line for pvk2pfx.exe is:

pvk2pfx.exe /pvk rcmtech_private.pvk /spc rcmtech_public.crt /pfx rcmtech.pfx

You’ll get a pop up asking for your pvk file password, which you specified when creating it using pvk.exe. (If you didn’t specify a password, and just hit enter on this popup you’ll just get an error: ERROR: Password incorrect. (Error Code = 0x80070056).)

You should now find yourself with a PFX file, which you can use to import into Windows (e.g. ADFS config wizard).

Posted in Security, Windows | Tagged , , , , , , , , , , , , , | 2 Comments

Send email via Yahoo with PowerShell

Quick reference for sending email via a Yahoo! mail account and their SMTP servers from within a PowerShell script.

You’ll need the Yahoo SMTP server details, which require you to use a specific port (587 – I couldn’t get 465 to work) and an encrypted connection.

I also set up a Yahoo “app password” for PowerShell, which means I don’t have to use my regular password in plain text in a script, which is a good thing. To do this click the settings cog from within Yahoo Mail, go to Account info, then when that opens go to Account Security. From there you’ll find Manage app passwords and can add a new one called (e.g.) PowerShell. Copy and paste the password generated into the PowerShell script. Note that the generated password is shown in four blocks of four letters with spaces in between but when you paste it it’ll come out with no spaces – and this is correct – you do not need the spaces displayed on the Yahoo web page.

Here’s the sample script:

$Username = ""
$Password = "abcdefghijklmnop"

$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $Username, $SecurePassword

$RcptTo = ""
$Subject = "Yahoo Test"
$Body = "This is a test message"
Send-MailMessage -From $Username -To $RcptTo -Subject $Subject -Body $Body -SmtpServer -Port 587 -UseSsl -Credential $Credentials

And here’s the same thing as a function:

function Send-YahooMail ($Username, $Password, $RcptTo, $Subject, $Body){
    $SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
    $Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $Username, $SecurePassword
    Send-MailMessage -From $Username -To $RcptTo -Subject $Subject -Body $Body -SmtpServer -Port 587 -UseSsl -Credential $Credentials

If you don’t want any kind of password in plain text in a script then you need to also look at this post of mine too.

Posted in PowerShell, Security | Tagged , , , , , , , , , , , , | 1 Comment

Connection State Announcer

I’ve been having some very annoying problems with my home broadband where the connection keeps dropping every few minutes. I wrote this quick script to monitor a site on the internet and tell me when it can’t be reached anymore, but it has plenty of other uses. I’m using PowerShell’s ability to speak because I wanted to leave this running whilst I had a web browser open over the top or was away from the computer.
It was also a fun coding exercise to write something that would detect a state change and only report when the connection came up or down, not the entire time it was down. I did this using a two position array and comparing the contents between subsequent tests of the internet site. If the test results were the same, the connection hadn’t changed state, if they were different it had.

# Configure the test
$TestSubject = ""
$TestInterval = 2
$TriesPerTest = 2

# Initialise speech
Add-Type -AssemblyName System.Speech
$Speak = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer

# Initialise an array to hold state information
$Connected = New-Object System.Collections.ArrayList
# Assume the connection is down, write this to the first two positions in the array
$Connected.Add($false) | Out-Null
$Connected.Add($false) | Out-Null

# Loop forever
    # Test the connection, store the result in the second position in the array
    if(Test-Connection -ComputerName $TestSubject -Count $TriesPerTest -ErrorAction SilentlyContinue){
        $Connected[1] = $true
        $Connected[1] = $false
    # Compare the first and second positions to give us a state change trigger
    if($Connected[0] -ne $Connected[1]){
        # State has changed, write timestamp to screen
        Write-Host ("`n"+(Get-Date -Format s)+" ") -ForegroundColor Gray
        if($Connected[1] -eq $true){
            # Announce that the connection is now up
            $Speak.Speak($TestSubject+" is up!")
            # Announce that the connection is now down
            $Speak.Speak($TestSubject+" is down.")
        # Copy the test result into the first position in the array, ready for comparison with the next test result
        $Connected[0] = $Connected[1]
    # Print something colourful to the screen to show relative up/down times
    if($Connected[0] -eq $true){
        Write-Host "#" -ForegroundColor Green -NoNewline
        Write-Host "#" -ForegroundColor Red -NoNewline
    # Pause before next test
    Start-Sleep -Seconds $TestInterval
Posted in Networking, PowerShell, Windows | Tagged , , , , | Leave a comment