Enable BitLocker Safely with PowerShell and Intune · CloudEngineerHub
Detection & Remediation10 min read4 views
How to Remediate BitLocker Encryption Issues with PowerShell
An Intune detection and remediation pair that enables BitLocker with XtsAes256 and a TPM protector, adds a recovery password, and skips devices without a ready TPM.
C
CloudEngineerHub Team
Published: September 17, 2026· Last Updated: September 28, 2026·10 min read
Somewhere in your fleet there is a set of devices where disk encryption simply never
happened: the golden image predated your BitLocker policy, a task sequence step was
disabled "temporarily", or an acquisition brought in machines that had their protection
switched off during a support incident. Enabling BitLocker by hand on each one is an
afternoon you do not have, and doing it blind from a runbook is how volumes end up
encrypted with no recovery password in escrow.
Visual Walkthrough
Every reliable detection script follows this exact structure — copy it.
Decision TreeDetection Script Anatomy — The Exit-Code Contract5/5
Decision gate
Is the state healthy?
One question, one exit code — keep detection dumb and honest.
Healthy → exit 0
1
Test the condition
Single cmdlet or property read; no side effects, no output noise.
2
Exit 0, no output
Silence is the success contract — Intune treats it as compliant.
Unhealthy → exit 1
1
Emit one evidence line
Write the observed value — your future self reads the report.
2
Exit 1
Signals "needs remediation"; the paired fix script may now run.
3
Remediate idempotently
Fix script is safe to run repeatedly; no reboots without consent.
4
Exit 0 after fix
Next detection run proves remediation worked.
Detection Script Anatomy — The Exit-Code Contract. Gate: Is the state healthy? — Healthy → exit 0: Test the condition — Healthy → exit 0: Exit 0, no output — Unhealthy → exit 1: Emit one evidence line — Unhealthy → exit 1: Exit 1 — Unhealthy → exit 1: Remediate idempotently — Unhealthy → exit 1: Exit 0 after fix
C
CloudEngineerHub Team
Author
The CloudEngineerHub editorial team — Microsoft endpoint management and cloud engineers writing hands-on guides on Intune, Azure, Entra ID, Autopilot, Defender and PowerShell. Every article is reviewed against current Microsoft documentation.
This article provides a paired detection and remediation package for exactly that job. The
detection script confirms the device can actually support TPM-based enablement and reports
whether the OS volume is protected. The remediation script enables BitLocker on the
operating system volume with a TPM protector and XtsAes256 encryption, using the Used Space
Only option to keep the first conversion pass short, and makes sure a numerical recovery
password protector exists for recovery and escrow. Devices that cannot support TPM-only
enablement are skipped with a distinct exit code instead of being forced through a
half-working path.
The scope is intentionally narrow. No PIN scenarios, no USB startup keys, no decryption,
no protector removal. Just the one enablement path that works unattended at fleet scale,
with idempotency checks so repeated runs are harmless.
Symptoms
You will usually find these devices through compliance reporting, then confirm locally:
An Intune compliance policy requiring BitLocker fails on specific models or cohorts.
A device shows no BitLocker recovery key in its Entra ID record, or shows no key at all.
Get-BitLockerVolume returns ProtectionStatus: Off and VolumeStatus: FullyDecrypted on the OS volume.
Ad-hoc Enable-BitLocker attempts fail with TPM-related errors on the same devices.
The devices otherwise check in, sync policy, and behave normally, which is why the gap survives for months.
Possible Causes
Windows edition does not include BitLocker
BitLocker requires Windows Pro, Enterprise, or Education. On Home editions the feature and
its cmdlets do not exist, so enablement is impossible regardless of configuration. Verify
the edition before anything else; a fleet audit that skips this check produces mysterious
failures.
TPM absent or not ready
TPM-only enablement needs a TPM that is present and ready. Firmware settings that hide the
TPM, devices provisioned with the TPM cleared, or virtual machines without a vTPM all fail
here. The remediation checks Get-Tpm and refuses to proceed rather than attempting a
protector that cannot be created.
No enablement step ever ran
Devices built from images or Autopilot profiles that never included a disk encryption
policy or script arrive unencrypted. Encryption is not enabled by default on existing Pro
devices outside of modern device provisioning, so absence of an enablement mechanism equals
absence of encryption.
Protectors cleared and never restored
A recovery workflow that turned BitLocker off or removed protectors to access the disk and
did not re-enable protection leaves the volume in an unusable in-between state. Detection
that looks only at VolumeStatus misses this; the pair here checks ProtectionStatus too.
A conversion job already in flight
If encryption or decryption is running, starting another enablement is at best redundant
and at worst corrupts the conversion state. The scripts treat an in-progress conversion as
a wait state, not a failure.
Detection Script
The detection script takes a few seconds, runs in 64-bit SYSTEM context, and performs two
gates plus a volume state read. It never modifies the device; it only decides whether
remediation would be safe and useful.
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#Requires -RunAsAdministrator
[CmdletBinding()]
param()
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
<#
.SYNOPSIS
Detection script: checks whether the OS volume is BitLocker-protected and
whether the device meets the TPM prerequisite for TPM-only enablement.
.NOTES
Intended for Intune Scripts and Remediations, 64-bit SYSTEM context.
Exit 0 = OS volume fully encrypted and protected.
Exit 1 = OS volume unencrypted or unprotected - remediation needed.
Exit 2 = prerequisites missing: BitLocker cmdlets unavailable (Windows
Home or stripped SKU), TPM absent or not ready, or a conversion
job already running. None of these are repairable by enabling.
Exit 3 = unexpected error.
#>$logDir = 'C:\ProgramData\Company\Logs'$logFile = Join-Path $logDir'BitLockerEnableDetection.log'function Write-DetectionLog {
param([Parameter(Mandatory)][string] $Level, [Parameter(Mandatory)][string] $Message)
if (-not (Test-Path $logDir)) { New-Item -Path$logDir -ItemType Directory -Force | Out-Null }
"$([DateTime]::UtcNow.ToString('o')) [$Level] $Message" | Out-File -FilePath$logFile -Append -Encoding utf8
}
try {
Write-DetectionLog 'INFO''BitLocker enablement detection run started.' # ---- Gate 1: BitLocker and TPM cmdlets must exist ----$cmdletsPresent = (@(Get-Command -Name'Get-BitLockerVolume', 'Get-Tpm' -ErrorAction SilentlyContinue).Count -eq2)
if (-not $cmdletsPresent) {
Write-DetectionLog 'WARN''BitLocker/TPM cmdlets are not available. BitLocker requires Windows Pro, Enterprise, or Education; Home editions cannot use it.'
exit 2
}
# ---- Gate 2: TPM present and ready ---- # TPM-only enablement is the only scenario this package supports. Without # a ready TPM the correct fix is firmware/configuration work, not enable.$tpm = Get-Tpm
Write-DetectionLog 'INFO'"TPM state: TpmPresent=$($tpm.TpmPresent) TpmReady=$($tpm.TpmReady)"if (-not $tpm.TpmPresent -or -not$tpm.TpmReady) {
Write-DetectionLog 'WARN''TPM prerequisite not met. TPM-only BitLocker enablement is not possible; resolve TPM presence/readiness first.'
exit 2
}
# ---- OS volume state ----$volume = Get-BitLockerVolume -MountPoint$env:SystemDrive
Write-DetectionLog 'INFO' ("OS volume {0}: ProtectionStatus={1} VolumeStatus={2} EncryptionPercentage={3}%" -f$env:SystemDrive, $volume.ProtectionStatus, $volume.VolumeStatus, $volume.EncryptionPercentage)
if ($volume.VolumeStatus -eq'EncryptionInProgress' -or$volume.VolumeStatus -eq'DecryptionInProgress') {
Write-DetectionLog 'WARN'"A conversion job is already running on the OS volume ($($volume.VolumeStatus)). Remediation must wait for BitLocker to finish."
exit 2
}
if ($volume.ProtectionStatus -eq'On' -and$volume.VolumeStatus -eq'FullyEncrypted') {
Write-DetectionLog 'INFO''OS volume is already protected - device compliant for this package.'
exit 0
}
Write-DetectionLog 'ERROR'"OS volume is not protected (ProtectionStatus=$($volume.ProtectionStatus) VolumeStatus=$($volume.VolumeStatus)). Enablement needed."
exit 1
}
catch {
Write-DetectionLog 'ERROR'"Unexpected failure: $($_.Exception.Message)"
exit 3
}
finally {
Write-DetectionLog 'INFO''BitLocker enablement detection run finished.'
}
Detection Logic
Cmdlet gate. The script verifies that both Get-BitLockerVolume and Get-Tpm are
available. Their absence means Windows Home or a similarly stripped SKU, and the script
exits 2: no amount of scripting adds BitLocker to an edition that does not ship it.
TPM gate.Get-Tpm reports TpmPresent and TpmReady. Both must be true. A device
that fails here needs firmware or provisioning work; enablement attempts would only
generate errors, so the script refuses with exit 2.
OS volume state.Get-BitLockerVolume -MountPoint $env:SystemDrive returns the
authoritative state of the system drive. Three outcomes matter:
ProtectionStatus: On with VolumeStatus: FullyEncrypted means compliant, exit 0.
EncryptionInProgress or DecryptionInProgress means BitLocker is already working;
the script exits 2 with a log line saying to wait, preventing double jobs.
Anything else (typically FullyDecrypted with protection off) is the target state for
remediation, exit 1.
The Healthy value for the OS volume is unambiguous: protection on, fully encrypted. The
log records EncryptionPercentage and EncryptionMethod so you can see the estate's
actual configuration, not just its pass/fail state.
Remediation Script
The remediation enables BitLocker on the OS volume only, with a TPM protector, XtsAes256,
and Used Space Only, then ensures a RecoveryPassword key protector exists. It refuses to
run without a ready TPM (exit 2), never touches an active conversion, never decrypts, and
never prints key material: the recovery password object is captured in a variable and only
its GUID reaches the log. Data volumes, PIN/USB protector scenarios, and protector removal
are all out of scope.
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#Requires -RunAsAdministrator
[CmdletBinding()]
param()
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
<#
.SYNOPSIS
Remediation script: enables BitLocker on the operating system volume with
a TPM protector and ensures a numerical recovery password protector exists.
.DESCRIPTION
Deliberate scope limits (read before assigning this package):
- Acts ONLY when a TPM is present and ready (Get-Tpm). Devices without
a usable TPM exit with code 2; the script never attempts PIN,
PIN-plus-USB, or startup-key scenarios.
- Enables encryption with XtsAes256 and the Used Space Only option,
which converts only allocated space and keeps the initial encryption
pass short on large volumes.
- Ensures a RecoveryPassword key protector exists for recovery and
escrow. Protector objects are captured in variables; only the
protector GUID is written to the log. The 48-digit recovery password
itself is NEVER written to the log or to script output.
- Never decrypts, never rekeys an already-protected volume, never
touches data volumes, and never removes a protector.
.NOTES
Exit 0 = volume protected, already compliant, or a conversion job is
already running under BitLocker control (never restart it).
Exit 2 = prerequisites missing: cmdlets unavailable (Home edition) or
TPM absent/not ready. The device needs a different fix.
Exit 3 = unexpected error.
#>$logDir = 'C:\ProgramData\Company\Logs'$logFile = Join-Path $logDir'BitLockerEnableRemediation.log'function Write-RemediationLog {
param([Parameter(Mandatory)][string] $Level, [Parameter(Mandatory)][string] $Message)
if (-not (Test-Path $logDir)) { New-Item -Path$logDir -ItemType Directory -Force | Out-Null }
"$([DateTime]::UtcNow.ToString('o')) [$Level] $Message" | Out-File -FilePath$logFile -Append -Encoding utf8
}
try {
Write-RemediationLog 'INFO''BitLocker enablement remediation run started.' # ---- Gate 1: cmdlets must exist ----$cmdletsPresent = (@(Get-Command -Name'Get-BitLockerVolume', 'Enable-BitLocker', 'Add-BitLockerKeyProtector', 'Get-Tpm' -ErrorAction SilentlyContinue).Count -eq4)
if (-not $cmdletsPresent) {
Write-RemediationLog 'WARN''BitLocker management cmdlets are unavailable (Windows Home or stripped-down SKU). No enablement attempted.'
exit 2
}
# ---- Gate 2: TPM present and ready ----$tpm = Get-Tpm
Write-RemediationLog 'INFO'"TPM state: TpmPresent=$($tpm.TpmPresent) TpmReady=$($tpm.TpmReady)"if (-not $tpm.TpmPresent -or -not$tpm.TpmReady) {
Write-RemediationLog 'WARN''TPM not usable. Skipping enablement: TPM-only BitLocker cannot be configured on this device. Resolve TPM presence/readiness (firmware settings or provisioning) first.'
exit 2
}
# ---- Current OS volume state: check before any change ----$volume = Get-BitLockerVolume -MountPoint$env:SystemDrive
Write-RemediationLog 'INFO' ("OS volume {0}: ProtectionStatus={1} VolumeStatus={2} EncryptionPercentage={3}%" -f$env:SystemDrive, $volume.ProtectionStatus, $volume.VolumeStatus, $volume.EncryptionPercentage)
if ($volume.VolumeStatus -eq'EncryptionInProgress' -or$volume.VolumeStatus -eq'DecryptionInProgress') {
Write-RemediationLog 'WARN'"A conversion job is already running on $($env:SystemDrive). No action taken - let BitLocker finish before evaluating again."
exit 0
}
if ($volume.ProtectionStatus -eq'On' -and$volume.VolumeStatus -eq'FullyEncrypted') {
Write-RemediationLog 'INFO''OS volume already protected - no changes made.'
exit 0
}
$changed = $false # ---- Step 1: ensure a TPM protector exists and protection is on ----$tpmProtectors = @($volume.KeyProtectors | Where-Object { $_.KeyProtectorType -eq'Tpm' })
if ($volume.VolumeStatus -eq'FullyEncrypted' -and$tpmProtectors.Count -gt0) {
Write-RemediationLog 'INFO''Volume is encrypted and already has a TPM protector - skipping the enable step.'
}
else {
Write-RemediationLog 'INFO'"Enabling BitLocker on $($env:SystemDrive): EncryptionMethod=XtsAes256, UsedSpaceOnly, TpmProtector."$null = Enable-BitLocker -MountPoint$env:SystemDrive -EncryptionMethod XtsAes256 -UsedSpaceOnly -TpmProtector
Write-RemediationLog 'INFO''Enable-BitLocker accepted. The encryption job now runs in the background; no restart is required for conversion to proceed.'$changed = $true
}
# ---- Step 2: ensure a recovery password protector exists (escrow target) ----$currentVolume = Get-BitLockerVolume -MountPoint$env:SystemDrive$recoveryProtectors = @($currentVolume.KeyProtectors | Where-Object { $_.KeyProtectorType -eq'RecoveryPassword' })
if ($recoveryProtectors.Count -eq0) {
$newProtector = Add-BitLockerKeyProtector -MountPoint$env:SystemDrive -RecoveryPasswordProtector
Write-RemediationLog 'INFO'"Added RecoveryPassword key protector $($newProtector.KeyProtectorId). The 48-digit password is never logged or emitted by this script."$changed = $true
}
else {
Write-RemediationLog 'INFO'"RecoveryPassword protector already present ($($recoveryProtectors[0].KeyProtectorId))."
}
# ---- Verify and report final state ----$finalVolume = Get-BitLockerVolume -MountPoint$env:SystemDrive
Write-RemediationLog 'INFO' ("Post-change state: ProtectionStatus={0} VolumeStatus={1} EncryptionPercentage={2}% EncryptionMethod={3}" -f$finalVolume.ProtectionStatus, $finalVolume.VolumeStatus, $finalVolume.EncryptionPercentage, $finalVolume.EncryptionMethod)
if ($changed) {
Write-RemediationLog 'INFO''BitLocker enablement applied.'
}
else {
Write-RemediationLog 'INFO''Device already compliant - no changes made.'
}
exit 0
}
catch {
Write-RemediationLog 'ERROR'"BitLocker enablement failed: $($_.Exception.Message)"
exit 3
}
finally {
Write-RemediationLog 'INFO''BitLocker enablement remediation run finished.'
}
Two design decisions deserve explanation. First, Used Space Only: on a large volume that
was never full, converting only allocated space cuts initial encryption time dramatically
and is Microsoft's recommended default for new enablement. The honest trade-off is that
blocks from previously deleted files are not covered on a volume that held sensitive data
before enablement. Second, the recovery password is added even though TPM-only volumes
rarely need it interactively: without it there is nothing to escrow to Entra ID, and
recovery scenarios that do need it are exactly the ones where you cannot create it anymore.
For fleets with Entra join, the escrow of that protector is handled by disk encryption
policy or by the companion package in
Detecting BitLocker Recovery Key Escrow Problems with PowerShell,
which uses BackupToAAD-BitLockerKeyProtector to re-trigger the backup.
Deploying Through Intune
In the Microsoft Intune admin center, go to Devices → Scripts and remediations and select + Add under Windows 10/11.
On Basics, name it something like Remediate - Enable BitLocker on OS volume, and put the blast radius in the description: "enables BitLocker with TPM protector and recovery password on C: only; skips devices without a ready TPM".
On Detection script, upload detect.ps1. Set Run script in 64-bit PowerShell: Yes and Run this script using signed-on credentials: No so it runs as SYSTEM.
On Remediation script, upload remediate.ps1 with the same context settings. Leave Enforce script signature check: No unless your organization signs and distributes internal certificates.
On Schedule, choose Daily while the backlog of unencrypted devices drains, then move to Monthly as a safety net.
On Assignments, start with a pilot ring of test devices, including one known-unencrypted VM. Exclude devices you know lack a TPM. Apply device filters to keep Home-edition machines out of scope entirely.
Post-specific notes:
Devices exiting 2 for TPM reasons need firmware or provisioning work first; the TPM
health companion post covers detection of that state.
Encryption proceeds in the background after enablement; on typical hardware with Used
Space Only this takes minutes to a couple of hours. Expect the device to stay busy on
disk I/O during conversion.
TPM-only enablement does not require a restart for conversion to start, but validate
your device models in the pilot ring anyway; firmware variance is real.
If your tenant uses Intune's disk encryption policy, prefer that as the primary
mechanism and use this package as the catch-up for devices that slipped through.
Visual Walkthrough
Silent encryption only works when recovery keys land where you can find them.
Silent enable with TPM + X protectors; no user prompt.
protect
2
TPM seals the key
Platform + PCR values bind the key to device state.
recovery
3
Recovery key generated
48-digit numeric key created at enablement.
escrow
4
Key escrowed to Entra
Backup succeeds before compliance is reported — the critical step.
recover
5
Recovery available
Admin/self-service retrieve key with RBAC + audit.
6
Compliance reported
Encryption status flows into compliance + CA decisions.
BitLocker Silent Encryption + Key Escrow. 1. Policy triggers encryption: Silent enable with TPM + X protectors; no user prompt. — 2. TPM seals the key: Platform + PCR values bind the key to device state. — 3. Recovery key generated: 48-digit numeric key created at enablement. — 4. Key escrowed to Entra: Backup succeeds before compliance is reported — the critical step. — 5. Recovery available: Admin/self-service retrieve key with RBAC + audit. — 6. Compliance reported: Encryption status flows into compliance + CA decisions.
Exit Codes
Intune evaluates the detection script's exit code; any non-zero marks the device as
needing remediation and runs the remediation script per your schedule.
Code
Meaning
0
Detection: OS volume encrypted and protected. Remediation: repair applied or device already compliant
1
Detection: OS volume unencrypted or unprotected - remediation needed
2
Prerequisites missing or a wait state: BitLocker cmdlets unavailable, TPM absent/not ready, or a conversion job already running
3
Unexpected script error - inspect the log
Devices that flip to "Remediated" in the device status view are ones where enablement
succeeded and detection now passes. Devices sitting in "Error" need the local log; exit 3
usually means enablement was attempted and the platform refused.
Both carry UTC timestamps, levels (INFO, WARN, ERROR), and messages that include the
TPM state, the volume state before and after, and every action taken. Protector GUIDs are
logged; recovery passwords never are. Log volume is a few lines per run, so monthly
rotation is more than enough retention for most environments.
Troubleshooting the Script
Remediation exits 3 immediately on specific models. Read the exception in the log.
Enable-BitLocker failures usually name the underlying cause: TPM locked, volume not
eligible, or group/MDM policy conflict. Cross-check with manage-bde -status for a
human-readable view.
Devices stuck at exit 2 with TpmReady=False. Check firmware TPM settings and
provisioning state (Get-Tpm again interactively). Many devices need one clean reboot
after TPM settings change; some need a firmware update.
Exit code 2 flood from consumer devices. Those are Home editions. The scripts told
you honestly; exclude them with a filter rather than leaving them as errors.
Encryption does not progress after enablement. Confirm the volume state with
Get-BitLockerVolume; if the percentage never moves, the BitLocker-API event log under
Applications and Services Logs records why the conversion stalled.
A device already has a PIN or startup key protector. The scripts leave such volumes
alone if protection is on. If protection is off and an unexpected protector mix exists,
involve your security team before changing anything by hand.
How to Validate the Fix
Pick an unencrypted test device and run the detection script manually in an elevated
64-bit PowerShell. Expect exit 1 with the unprotected-volume log line.
Run the remediation manually. Expect exit 0, log lines showing the TPM check, the
Enable-BitLocker acceptance, and the recovery protector GUID.
Re-run detection immediately: with conversion in progress it exits 2 (wait state).
Re-run after conversion completes: it exits 0.
Confirm the protector list with manage-bde -protectors -get C: and verify a numerical
password protector exists alongside TPM.
In the admin center, check the package's Device status; the device should report
Remediated after its next sync. If disk encryption policy with escrow is assigned, the
recovery key should appear on the device's Entra record after the next check-in.
Production Considerations
Execution context. Both scripts run as SYSTEM in 64-bit Windows PowerShell. Enablement
requires the admin rights that SYSTEM context provides.
Idempotency. Check-then-change throughout: protected volumes are never re-enabled,
existing protectors are never duplicated, and active conversions are never restarted.
Repeated scheduled runs converge to "already compliant".
Side effects and reboots. The only meaningful side effect is the encryption
conversion itself, which consumes disk I/O and CPU for its duration. No restart is
triggered by the scripts. Used Space Only keeps the conversion window short.
Security. No credentials or key material appear in scripts, logs, or script output;
the recovery password is deliberately suppressed. Coordinate the rollout with your
security team since enablement changes the device's recovery story, and validate the
package on a test ring together with your PowerShell automation SME before broad
production rollout.
Why does the script refuse to run when no TPM is present?
TPM-only is the only enablement path that works unattended and securely at scale. The
alternatives (PINs users forget, USB startup keys that get lost, recovery-password-only
volumes) create more support load than they solve and are policy decisions, not script
decisions. A distinct exit code tells you exactly which devices need firmware or vTPM work.
Why XtsAes256 and Used Space Only?
XtsAes256 is the strong default for Windows 10 and 11 devices, and Used Space Only
shortens initial conversion substantially on large drives, which matters when hundreds of
devices encrypt at once. The trade-off, that previously deleted blocks are not covered, is
stated in the article so you can make the call consciously for volumes with a sensitive
history.
Does this enable encryption on data drives too?
No. The package scopes itself to the OS volume deliberately, because data volume
enablement has different protectors, auto-unlock considerations, and failure modes. Pair
the status detection post with this one: it reports all fixed drives, and you can extend
the same pattern to data volumes once your OS volume coverage is stable.
Comments
0No comments yet — be the first to share your thoughts.