Use API to Determine if a Certain Software is Installed on All Devices

  • 7 December 2020
  • 11 replies
  • 1319 views

Userlevel 5

This was originally written for a customer that wanted to see if every system in their environment had Sophos Antivirus installed or not - and what version if they did.


$apiKey = 'YOUR_API_KEY' - in your console, go to Settings->API and select the API key. Note that the API key is per admin user, so you and another admin in your console will have different API keys.


$orgID = 'YOUR_ORG_ID' - put in your Org ID which can be found by looking at the URL on the dashboard and selecting the value after the “?o=”: [https://console.automox.com/dashboard?o=1234]. In this example the Org ID is 1234.


$appInstalled = 'APPLICATION' - put the name of the application as it is listed in the software section of a device’s page that has it installed.


$filepath - The save location and file name for the .csv file generated.


Here’s a sample output checking for Microsoft Edge Chromium:

2020-12-07 14_12_24-AppInstalled - Google Sheets


$apiKey = 'YOUR_API_KEY'
$orgID = 'YOUR_ORG_ID'

$appInstalled = 'Microsoft Edge'
$filepath = 'C:\Temp\AppInstalled.csv'

Set-Content $filepath -Value "Computer,Name,Version"

$apiInstance = 'https://console.automox.com/api/'
$apiTable = 'servers'
$orgAndKey = "?o=$orgID&api_key=$apiKey"

# Put components together
$getURI = $apiInstance + $apiTable + $orgAndKey

# Get the json body of the Web Request
$jsonReturn = (Invoke-WebRequest -UseBasicParsing -Method Get -Uri $getURI).Content

# Convert to object with manipulatable properties/values
$servers = $jsonReturn | ConvertFrom-Json
$servers = $servers | Sort-Object name

# Check each server for software
foreach ($server in $servers) {

$serverID = $server.id
$serverName = $server.name

$orgAndKey = "/$serverID/packages?o=$orgID"

# Put components together
$getURI = $apiInstance + $apiTable + $orgAndKey

$headers = @{ "Authorization" = "Bearer $apiKey" }
$response = (Invoke-WebRequest -Method Get -Uri $getURI -Headers $headers).Content | ConvertFrom-Json

$installed = $response | Where-Object {$_.installed -EQ $true -and $_.display_name -EQ $appInstalled}

$output = $serverName + "," + $installed.display_name + "," + $installed.version
$output | Add-Content -Path $filepath

}

11 replies

Hello there,


I’m following all the steps exactly and I’m getting the report generated to the desirable path but there is no info for the application and its version in it for all 500 devices. I got only the names of the devices. I have tried with several application names taken from the software section of the device page.

Any ideas what I’m doing wrong?

Thank you in advance

Userlevel 2
Badge

How do I remove the limit of returning 500 systems. I have closer to 1200 that I need to query…

There’s not a way to remove the limit, but you can work with it by including some pagination handling in the code. See Use API to Pull Software Inventory for Every Computer in an Organization for an example of a script where that is being used.

Userlevel 3
Badge

I tweaked the code above to deal with pagination and pull all the devices. This should make it easier for folks. 

 

$apiKey = 'Your API Key'
$orgID = 'Your ORG ID'
$appInstalled = 'Adobe Acrobat*'
$filepath = 'C:\Temp\AppInstalled.csv'

Set-Content $filepath -Value "Computer,Name,Version"
$apiInstance = 'https://console.automox.com/api/'
$apiTable = 'servers'

####
#This will pull all devices and not just the first 500

$pageindex = 0
$Items = New-Object -TypeName "System.Collections.ArrayList"
$headers = @{ "Authorization" = "Bearer $apiKey" }

Do {
$url = "https://console.automox.com/api/servers?o=$orgID&page=$pageindex"
$Devices =(Invoke-restmethod -Method Get -Uri $url -Headers $headers)
foreach ($Item in $Devices) {$Items += $Item}
$pageindex++
}
Until ($Devices.count -lt 500)

####
# Check each server for software
foreach ($server in $Items) {
$serverID = $server.id
$serverName = $server.name
$orgAndKey = "/$serverID/packages?o=$orgID"
# Put components together
$getURI = $apiInstance + $apiTable + $orgAndKey
$headers = @{ "Authorization" = "Bearer $apiKey" }
$response = (Invoke-WebRequest -Method Get -Uri $getURI -Headers $headers).Content | ConvertFrom-Json
$installed = $response | Where-Object {$_.installed -EQ $true -and $_.display_name -Like $appInstalled}
$output = $serverName + "," + $installed.display_name + "," + $installed.version
$output | Add-Content -Path $filepath
}

 

Badge

will the pagination work for 2800+ devices?

Badge

I tweaked the code above to deal with pagination and pull all the devices. This should make it easier for folks. 

 

$apiKey = 'Your API Key'
$orgID = 'Your ORG ID'
$appInstalled = 'Adobe Acrobat*'
$filepath = 'C:\Temp\AppInstalled.csv'

Set-Content $filepath -Value "Computer,Name,Version"
$apiInstance = 'https://console.automox.com/api/'
$apiTable = 'servers'

####
#This will pull all devices and not just the first 500

$pageindex = 0
$Items = New-Object -TypeName "System.Collections.ArrayList"
$headers = @{ "Authorization" = "Bearer $apiKey" }

Do {
$url = "https://console.automox.com/api/servers?o=$orgID&page=$pageindex"
$Devices =(Invoke-restmethod -Method Get -Uri $url -Headers $headers)
foreach ($Item in $Devices) {$Items += $Item}
$pageindex++
}
Until ($Devices.count -lt 500)

####
# Check each server for software
foreach ($server in $Items) {
$serverID = $server.id
$serverName = $server.name
$orgAndKey = "/$serverID/packages?o=$orgID"
# Put components together
$getURI = $apiInstance + $apiTable + $orgAndKey
$headers = @{ "Authorization" = "Bearer $apiKey" }
$response = (Invoke-WebRequest -Method Get -Uri $getURI -Headers $headers).Content | ConvertFrom-Json
$installed = $response | Where-Object {$_.installed -EQ $true -and $_.display_name -Like $appInstalled}
$output = $serverName + "," + $installed.display_name + "," + $installed.version
$output | Add-Content -Path $filepath
}

 

How do I run this script? Can I save it as Powershell and run through powershell command? Or do I need to use API program like POSTMAN and run it? Sorry for the novice question!

Userlevel 3
Badge

Yes, we have about 3,500 devices and it works fine. It will keep pulling results of 500 until it gets to the last one with less than 500 and exit the loop after that batch. It takes a while to pull that many results, but it works. I have some other scripts that outputs $items and feeds $items back in to the script as a parameter for next time its ran so you only have to do the heavy lifting the first time. Here is an example of how to do that from another script. 

####Process Params
#### $device = "devicename"
#### $key = "apikey"
#### $policy = "policy1", "policy2.."
#### Example First run: $items = .\RunPolicyonDevN.ps1 -DeviceName $device -Policylist $policy -apiKey $key
#### Example Subsequent runs: $items = .\RunPolicyonDevN.ps1 -DeviceName $device -Policylist $policy -apiKey $key -Items $items
param ([String]$DeviceName, [String]$apiKey, [String[]]$Policylist, [System.Collections.ArrayList]$Items)



#### List of software to install as base image
#$Policylist = "Apply Dell Driver Updates","Install Sophos", "Install Mozilla Firefox", "Install Google Chrome", "Install Adobe Reader", "Install EgnyteWebEdit", "Install Java"
#### Org ID Settings (put your Org ID here)
$orgID = 'YourID'


###### Get Policies
$headers = @{ "Authorization" = "Bearer $apiKey" }
$url = "https://console.automox.com/api/policies?o=$orgID"

$AutomoxPolicies = (Invoke-RestMethod -Method Get -Uri $url -Headers $headers)

#if $items is not included as a parameter it will pull all devices and output it to $items
#next time you can run the script and include $items saving time.

If (-not($Items)){
###### Get Devices
$pageindex = 0
$Items = New-Object -TypeName "System.Collections.ArrayList"
$headers = @{ "Authorization" = "Bearer $apiKey" }

Do {
$url = "https://console.automox.com/api/servers?o=$orgID&page=$pageindex"
$Devices =(Invoke-restmethod -Method Get -Uri $url -Headers $headers)
foreach ($Item in $Devices) {$Items += $Item}
$pageindex++
}
Until ($Devices.count -lt 500)
###
}

########Install Policies
$serverID = $Items | where {$_.name -match $DeviceName} | Select -ExpandProperty Id
Write-Host $serverID


$policies = $AutomoxPolicies | where {$_.name -in $Policylist} | Select -ExpandProperty Id


foreach ($policy in $policies) {

$headers = @{ "Authorization" = "Bearer $apiKey" }

$url = "https://console.automox.com/api/policies/$policy/action?o=$orgID&action=remediateServer&serverId=$serverID"

Invoke-WebRequest -Method POST -Uri $url -Headers $headers
Write-Host $url
}
Write-Host "Policy Deploying, check machine in Automox for status"
Return $Items

 

 

Userlevel 3
Badge

How do I run this script? Can I save it as Powershell and run through powershell command? Or do I need to use API program like POSTMAN and run it? Sorry for the novice question!

 

You save the text to a .ps1 file, or you can paste it directly into powershell. You do not need POSTMAN. Make sure to update the variables to your org id and your api key and such. Careful running scripts that you dont fully understand. People make mistakes, typos and such and you want to be sure you know exactly what they are doing and how they are doing it. I go through each, line by line, and find out what its doing before executing it. I know its hard to do when you are just starting out and not quite sure what everything does, but highlight what you don't understand and do some google searches on the syntax to learn more about those sections. Or feel free to ask questions. I am always happy to help people learn and many many people have helped me learn and understand over the years. Learning powershell is a great way to get the most out of Automox. You can build some amazing worklets that do just about anything you can think of. 

Badge

How do I run this script? Can I save it as Powershell and run through powershell command? Or do I need to use API program like POSTMAN and run it? Sorry for the novice question!

 

You save the text to a .ps1 file, or you can paste it directly into powershell. You do not need POSTMAN. Make sure to update the variables to your org id and your api key and such. Careful running scripts that you dont fully understand. People make mistakes, typos and such and you want to be sure you know exactly what they are doing and how they are doing it. I go through each, line by line, and find out what its doing before executing it. I know its hard to do when you are just starting out and not quite sure what everything does, but highlight what you don't understand and do some google searches on the syntax to learn more about those sections. Or feel free to ask questions. I am always happy to help people learn and many many people have helped me learn and understand over the years. Learning powershell is a great way to get the most out of Automox. You can build some amazing worklets that do just about anything you can think of. 

Is there a way I can run this exact script to find a Java based application which resides in C:\ drive?  We have a script which pulls information on a single machine but wanted to run it on our AM environment.  The script in this post looks like does it for Add/Remove programs location.  But we have a Java based application which resides in C: drive and we need the file Version as well as the output to a CSV file.

Get-Childitem -Path 'C:\' -Filter 'acslaunch_win-64.exe' -Recurse -Force -ErrorAction SilentlyContinue | ForEach-Object {


[PsCustomObject]@{

'Path' = $_.FullName

'Version' = (Get-Command java | Select-Object -ExpandProperty Version)

'ExeVersion' = $_.VersionInfo.ProductVersion

'User' = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name

}

}| Export-Csv -path "C:\temp\test_$($env:computername).csv" -NoTypeInformation -Force

 

Userlevel 3
Badge

Deepan.bala, I would not normally do what you are trying to do using the automox api. You can put your script into a worklet and run it on as many computers as you like. Instead of Export-CSV at the end, I would put the output in a variable and do a write-host $output at the end. The output you want will show up in the Console\Activity Reports. You can export it from there if you want to create a report of all the devices. So something like this in a worklet would be better, I think. 

$output = Get-Childitem -Path 'C:\' -Filter 'acslaunch_win-64.exe' -Recurse -Force -ErrorAction SilentlyContinue | ForEach-Object {


[PsCustomObject]@{

'Path' = $_.FullName

'Version' = (Get-Command java | Select-Object -ExpandProperty Version)

'ExeVersion' = $_.VersionInfo.ProductVersion

'User' = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name

}

}
Write-Host $output

Sorry for the late response, been swamped at work. 

I have the script deployed and when I search for Microsoft Edge, I get something back.  If I search for any other applications I get a blank excel.  Any ideas what could be causing that?

Reply