Utilizing Datto RMM User-Defined Custom Fields
Table of Contents
INTRO
Greeting folks, Datto RMM is a powerful and fantastic tool for Systems Administrators. We can manage hundreds of computers and with the recent trend to move to domain-less networks it will surely be a tool of continued use in the future. I want to talk about the User-Defined Fields (UDFs) feature because it has made my life much easier.
While Datto RMM already gives us so much information about each endpoint, there was some information I wanted on the front-page of each device summary so I didn’t need to go digging through multiple tabs and also so I could export to Microsoft Excel.
THE COMPONENT STORE
The community component store has many options already available for you to add to your portal’s component store. Simply go through the list and add the ones you want. For example, you can have the device’s TPM status and Bitlocker Recovery Key shown. You can have Office and Windows Product Keys detected. Activation status, a Windows 11 compatibility check, backup product detection, and much more.
CONFIGURING THE UDF JOB
Under the Administrator account for your portal, go to Setup -> Account Settings -> User-Defined Fields.
This is where you will label the header for the value of data that will be in the field, but this is not where you will configure UDFs. Configuring them will be done under Jobs.
Create a new job called, “Managed IT [All] – Custom UDFs – Initial Audit” and for Job targets add the following:
- Default Device Filters (All Sites): All Windows Servers
- Default Device Filters (All Sites): All Windows Desktops
For a schedule set it for, “Once an initial audit has completed”. This means whenever a new device is added the job will run and add the UDFs.
You can also repeat the process with a job called, “Managed IT [All] – Custom UDFs – Schedule” where you can set a time each day that Datto RMM will run the UDF scripts for each device to keep the UDFs updated daily.
A screenshot of my configuration for the job is next to this section.
OUTPUT EXAMPLE
Here is also an example output of the job when it runs on an endpoint in New UI. I removed information that I would rather not share.
As you can see, I can get a lot of information on the summary page of an endpoint. I can tell if an endpoint has an SSD, if it’s using Bitlocker, how it’s activated, if it’s running UEFI and Secure Boot, and more.
I can have the Windows OEM Product Key stored in BIOS given to me as well as the Windows Product Key stored in the Registry and used to activate Windows.
I also have the Bitlocker Recovery Key. User Profile Folders, Local User Accounts, and Enabled Local Administrators at the end. All of these fields get stored into columns as well and can be exported to an Excel document for auditing purposes.
Also, having the information acts as a backup in-case you lose Bitlocker or Product Key information.
POWERSHELL SCRIPT
If you notice from my configuration, I have several components that start with Managed IT. You will not find these in the Component Store for download as they are my own custom scripts that I created.
The scripts run and then the output is placed in the registry under a certain User-Defined Field number of my choosing. This is how we can customize the fields we want when no component is available for it. Here is my script for querying Local Administrators below:
# Get Local Users
$Administrators = Get-LocalGroupMember -Group "Administrators" | Select-Object Name | Format-Table -HideTableHeaders
$AdministratorsList = $Administrators | Out-String
# Validate the UDF Variable
[int]$env:usrUDF = '22'
if ([int]$env:usrUDF -and [int]$env:usrUDF -match '^\d+$') {
# Validate the variable value is between 1 and 30
if ([int]$env:usrUDF -ge 1 -and [int]$env:usrUDF -le 30) {
New-ItemProperty -Path "HKLM:\SOFTWARE\CentraStage" -Name Custom$env:usrUDF -Value $AdministratorsList -Force | Out-Null
Write-Host "Value written to User-Defined Field $env:usrUDF`."
}
else {
Write-Host "User-Defined Field value must be an integer between 1 and 30."
}
} else {
Write-Host "User-Defined Field value invalid or not specified. Not writing results to the User-Defined Field."
}
The example is given so you can customize yourself with your own scripts.
COMPONENT UDF SCRIPTS
Below are the custom UDF scripts that I use to gather the details above. Simply add to the example script above before the “# Validate the UDF Variable” line and replace the UDF number with the one you desire. Then on line 12 replace with the correct variable in the script for output.
Managed IT – UDF-1 – Microsoft Office
# Get Microsoft Office Products Installed
$Microsoft32Bit = Get-ItemProperty HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | where{$_.DisplayName -LIKE 'Microsoft Office P*' -or $_.DisplayName -LIKE 'Microsoft Office H*' -or $_.DisplayName -LIKE 'Microsoft Office S*' -or $_.DisplayName -LIKE 'Microsoft Visio*' -or $_.DisplayName -LIKE 'Microsoft Lync*' -or $_.DisplayName -LIKE 'Microsoft P*' -or $_.DisplayName -LIKE 'Microsoft O*' -or $_.DisplayName -LIKE 'Microsoft Access*' -or $_.DisplayName -LIKE 'Microsoft Excel*' -or $_.DisplayName -LIKE 'Microsoft Word*' -or $_.DisplayName -LIKE 'Microsoft InfoPath*'} | Select-Object DisplayName, DisplayVersion | Format-Table -HideTableHeaders
$Microsoft64Bit = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* | where{$_.DisplayName -LIKE 'Microsoft Office P*' -or $_.DisplayName -LIKE 'Microsoft Office H*' -or $_.DisplayName -LIKE 'Microsoft Office S*' -or $_.DisplayName -LIKE 'Microsoft Visio*' -or $_.DisplayName -LIKE 'Microsoft Lync*' -or $_.DisplayName -LIKE 'Microsoft P*' -or $_.DisplayName -LIKE 'Microsoft O*' -or $_.DisplayName -LIKE 'Microsoft Access*' -or $_.DisplayName -LIKE 'Microsoft Excel*' -or $_.DisplayName -LIKE 'Microsoft Word*' -or $_.DisplayName -LIKE 'Microsoft InfoPath*'} | Select-Object DisplayName, DisplayVersion | Format-Table -HideTableHeaders
$Microsoft = $Microsoft32Bit, $Microsoft64Bit | Out-String
Managed IT – UDF-6 – Microsoft 365
# Get Microsoft Office 365 Products Installed
$Microsoft32Bit = Get-ItemProperty HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | where{$_.DisplayName -like 'Microsoft 365*'} | Select-Object DisplayName, DisplayVersion | Format-Table -HideTableHeaders
$Microsoft64Bit = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* | where{$_.DisplayName -like 'Microsoft 365*'} | Select-Object DisplayName, DisplayVersion | Format-Table -HideTableHeaders
$Microsoft365= $Microsoft32Bit, $Microsoft64Bit| Out-String
Managed IT – UDF-7 – Microsoft Office Keys
# Get Microsoft Office Product Keys:
function Search-RegistryKeyValues {
param(
[string]$Path,
[string]$valueName
)
Get-ChildItem $Path -recurse -ea SilentlyContinue |
% {
if ((Get-ItemProperty -Path $_.PsPath -ea SilentlyContinue) -match $valueName)
{
$_.PsPath
}
}
}
# Find registry key that has value: "digitalproductid"
# 32-Bit Versions:
$Key = Search-RegistryKeyValues "HKLM:\SOFTWARE\Microsoft\Office" "digitalproductid"
if ($Key -eq $null) {
# 64-Bit Versions:
$Key = Search-RegistryKeyValues "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Office" "digitalproductid"
if ($Key -eq $null) {Write-Host "Microsoft Office is NOT Installed.";break}
}
$ValueData = (Get-ItemProperty $Key).digitalproductid[52..66]
# Decrypt Base24 Encoded Binary Data:
$ProductKey = ""
$Chars = "BCDFGHJKMPQRTVWXY2346789"
for ($i = 24; $i -ge 0; $i--) {
$r = 0
for ($j = 14; $j -ge 0; $j--) {
$r = ($r * 256) -bxor $ValueData[$j]
$ValueData[$j] = [math]::Truncate($r / 24)
$r = $r % 24
}
$ProductKey = $Chars[$r] + $ProductKey
if (($i % 5) -eq 0 -and $i -ne 0) {
$ProductKey = "-" + $ProductKey
}
}
$MSOfficeKey= $ProductKey | Out-String
Managed IT – UDF-12 – Hardware Other
# Get Hardware Details
$Hardware = Get-ComputerInfo -Property BiosFirmwareType, CsAdminPasswordStatus, OsInstallDate | Format-List
$HardwareDetails = $Hardware | Out-String
Managed IT – UDF-13 – Secure Boot Status
# Get Secure Boot Status
$Status= Confirm-SecureBootUEFI | Format-List
$SecureBootDetails= $Status | Out-String
Managed IT – UDF-21 – Local User Accounts
# Get Local Users
$LocalUsers = Get-LocalUser | where{$_.Enabled -eq 'True'} | Select-Object Name, PasswordRequired, PasswordExpires, PasswordLastSet, LastLogon | Format-List
$List= $LocalUsers | Out-String
Managed IT – UDF-22 – All Local Administrators
# Get All Local Administrators
$AllAdministrators = Get-LocalGroupMember Administrators | Select-Object Name, PrincipalSource | Format-Table -HideTableHeaders
$AllAdministratorsList = $Administrators | Out-String
Managed IT – UDF-23 – Enabled Local Administrators
# Get Enabled Local Administrators
$EnabledAdministrators = Get-LocalGroupMember Administrators | Where-Object { (Get-LocalUser $_.SID -EA 0).Enabled } | Select-Object Name, PrincipalSource | Format-Table -HideTableHeaders
$EnabledAdministratorsList = $EnabledAdministrators | Out-String
Managed IT – UDF-25 – Intermedia
# Get Intermedia Products Installed
$Intermedia32Bit = Get-ItemProperty HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | where{$_.Publisher -like 'Intermedia*'} | Select-Object DisplayName, DisplayVersion | Format-Table -HideTableHeaders
$Intermedia64Bit = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | where{$_.Publisher -like 'Intermedia*'} | Select-Object DisplayName, DisplayVersion | Format-Table -HideTableHeaders
$Intermedia = $Intermedia32Bit, $Intermedia64Bit | Out-String
Managed IT – UDF-26 – Zyxel
# Get Zyxel Products Installed
$Zyxel32Bit = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | where{$_.Publisher -like 'Zyxel*'} | Select-Object DisplayName, DisplayVersion | Format-Table -HideTableHeaders
$Zyxel64Bit = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* | where{$_.Publisher -like 'Zyxel*'} | Select-Object DisplayName, DisplayVersion | Format-Table -HideTableHeaders
$Zyxel = $Zyxel32Bit, $Zyxel64Bit | Out-String
Managed IT – UDF-27 – Alibi
# Get Alibi Products Installed
$Alibi32Bit = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | where{$_.Publisher -like 'Observint Technologies*'} | Select-Object DisplayName, DisplayVersion | Format-Table -HideTableHeaders
$Alibi64Bit = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* | where{$_.Publisher -like 'Observint Technologies*'} | Select-Object DisplayName, DisplayVersion | Format-Table -HideTableHeaders
$Alibi = $Alibi32Bit, $Alibi64Bit | Out-String
Managed IT – UDF-28 – Solidworks Serials
# Get Solidworks Serial Numbers
$SolidworksMain = Get-ItemProperty -Path "HKLM:\SOFTWARE\SolidWorks\Licenses\Serial Numbers" -Name "SolidWorks" | Select-Object Solidworks | Format-Table
$SolidworksVisualize = Get-ItemProperty -Path "HKLM:\SOFTWARE\SolidWorks\Licenses\Serial Numbers" -Name "Visualize" | Select-Object Visualize | Format-Table
$SolidworksSerials = $SolidworksMain, $SolidworksVisualize | Out-String
CONCLUSION
Well, there you have it! Hopefully this can save you some time in auditing. I would create a second duplicate job called, “Managed IT [All] – Custom UDFs – Schedule” that runs every day at around 11:00 AM as I find most computers are on at that time, this way the information stays updated after the initial audit. Stay tuned for more!
My name is Dex Sandel, author at WinReflection, a blog which aims to help others on various IT and Christian related subjects. DON’T TREAD ON ME! The best is yet to come, and nothing can stop what’s coming!
You all have a greater destiny in Christ, should you choose to ‘follow’ Him, not just believe. Many of you feel lost, without drive, and lack a greater purpose in your life causing depression, sadness, anxiety, and loneliness. Working your 9-5 job isn’t your primary purpose. So, then what is? That’s for you to discover, but hopefully I can provide some new unlocks along your path.
What will ‘you’ do, and what will your destiny be?
John 3:16: For God so loved the world that he gave his one and only Son, that whoever believes in him shall not perish but have eternal life.
Hi,
I found the article really useful. Thanks for placing it.
Is there any way to read the value of a User defined field and based on it modify another User defined field?
example: I have the purchase date of laptops and desktops in a User defined field. I created another field named “Marked for replacement”.
I want to use this purchase date to calculate if device needs to be replaced already or not, and if that’s the case modify the field “Marked for replacement”. Life could be different for laptops, let’s say 3 years, while for desktops it can be 4 years. Therefore I also need to check the “Device Type” field to do the calculation.
I think it can be done, but I didn’t find the way to obtain the data from those user defined fields from an script.
Can you help me or provide me some guidance?
Thanks a lot!
Hi Carles, I am glad you found the post helpful and thanks for letting me know!
The UDFs are just values placed in the registry and then Datto RMM, whenever it audits the device it looks at those values and places them into the Device Summary area. You would need to create a PowerShell script to make the edits you’re looking to have done, and maybe run a schedule. I think what you’re doing can be done and I would recommend using ChatGPT for help.
I would simply ask ChatGPT to give you a template to read a device’s purchase date value from the registry UDF key location and then have logic to determine the age of the device and if said age meets criteria then edit the “Market for replacement” UDF key in the registry.
Datto RMM will then see that value on the device’s next audit and should be visible to you.