Ivanti EPM vs Active Directory using PowerShell

  • by

Endpoint Manager’s reporting leaves much to be desired – it is clunky and unintuitive.  The first thing I did in our environment after moving into my new role was to ensure 100% device enrollment. After a bit of researching, I found Endpoint Manager’s API called MBSDK.

I was then able to find KB with PowerShell syntax on the Ivanti community forums. With these examples in hand, I was able to get authenticated to the Endpoint Manager and even execute a query. I confirmed I was able to display the query data in PowerShell and then went on to create a query with a broad qualifier, e.g., all computers with the OS name LIKE ‘windows”. This query would list all windows PCs within our Endpoint Manager environment. The next step was to get the full distinguished name of the OU I wanted to compare against, e.g., ‘computers’ in the contoso.com domain. Our last step was to generate a list of computers that were not in Endpoint Manager but were in Active Directory and email the report.

Our Example:

  • Endpoint Manager Query Setup: All computers with OS name LIKE ‘windows’
  • Active Directory Setup: All computer objects within ‘ou=computers,DC=contoso,dc=com’

Note: Depending on how often you want to report. You may want to set up a dedicated service account and keep permissions to a minimum. Then you can leverage this service account to run reports on a scheduled interval via scheduled tasks.

Example script:

# Load Modules
Import-Module ActiveDirectory

$from = "[email protected]"
$to = "[email protected]"
$cc = "[email protected]"
$subject = (Get-Date).ToString("%d-MMMM-yyyy") + " - Active Directory vs Endpoint Manager"
$smtpServer = "mailserver.contoso.com"

# Define HTML Report Header Style
$header = @"
<style>
body { font-size:12px; font-family:Verdana, Geneva, sans-serif;}
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #e5efff;}
TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
tr:nth-child(even) {background: #ededed}
tr:nth-child(odd) {background: #FFF}
</style>
"@

# Get ALL AD Computers and Export
$adData = get-adcomputer -Filter * -searchbase "OU=computers,DC=contoso,DC=com" | 
Select-Object @{ Name = "Device Name"; Expression = { $_. "Name" } } | Sort-Object 'Device Name' -Unique

# Connect to Endpoint Manager and Export
$ldws = New-WebServiceProxy -Uri 'https://epm.contoso.com/MBSDKService/MsgSDK.asmx?WSDL' -UseDefaultCredential
$ldws.ResolveScopeRights() | Out-Null

# Query in Endpoint Manager will just list all workstations in the enviorment.
$ldList = $ldws.RunQuery("All_Windows_Devices") 

# Create Hashtables
$ldTable = @{}
$adTable = @{}

# Varibles
$missingPCs = @()

# Process datasets and add to hashtable
$ldList.Tables[0].Rows | ForEach-Object { $ldTable[$_.'Device Name'] = $_.Data }
$adData | ForEach-Object { $adTable[$_.'Device Name'] = $_.Data }

# Compare hashtables
foreach ($pc in $adTable.Keys) {
    if ($ldTable.ContainsKey($pc) -eq $false) {
        $item = New-Object PSObject
        $item | Add-Member -type NoteProperty -Name 'Device Name' -Value $pc
        $missingPCs += $item
    }
}

# Print final report to console
Write-Host ""
Write-Host -ForegroundColor DarkMagenta 'Missing Devices:'
$missingPCs | Sort-Object 'Device Name' | Format-Table -HideTableHeaders
Write-Host ""

if ($missingPCs) {
    # Generate Report
    $HTMLReport = $missingPCs | Sort-Object 'Device Name' | ConvertTo-Html -property 'Device Name' -Head $Header -pre "<h1>Active Directory vs Endpoint Manager</h1><p><b>Generated:</b> $(get-date)<br /><b>Total Records Processed:</b> $($missingPCs | Measure | Select-Object Count | ft -HideTableHeaders | Out-String)</p> <P>PCs on this list either: Need to be removed from Active Directory or added to Endpoint Manager immediately"

    # Send Email
    Send-MailMessage -To $to -Cc $cc -From $from -SmtpServer $smtpServer -Subject $subject-Body ($HTMLReport | Out-String) -BodyAsHtml
}