Skip to main content

How to Check BitLocker Encryption Status in Batch Script

BitLocker is the enterprise-grade full disk encryption tool built into Windows Pro, Enterprise, and Education editions. If a laptop is stolen and its drive is not encrypted, every file (passwords, financial records, personal data) is freely accessible to anyone who removes the hard drive. To verify that your fleet is protected, you need a way to programmatically audit the encryption status of every drive. A Batch script can use the manage-bde command-line tool to report whether BitLocker is active, the encryption percentage, and which key protectors are in use.

This guide will explain how to audit BitLocker status via the command line.

Understanding BitLocker States​

BitLocker has two independent states that must both be correct for full protection:

StatePropertyValuesWhat It Means
Conversion StatusIs the data encrypted?Fully Encrypted, Encryption in Progress, Fully DecryptedWhether the actual bits on disk are scrambled
Protection StatusIs the key protector active?Protection On, Protection OffWhether the encryption key is being enforced

Why both matter:​

  • Fully Encrypted + Protection On: The drive is secure. This is the only fully compliant state.
  • Fully Encrypted + Protection Off: The data is encrypted but the protection is suspended (common during BIOS/firmware updates). Anyone with physical access can read the drive until protection is resumed.
  • Fully Decrypted + Protection Off: BitLocker is not active. The drive is completely unprotected.
  • Encryption in Progress: BitLocker is currently encrypting. The drive is partially protected.

Method 1: Comprehensive BitLocker Audit Report​

This method generates a detailed report of all volumes' encryption status, suitable for security auditing and compliance documentation.

@echo off
setlocal

for /f "delims=" %%t in (
'powershell -NoProfile -Command "Get-Date -Format ''yyyyMMdd_HHmmss''"'
) do set "Stamp=%%t"

set "ReportFile=%~dp0BitLocker_%COMPUTERNAME%_%Stamp%.txt"

:: Verify admin privileges
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] BitLocker status queries require administrator privileges. >&2
echo Right-click and select "Run as administrator." >&2
endlocal
exit /b 1
)

:: Verify manage-bde is available (not present on Home editions)
where manage-bde >nul 2>&1
if errorlevel 1 (
echo [ERROR] manage-bde is not available on this system. >&2
echo BitLocker requires Windows Pro, Enterprise, or Education edition. >&2
endlocal
exit /b 1
)

echo [INFO] Generating BitLocker audit report...

:: =============================================
:: Report Header
:: =============================================
(
echo ==================================================
echo BITLOCKER ENCRYPTION AUDIT REPORT
echo ==================================================
) > "%ReportFile%"

for /f "delims=" %%t in (
'powershell -NoProfile -Command "Get-Date -Format ''yyyy-MM-dd HH:mm:ss''"'
) do echo Generated: %%t >> "%ReportFile%"

echo Computer: %COMPUTERNAME% >> "%ReportFile%"
echo. >> "%ReportFile%"

:: =============================================
:: Windows Edition Check
:: =============================================
echo --- Windows Edition --- >> "%ReportFile%"
for /f "delims=" %%e in (
'powershell -NoProfile -Command "(Get-CimInstance Win32_OperatingSystem).Caption"'
) do echo %%e >> "%ReportFile%"
echo. >> "%ReportFile%"

:: =============================================
:: Full Status for All Volumes
:: =============================================
echo --- BitLocker Status (All Volumes) --- >> "%ReportFile%"
echo. >> "%ReportFile%"

manage-bde -status >> "%ReportFile%" 2>&1

echo. >> "%ReportFile%"

:: =============================================
:: Summary Analysis
:: =============================================
echo --- Compliance Summary --- >> "%ReportFile%"
echo. >> "%ReportFile%"

powershell -NoProfile -Command ^
"$volumes = Get-BitLockerVolume -ErrorAction SilentlyContinue;" ^
"if (-not $volumes) {" ^
" Write-Output ' BitLocker information not available (cmdlet may not be supported).';" ^
" exit 0" ^
"};" ^
"$compliant = 0; $noncompliant = 0; $suspended = 0;" ^
"foreach ($v in $volumes) {" ^
" $status = 'NON-COMPLIANT';" ^
" if ($v.VolumeStatus -eq 'FullyEncrypted' -and $v.ProtectionStatus -eq 'On') {" ^
" $status = 'COMPLIANT';" ^
" $compliant++" ^
" } elseif ($v.VolumeStatus -eq 'FullyEncrypted' -and $v.ProtectionStatus -eq 'Off') {" ^
" $status = 'SUSPENDED';" ^
" $suspended++" ^
" } else {" ^
" $noncompliant++" ^
" };" ^
" $protectors = ($v.KeyProtector | ForEach-Object { $_.KeyProtectorType }) -join ', ';" ^
" if (-not $protectors) { $protectors = 'None' };" ^
" Write-Output \" [$status] $($v.MountPoint)\";" ^
" Write-Output \" Encryption: $($v.VolumeStatus)\";" ^
" Write-Output \" Protection: $($v.ProtectionStatus)\";" ^
" Write-Output \" Protectors: $protectors\";" ^
" Write-Output ''" ^
"};" ^
"Write-Output \" Total: $($volumes.Count) volume(s)\";" ^
"Write-Output \" Compliant: $compliant Suspended: $suspended Non-compliant: $noncompliant\";" ^
"if ($noncompliant -gt 0 -or $suspended -gt 0) {" ^
" Write-Output '';" ^
" Write-Output ' [ACTION REQUIRED] One or more volumes are not fully protected.'" ^
"}" >> "%ReportFile%"

echo. >> "%ReportFile%"
echo ================================================== >> "%ReportFile%"

echo [OK] BitLocker report saved to: %ReportFile%

:: Display the summary on screen too
echo.
type "%ReportFile%" | findstr /i "COMPLIANT SUSPENDED NON-COMPLIANT ACTION"

endlocal
exit /b 0

Sample compliance summary:​

[COMPLIANT] C:
Encryption: FullyEncrypted
Protection: On
Protectors: Tpm, RecoveryPassword

[SUSPENDED] D:
Encryption: FullyEncrypted
Protection: Off
Protectors: Password, RecoveryPassword

[NON-COMPLIANT] E:
Encryption: FullyDecrypted
Protection: Off
Protectors: None

Total: 3 volume(s)
Compliant: 1 Suspended: 1 Non-compliant: 1

[ACTION REQUIRED] One or more volumes are not fully protected.

Why the report uses both manage-bde and Get-BitLockerVolume:​

  • manage-bde -status provides the complete raw output that compliance auditors expect to see, i.e. it is the canonical reference tool.
  • Get-BitLockerVolume returns typed PowerShell objects that can be analyzed programmatically (counting compliant/non-compliant, extracting protector types, building CSV reports).

Method 2: Quick Compliance Check for a Specific Drive​

For login scripts, deployment gates, or quick verification, this method checks a single drive and returns a clear pass/fail result.

@echo off
setlocal EnableDelayedExpansion

set "Drive=%~1"
if "%Drive%"=="" set "Drive=C:"

:: Ensure drive letter format
if NOT "%Drive:~1,1%"==":" set "Drive=%Drive%:"

net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)

where manage-bde >nul 2>&1
if errorlevel 1 (
echo [ERROR] BitLocker is not available on this Windows edition. >&2
endlocal
exit /b 1
)

echo [INFO] Checking BitLocker compliance for %Drive%...

:: Get full status into a temp file for reliable parsing
set "TempFile=%TEMP%\bde_status_%RANDOM%.txt"
manage-bde -status %Drive% > "%TempFile%" 2>&1

if errorlevel 1 (
echo [ERROR] Cannot get BitLocker status for %Drive%. >&2
del "%TempFile%" 2>nul
endlocal
exit /b 1
)

:: Initialize as FALSE
set "Encrypted=FALSE"
set "Protected=FALSE"

:: Check for Fully Encrypted
findstr /i /c:"Fully Encrypted" "%TempFile%" >nul 2>&1
if !errorlevel! equ 0 set "Encrypted=TRUE"

:: Check for 100% encrypted (alternative check)
findstr /i /c:"100.0%%" "%TempFile%" >nul 2>&1
if !errorlevel! equ 0 set "Encrypted=TRUE"

findstr /i /c:"100%%" "%TempFile%" >nul 2>&1
if !errorlevel! equ 0 set "Encrypted=TRUE"

:: Check Protection Status is ON
findstr /i /c:"Protection On" "%TempFile%" >nul 2>&1
if !errorlevel! equ 0 set "Protected=TRUE"

:: Debug - show what we found
echo.
echo [DEBUG] === Key lines from manage-bde ===
findstr /i "Conversion Status Percentage Protection" "%TempFile%"
echo [DEBUG] Encrypted=!Encrypted!, Protected=!Protected!
echo.

:: Cleanup temp file
del "%TempFile%" 2>nul

:: Evaluate results
if "!Encrypted!"=="TRUE" if "!Protected!"=="TRUE" (
echo [PASS] %Drive% is fully encrypted with protection enabled.
endlocal
exit /b 0
)

if "!Encrypted!"=="TRUE" if "!Protected!"=="FALSE" (
echo [WARNING] %Drive% is encrypted but protection is SUSPENDED. >&2
endlocal
exit /b 1
)

echo [FAIL] %Drive% is NOT encrypted. This machine is non-compliant. >&2
echo Enable BitLocker: manage-bde -on %Drive%
endlocal
exit /b 2

Exit codes for automation:​

Exit CodeMeaning
0Fully encrypted and protection is on (compliant)
1Encrypted but protection is suspended (partially compliant)
2Not encrypted (non-compliant)

These exit codes allow a parent script or scheduled task to take different actions based on the compliance level.

Localization note:​

The findstr approach searches for English-language strings like "Fully Encrypted" and "Protection On." On non-English Windows, these strings are translated. For international deployments, use Get-BitLockerVolume in PowerShell, which returns language-independent enum values.

Method 3: Fleet-Wide BitLocker Compliance CSV​

For auditing encryption across multiple machines, export compliance data to a shared CSV.

@echo off
setlocal

set "CSVFile=\\Server\Audit\bitlocker_compliance.csv"

if not exist "%CSVFile%" (
echo "Timestamp","Computer","Drive","EncryptionStatus","ProtectionStatus","Protectors","EncryptionPct" > "%CSVFile%" 2>nul
)

net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)

powershell -NoProfile -Command ^
"$ts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss';" ^
"$volumes = Get-BitLockerVolume -ErrorAction SilentlyContinue;" ^
"if (-not $volumes) {" ^
" Write-Output ('\"' + $ts + '\",\"' + $env:COMPUTERNAME + '\",\"N/A\",\"Not Available\",\"N/A\",\"N/A\",\"N/A\"')" ^
"} else {" ^
" foreach ($v in $volumes) {" ^
" $protectors = ($v.KeyProtector | ForEach-Object { $_.KeyProtectorType }) -join '; ';" ^
" if (-not $protectors) { $protectors = 'None' };" ^
" $pct = $v.EncryptionPercentage;" ^
" Write-Output ('\"' + $ts + '\",\"' + $env:COMPUTERNAME + '\",\"' + $v.MountPoint + '\",\"' + $v.VolumeStatus + '\",\"' + $v.ProtectionStatus + '\",\"' + $protectors + '\",\"' + $pct + '\"')" ^
" }" ^
"}" >> "%CSVFile%" 2>nul

echo [OK] BitLocker data exported for %COMPUTERNAME%.

endlocal
exit /b 0

What to look for in the fleet CSV:​

  • VolumeStatus β‰  FullyEncrypted: Machines that are not encrypted or are still encrypting.
  • ProtectionStatus = Off: Machines where BitLocker is suspended. If the suspension has lasted more than a few hours, it may indicate a forgotten resume after a BIOS update.
  • Protectors = None or ClearKey: A drive with no protectors or only a "Clear Key" is technically encrypted but provides no actual security (anyone can decrypt it).
  • EncryptionPct < 100: Encryption is in progress. Monitor until it reaches 100%.
  • "Not Available": Machine is running Windows Home (no BitLocker) or the Get-BitLockerVolume cmdlet is not available.

Method 4: Key Protector Audit​

For security teams, knowing what types of key protectors are in use is as important as knowing whether the drive is encrypted. A TPM-only protector is vulnerable to certain cold-boot attacks; TPM + PIN provides stronger security.

@echo off
setlocal

set "Drive=%~1"
if "%Drive%"=="" set "Drive=C:"
if "%Drive:~1,1%"=="" set "Drive=%Drive%:"

net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges required. >&2
endlocal
exit /b 1
)

echo [INFO] Key protector audit for %Drive%:
echo --------------------------------------------------

powershell -NoProfile -Command ^
"$vol = Get-BitLockerVolume -MountPoint '%Drive%' -ErrorAction SilentlyContinue;" ^
"if (-not $vol) { Write-Host 'BitLocker information not available for %Drive%.'; exit 1 };" ^
"Write-Host \" Volume: %Drive%\";" ^
"Write-Host \" Encryption: $($vol.VolumeStatus)\";" ^
"Write-Host \" Protection: $($vol.ProtectionStatus)\";" ^
"Write-Host '';" ^
"if ($vol.KeyProtector.Count -eq 0) {" ^
" Write-Host ' No key protectors configured.' -ForegroundColor Red;" ^
" exit 1" ^
"};" ^
"Write-Host ' Key Protectors:';" ^
"foreach ($kp in $vol.KeyProtector) {" ^
" $type = [string]$kp.KeyProtectorType;" ^
" $id = $kp.KeyProtectorId;" ^
" Write-Host \" Type: $type\";" ^
" Write-Host \" ID: $id\";" ^
" Write-Host ''" ^
"};" ^
"$types = $vol.KeyProtector.KeyProtectorType;" ^
"if ('Tpm' -in $types -and 'TpmPin' -notin $types -and 'TpmPinStartupKey' -notin $types) {" ^
" Write-Host ' [INFO] TPM-only protection. Consider adding a PIN for stronger security.' -ForegroundColor Yellow" ^
"};" ^
"if ('RecoveryPassword' -notin $types) {" ^
" Write-Host ' [WARNING] No recovery password protector. Recovery will be difficult if TPM fails.' -ForegroundColor Red" ^
"}"

echo --------------------------------------------------

endlocal
exit /b 0

Key protector types and their security implications:​

Protector TypeSecurity LevelNotes
TpmGoodUnlocks automatically at boot. Vulnerable to hardware attacks.
TpmPinBetterRequires PIN at pre-boot. Mitigates cold-boot and DMA attacks.
TpmPinStartupKeyBestRequires both PIN and USB key. Most secure for laptops.
PasswordGoodRequires password at pre-boot. Used for data drives.
RecoveryPasswordN/A (backup)48-digit numeric key for recovery. Essential for lockout scenarios.
ExternalKeyVariesUSB-based key. Must be present at boot.

Every encrypted volume should have a RecoveryPassword protector. Without it, a TPM failure, BIOS update, or hardware change will make the drive permanently inaccessible.

How to Avoid Common Errors​

Wrong Way: Checking Only Conversion Status​

:: INCOMPLETE: drive may be encrypted but protection is suspended
manage-bde -status C: | findstr /i "Fully Encrypted"

A drive can be Fully Encrypted with Protection Off (suspended). This means the encryption key is available in clear text, i.e. anyone with physical access can read the drive.

Correct Way: Always check both Conversion Status AND Protection Status. Method 2 demonstrates this dual check.

Problem: BitLocker Not Available (Windows Home)​

manage-bde and Get-BitLockerVolume are not present on Windows Home edition. Running them produces "not recognized" or "not found" errors.

Solution: Method 1 checks for manage-bde availability before proceeding. The fleet CSV (Method 3) records "Not Available" rather than failing silently.

Problem: Suspended Protection After BIOS/Firmware Updates​

BitLocker is often suspended before BIOS updates (either manually or by Windows Update) and should be resumed automatically afterward. Sometimes the resume fails or is forgotten.

Solution: Monitor for Protection Off status in your regular audits. Resume suspended protection with:

manage-bde -protectors -enable C:

Problem: Localized Output from manage-bde​

The text output of manage-bde -status is translated on non-English Windows. "Protection On" becomes "Schutz aktiviert" (German), "Protection activΓ©e" (French), etc. findstr patterns break on these.

Solution: Use Get-BitLockerVolume (PowerShell) for programmatic checks. Its properties (VolumeStatus, ProtectionStatus) return language-independent enum values.

Best Practices and Rules​

1. Check Both Encryption AND Protection Status​

A fully compliant drive must show both Fully Encrypted (data is scrambled) and Protection On (key protector is enforced). Either one alone is insufficient.

2. Verify Key Protector Types​

A drive with only a ClearKey protector is encrypted but provides zero actual security. Ensure production drives use Tpm, TpmPin, or Password protectors. Verify a RecoveryPassword protector exists for lockout recovery.

3. Audit All Volumes, Not Just C:​

Data drives, removable media, and secondary partitions can contain sensitive information. Method 1 audits all volumes. Method 3's CSV reports on every volume per machine.

4. Store Recovery Keys Securely​

The 48-digit recovery password should be stored in Active Directory, Azure AD, or a secure key management system, not in a text file on the same machine or a shared drive accessible to all users.

5. Schedule Regular Compliance Audits​

BitLocker protection can be suspended by Windows Update, firmware tools, or administrators. Run Method 3's fleet audit weekly or monthly to detect suspended or missing encryption before a device is lost.

6. Report on Windows Edition​

If a machine runs Windows Home, BitLocker is not available. The audit should report this clearly rather than failing silently, so IT can plan alternative encryption (Device Encryption, VeraCrypt) or hardware reassignment.

Conclusions​

Checking BitLocker encryption status is a non-negotiable task for any organization handling sensitive data. By auditing both encryption state and protection status, verifying key protector types, and collecting fleet-wide compliance data, you gain the assurance that every device is protected against physical theft. This automated oversight is essential for regulatory compliance (HIPAA, PCI-DSS, GDPR) and for maintaining the trust that your organization's data is secure.