Script Repository


Computers with BitLocker installed or not installed

February 24, 2021
1904

The script creates and emails 2 lists: a list of computers where Bitlocker is installed and a list of computers where it is not installed.

To generate such a report on demand, create a custom command configured for the Domain-DNS object type. To generate it on a regular basis, create a scheduled task and include any of your AD domains in the Activity Scope.

Script 1: Report in Excel

The script creates and emails an Excel report with 2 lists: a list of computers where Bitlocker is installed, and a list of computers where it is not installed.

Parameters:

  • $xlFilePath - Specifies a path to the Excel file that will be created by the script.
  • $removeXlFile - Specifies whether to remove the Excel file after sending.
  • $to - Specifies a recipient of the report.
  • $subject - Specifies the email message subject.
  • $from - Specifies the email address from which the notification will be sent.
  • $smtpServer - Specifies the SMTP server to use for sending the report.
Edit Remove
PowerShell
$xlFilePath = "C:\scripts\BitlockerReport.xlsx" # TODO: modify me
$removeXlFile = $True # TODO: modify me

# E-mail settings
$to = "recipient@domain.com" # TODO: modify me
$subject = "Bitlocker Report" # TODO: modify me
$from = "noreply@domain.com" # TODO: modify me
$smtpServer = "mail.domain.com" # TODO: modify me

function SearchObjects($filter, $properties)
{
    $searcher = $Context.BindToObject("Adaxes://rootDSE")
    $searcher.SearchFilter = $filter
    $searcher.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.PageSize = 500
    $searcher.ReferralChasing = "ADS_CHASE_REFERRALS_NEVER"
    $searcher.SetPropertiesToLoad($properties)
    $searcher.VirtualRoot = $True
    
    try
    {
        $searchResultIterator = $searcher.ExecuteSearch()
        $searchResults = $searchResultIterator.FetchAll()
        
        return ,$searchResults
    }
    finally
    {
        # Release resources
        if ($searchResultIterator){ $searchResultIterator.Dispose() }
    }
}

function ReleaseComObjects($objArray)
{
    foreach ($object in $objArray)
    {
        [System.Runtime.Interopservices.Marshal]::FinalReleaseComObject($object)
    }
}

# Get all BitLoker objects
$bitlockerSearchResults = SearchObjects "(objectClass=msFVE-RecoveryInformation)" @("distinguishedName")
$computersWithBitlocker = New-Object "System.Collections.Generic.HashSet[System.String]"

foreach ($searchResult in $bitlockerSearchResults)
{
    $dn = New-Object "Softerra.Adaxes.Ldap.DN" $searchResult.Properties["distinguishedName"].Value
    [void]$computersWithBitlocker.Add($dn.Parent)
}

# Search all computers
$computers = SearchObjects "(objectCategory=computer)" @("distinguishedName", "description", "operatingSystem")

try
{
    # Create Excel COM object
    try
    {
        $objExcel = New-Object -ComObject Excel.Application
    }
    catch
    {
        $errorMessage = "Cannot create an Excel object." + $_.Exception.Message
        Write-Error $errorMessage
        return
    }
    
    $objExcel.Visible = $false
    $objExcel.DisplayAlerts = $false
    $objExcel.AskToUpdateLinks = $false
    $objExcel.AlertBeforeOverwriting = $false

    $workbook = $objExcel.Workbooks.Add()
    $list = $workbook.Worksheets.Item(1)
    $list.Name = $subject
    $cells = $list.Cells

    $computersWithBitlockerRecords = New-Object "System.Collections.ArrayList"
    $computersWithoutBitlockerRecords = New-Object "System.Collections.ArrayList"
    
    foreach ($searchResult in $computers)
    {
        # Get computer info
        $computerName = $Context.GetDisplayNameFromAdsPath($searchResult.AdsPath)
        $description = $searchResult.Properties["description"].Value
        $operatingSystem = $searchResult.Properties["operatingSystem"].Value
        
        # Build record
        $record = New-Object "System.Collections.ArrayList"
        [void]$record.Add($computerName)
        [void]$record.Add($description)
        [void]$record.Add($operatingSystem)
        
        $dn = $searchResult.Properties["distinguishedName"].Value
        if ($computersWithBitlocker.Contains($dn))
        {
            $computersWithBitlockerRecords.Add($record)
        }
        else
        {
            $computersWithoutBitlockerRecords.Add($record)
        }
    }
    
    if ($computersWithBitlockerRecords.Count -ne 0)
    {
        # Create an array for computer with BitLocker records
        $rows = New-Object "object[,]" $computersWithBitlockerRecords.Count, 3
        for ($i = 0; $i -lt $computersWithBitlockerRecords.Count; $i++)
        {
            $record = $computersWithBitlockerRecords[$i]
            for($j = 0; $j -lt $record.Count; $j++)
            {
                $rows[$i,$j] = $record[$j]
            }
        }
        
        # Add records to the Excel file
        $cells.Item(1, 1) = "Computers with BitLocker"
        $cells.Item(2, 1) = "Name"
        $cells.Item(2, 2) = "Description"
        $cells.Item(2, 3) = "Operating System"
        $cells.Item(1, 1).Font.Bold = $True
        $cells.Item(2, 1).Font.Bold = $True
        $cells.Item(2, 2).Font.Bold = $True
        $cells.Item(2, 3).Font.Bold = $True
        $list.Range($cells.Item(3, 1), $cells.Item($computersWithBitlockerRecords.Count + 2, 3)).Value2 = $rows
    }

    if ($computersWithoutBitlockerRecords.Count -ne 0)
    {
        if ($computersWithBitlockerRecords.Count -ne 0)
        {
            $startRecord = $computersWithBitlockerRecords.Count + 6
        }
        else
        {
            $startRecord = 3
        }
        
        # Create an array for computer without BitLocker records
        $rows = New-Object "object[,]" $computersWithoutBitlockerRecords.Count, 3
        for ($i = 0; $i -lt $computersWithoutBitlockerRecords.Count; $i++)
        {
            $record = $computersWithoutBitlockerRecords[$i]
            for($j = 0; $j -lt $record.Count; $j++)
            {
                $rows[$i,$j] = $record[$j]
            }
        }
        
        # Add records to Excel file
        $cells.Item($startRecord - 2, 1) = "Computers without BitLocker"
        $cells.Item($startRecord - 1, 1) = "Name"
        $cells.Item($startRecord - 1, 2) = "Description"
        $cells.Item($startRecord - 1, 3) = "Operating System"
        $cells.Item($startRecord - 2, 1).Font.Bold = $True
        $cells.Item($startRecord - 1, 1).Font.Bold = $True
        $cells.Item($startRecord - 1, 2).Font.Bold = $True
        $cells.Item($startRecord - 1, 3).Font.Bold = $True
        $list.Range($cells.Item($startRecord, 1), $cells.Item($computersWithoutBitlockerRecords.Count + 1, 3)).Value2 = $rows
    }
    
    $usedRange = $list.UsedRange
    [void]$usedRange.EntireColumn.AutoFit()
    $workbook.SaveCopyAs($xlFilePath)
    
    # Send mail
    Send-MailMessage -To $to -from $from -SmtpServer $smtpServer -Subject $subject -Body "BitLocker report" -Attachments $xlFilePath
     
    if ($removeXlFile)
    {
        # Remove the file
        Remove-Item -Path $xlFilePath -Force
    }
    
}
finally
{
    # Quit Excel application
    ReleaseComObjects @($cells, $usedRange, $list)
    $workbook.Close($False)
    ReleaseComObjects @($workbook)
    $objExcel.Quit()
    ReleaseComObjects @($objExcel)
}

Script 2: Report in CSV

The script creates and emails 2 CSV files: one with a list of computers where Bitlocker is installed, and another with a list of computers where it is not installed.

Parameters:

  • $computersWithBitlockerCsvFilePath - Specifies a path to the CSV file that will contain computers with Bitlocker installed.
  • $computersWithoutBitlockerCsvFilePath - Specifies a path to the CSV file that will contain computers with not Bitlocker installed.
  • $removeCSVFile - Specifies whether to remove the CSV files after sending.
  • $to - Specifies a recipient of the report.
  • $subject - Specifies the email message subject.
  • $from - Specifies the email address from which the notification will be sent.
  • $smtpServer - Specifies the SMTP server to use for sending the report.
Edit Remove
PowerShell
# CSV file settings
$computersWithBitlockerCsvFilePath = "C:\scripts\ComputersWithBitlocker.csv" # TODO: modify me
$computersWithoutBitlockerCsvFilePath = "C:\scripts\ComputersWithoutBitlocker.csv" # TODO: modify me
$removeCSVFile = $True # TODO: modify me

# Mail settings
$to = "recipient@domain.com" # TODO: modify me
$subject = "Bitlocker Report" # TODO: modify me
$from = "noreply@domain.com" # TODO: modify me
$smtpServer = "mail.domain.com" # TODO: modify me

function SearchObjects($filter, $properties)
{
    $searcher = $Context.BindToObject("Adaxes://rootDSE")
    $searcher.SearchFilter = $filter
    $searcher.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.PageSize = 500
    $searcher.ReferralChasing = "ADS_CHASE_REFERRALS_NEVER"
    $searcher.SetPropertiesToLoad($properties)
    $searcher.VirtualRoot = $True
    
    try
    {
        # Execute search
		$searchResultIterator = $searcher.ExecuteSearch()
        $searchResults = $searchResultIterator.FetchAll()
        
        return ,$searchResults
    }
    finally
    {
        # Release resources
        if ($searchResultIterator){ $searchResultIterator.Dispose() }
    }
}

# Get all BitLoker objects
$bitlockerSearchResults = SearchObjects "(objectClass=msFVE-RecoveryInformation)" @("distinguishedName")
$computersWithBitlocker = New-Object "System.Collections.Generic.HashSet[System.String]"

foreach ($searchResult in $bitlockerSearchResults)
{
    $dn = New-Object "Softerra.Adaxes.Ldap.DN" $searchResult.Properties["distinguishedName"].Value
    [void]$computersWithBitlocker.Add($dn.Parent)
}

# Search all computers
$computersSearchResult = SearchObjects "(objectCategory=computer)" @("distinguishedName", "description", "operatingSystem")

$computersWithBitlockerRecords = New-Object "System.Collections.ArrayList"
$computersWithoutBitlockerRecords = New-Object "System.Collections.ArrayList"

foreach ($searchResult in $computersSearchResult)
{
    # Get computer info
    $computerName = $Context.GetDisplayNameFromAdsPath($searchResult.AdsPath)
    $description = $searchResult.Properties["description"].Value
    $operatingSystem = $searchResult.Properties["operatingSystem"].Value
    
    # Build record
    $recordProperties = [ordered]@{
        "Name" = $computerName;
        "Description" = $description;
        "Operating System" = $operatingSystem
    }
    $record = New-Object PSObject -Property $recordProperties
    
    $dn = $searchResult.Properties["distinguishedName"].Value
    if ($computersWithBitlocker.Contains($dn))
    {
        $computersWithBitlockerRecords.Add($record)
    }
    else
    {
        $computersWithoutBitlockerRecords.Add($record)
    }
}

$computersWithBitlockerRecords | Export-csv -NoTypeInformation -Path $computersWithBitlockerCsvFilePath
$computersWithoutBitlockerRecords | Export-csv -NoTypeInformation -Path $computersWithoutBitlockerCsvFilePath

# Send mail
Send-MailMessage -To $to -from $from -SmtpServer $smtpServer -Subject $subject -Body "BitLocker report" -Attachments @($computersWithBitlockerCsvFilePath, $computersWithoutBitlockerCsvFilePath)
 
if ($removeCSVFile)
{
    # Remove the file
    Remove-Item -Path $computersWithBitlockerCsvFilePath -Force
    Remove-Item -Path $computersWithoutBitlockerCsvFilePath -Force
}

Comments ( 2 )
avatar
Mark Daniel
Dec 04, 2019
This doesn't appear to work under 2019.2. Can this be changed to export to a CSV file?
avatar
Support
Dec 04, 2019

Hello Mark,

As per our check, the script works fine with Adaxes 2019.2. Most probably, the issue is related to Excel and not Adaxes or the script itself. We will add a version of the script that will create 2 CSV files for computers with Bitlocker installed/not installed.

avatar
Mark Daniel
Dec 18, 2019
Yep, it's due to Excel not being installed on the executing host. The CSV version works perfectly—thank you!
Leave a comment