# Windows sensors

One script per topic, run by `sysinfo_client.ps1` as `powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File <sensor> "<dir>\"`. The contract (exit codes, tab-separated STDOUT lines) is the one in `unix/sensors/Documentation/README.md`; the keys are listed in `Documentation/Spec.md` section 7.6.

| Sensor | Emits |
|---|---|
| `windows_identity.ps1` | `identity.*` (Spec 1.3): DMI uuid and serial, status, manufacturer, product, `machine_id`, `virtualization`, effective `uuid` and `serial` with their sources |
| `windows_system.ps1` | `system.last_boot` (UTC epoch), `system.uptime`, `operatingsystem.*` |
| `windows_storage.ps1` | `diskinfo.<letter>.fstype/size/used/mount` (sizes in KiB, as Unix `df`) |
| `windows_network.ps1` | `network.<adapter>.address/netmask/ip6address/ip6networkbits/mac/mtu` |
| `windows_software.ps1` | `software.<name>.version/description` from the registry Uninstall keys (both views; never `Win32_Product`) |

Exit codes: 0 ok, 1 not Windows, 2 a required cmdlet or CIM class is missing, 4 failure (one-line reason on STDERR).

## Writing a sensor

Start with the two lines below, then put the work inside `Invoke-SysinfoSensor`, which turns an uncaught error into exit 4. Emit facts only with `Write-SysinfoFact` (it removes tabs and newlines from values and writes UTF-8 without a BOM); never `Write-Output` or `Write-Host`.

    Import-Module ([IO.Path]::Combine($PSScriptRoot, '..', 'lib', 'SysinfoSensor.psm1'))
    Test-SysinfoWindows
    Invoke-SysinfoSensor {
       Write-SysinfoFact -Path @('category', 'key') -Value $value
    }

A sensor file must be pure ASCII, must work on Windows PowerShell 5.1, and the sensor directory and `..\lib` must be writable only by Administrators and SYSTEM, or the client refuses to run it.
