$cs.CustomInventory_SetValue
Description
Section titled “Description”Writes a custom inventory value for CapaOne, optionally with a unit such as bytes or date. Creates the category and instance if they don’t exist. Windows-only.
Custom inventory has three levels, stored in the 64-bit registry as HKLM\SOFTWARE\CapaSystems\CapaOneAgent\CustomInventory\<Category>\<Instance>\<Name>:
- A category groups related data, for example
OfficeorInstalled Applications. - An instance is one item in the category, for example one application. A category with only one item uses the instance
default. - A name is one value of the instance, for example
Version.
Each instance also has a Last Updated value with the date and time of its last change. The function updates it only when the value is new or different from the stored value, so you can write the same values on every run.
Category, instance and value names can only contain:
- Letters, also letters such as
æ,øandå - Digits
- Spaces
- Hyphens (
-)
Other characters, such as _, ., $, \, + or parentheses, aren’t allowed, because CapaOne uses the names as field names. A custom inventory function rejects a name with other characters: it writes the name, the characters that aren’t allowed and these rules to the package log, and throws an error. For example, Notepad++, Office 2.0 and Install_Date aren’t valid names, but Notepad, Office 2-0 and Install Date are.
To use a name from elsewhere, for example the name of an installed application, replace the other characters first:
$instance = $appName -replace '[^\p{L}\p{Nd} -]', '-' # 'Notepad++' becomes 'Notepad--'The CapaOne agent skips a category, instance or value whose name breaks these rules, for example one created by hand in Registry Editor, and writes a warning in its log.
Syntax
Section titled “Syntax”$cs.CustomInventory_SetValue(string category, string instance, string name, object value, string unit = “”)
Parameters
Section titled “Parameters”category (String)
Section titled “category (String)”Name of the category, for example Office. Leading and trailing spaces are removed. Can’t be empty or longer than 255 characters, and can only contain letters, digits, spaces and -: see Names. Names aren’t case-sensitive: Office and office are the same category.
instance (String)
Section titled “instance (String)”Name of the instance in the category, for example the name of an application. Pass "" for a category with only one instance, which then uses the instance default. Same rules as category.
name (String)
Section titled “name (String)”Name of the value, for example City. Can’t be empty, and can only contain letters, digits, spaces and -: see Names. The names Instance and Last Updated are reserved: the CapaOne agent adds the instance name as Instance, and Last Updated is maintained for you.
value (Object)
Section titled “value (Object)”The value. Its type decides how it’s stored, and how CapaOne shows it:
| You pass | Stored in the registry as |
|---|---|
A string, for example 'Copenhagen' |
REG_SZ: Copenhagen |
An integer, for example 3 |
REG_DWORD, or REG_QWORD for an integer larger than 2,147,483,647 |
$true or $false |
REG_SZ: {"value":true} |
A decimal number, for example 43.5 |
REG_SZ: {"value":43.5} |
An array of strings, for example @('Development', 'Support') |
REG_MULTI_SZ. CapaOne shows it as one text: Development, Support |
A date and time, for example (Get-Date) |
REG_SZ: {"unit":"date","value":"2026-10-20 08:20:17Z"} |
Any value with a unit |
REG_SZ, for example {"unit":"bytes","value":5242880} |
A date is always stored with the unit date, in UTC and to the whole second. $null isn’t allowed — to remove a value, use $cs.CustomInventory_RemoveValue. A string in the format {"value":...} isn’t allowed either, because it would be read as a typed value.
unit (String)
Section titled “unit (String)”Optional. The unit of the value. CapaOne uses it to show the value, for example 5242880 with the unit bytes as 5 MB. Units are case-sensitive. Valid units:
| Unit | What the value is | Value to pass | CapaOne shows it as |
|---|---|---|---|
percent |
A percentage, from 0 to 100 | Number | 99.5 % |
Hz |
A frequency in hertz | Number | Scaled by 1,000, for example 2 GHz |
cm |
A length in centimeters | Number | 61 cm |
inch |
A length in inches | Number | 24 ″ |
bytes |
A size in bytes | Number | Scaled by 1,024, for example 5 MB |
Bps |
Bytes per second | Number | Scaled by 1,024, for example 12 MBps |
bit |
A number of bits | Number | 64 bit |
bps |
Bits per second | Number | Scaled by 1,000, for example 100 Mbps |
s |
A duration in seconds | Number | 12 s |
ms |
A duration in milliseconds | Number | Scaled by 1,000, for example 1.5 s |
V |
A voltage in volts | Number | 12 V |
amp |
A current in amperes | Number | 2 amp |
mAh |
A battery capacity in milliampere-hours | Number | 5000 mAh |
date |
A date and time | Date, see below | The date and time |
locale |
A language, for example da-DK |
Text | The language name, for example Danish (Denmark) |
url |
A web address | Text | A link |
A number can also be a string with a number in it, with a period as the decimal separator: '5242880' or '43.5'. A string with other characters, such as '12 MB', isn’t a number.
For the unit date, pass one of these:
- A
DateTime, for example(Get-Date). - Unix time as a number: seconds (9 or 10 digits) or milliseconds (12 or 13 digits).
- A date as text: ISO 8601, for example
2026-10-17T11:06:43+02:00or2026-10-17 09:06:43Z, a WMI date such as20260104224730.000000+060, or a PowerShell 5.1 JSON date such as/Date(1760608800000)/. - A date as text in the device’s own date format, or in a common US or European format.
A date without a time zone is read as the device’s local time. The order of day and month in a date like 07-06-2026 depends on the device’s date format, so use a DateTime or ISO 8601 when you can.
Return value
Section titled “Return value”None. Throws an error if an argument isn’t valid, for example a name with a character that isn’t allowed, an unknown unit or a value that doesn’t fit its unit. In PowerShell, the reason is in $_.Exception.InnerException.Message.
Example
Section titled “Example”A category with one instance. The instance "" becomes default:
$cs.CustomInventory_SetValue('Office', '', 'City', 'Copenhagen')$cs.CustomInventory_SetValue('Office', '', 'Floor', 3)$cs.CustomInventory_SetValue('Office', '', 'Has Parking', $true)$cs.CustomInventory_SetValue('Office', '', 'Language', 'da-DK', 'locale')A category with one instance per installed application, with units:
$cs.CustomInventory_SetValue('Installed Applications', '7-Zip', 'Version', '24.08')$cs.CustomInventory_SetValue('Installed Applications', '7-Zip', 'Installed On', (Get-Date))$cs.CustomInventory_SetValue('Installed Applications', '7-Zip', 'Installer Size', 1599488, 'bytes')$cs.CustomInventory_SetValue('Installed Applications', '7-Zip', 'Website', 'https://www.7-zip.org', 'url')Writing a value that may not fit its unit, and logging why it wasn’t written:
try { $cs.CustomInventory_SetValue('Installed Applications', 'Firefox', 'Installer Size', $sizeText, 'bytes')} catch { $cs.Job_WriteLog("Installer Size not written: $($_.Exception.InnerException.Message)")}Moving from CMS_AddCustomInventory
Section titled “Moving from CMS_AddCustomInventory”CapaInstaller’s own custom inventory, CMS_AddCustomInventory, has two levels: a category and an entry. To write the same data as CapaOne custom inventory, use the category as it is, the instance "", and the entry as the name:
| CMS_AddCustomInventory | $cs.CustomInventory_SetValue |
|---|---|
category |
category |
| — | instance: "", the instance default |
entry |
name |
value with the valuetype S |
value as a string |
value with the valuetype I |
value as an integer |
value with the valuetype T, seconds since 1970 |
value as the same number, with the unit date |
A CapaInstaller category or entry may have a name with characters that CapaOne doesn’t allow, such as _, . or parentheses. Replace them, see Names: for example, write the entry Version (x64) as Version x64.
To remove an entry, use $cs.CustomInventory_RemoveValue in place of CMS_RemoveCustomInventory.
During the move, a package can write both. Afterwards, open HKLM\SOFTWARE\CapaSystems\CapaOneAgent\CustomInventory in Registry Editor to check that the data matches your CapaInstaller custom inventory:
# CapaInstaller custom inventoryCMS_AddCustomInventory -category 'Bitlocker' -entry 'TPM Chip - Enabled' -value 'True' -valuetype 'S'CMS_AddCustomInventory -category 'Bitlocker' -entry 'TPM Chip - Manufactured' -value '1694973146' -valuetype 'T'
# The same entries as CapaOne custom inventory$cs.CustomInventory_SetValue('Bitlocker', '', 'TPM Chip - Enabled', 'True')$cs.CustomInventory_SetValue('Bitlocker', '', 'TPM Chip - Manufactured', 1694973146, 'date')Related functions
Section titled “Related functions”$cs.CustomInventory_GetValue $cs.CustomInventory_RemoveValue $cs.CustomInventory_GetInstance CMS_AddCustomInventory