PowerShell Scanner
The PowerShell scanner in PDQ Connect allows you to collect custom inventory data from devices by running PowerShell scripts and storing the results in a structured, searchable format. This enables advanced inventory scenarios, custom reporting, and dynamic targeting using data that isn’t available through built‑in scanners.
This article is divided into two parts:
- Part 1 explains how to create, configure, and use a PowerShell scanner.
- Part 2 provides a high‑level overview of how PowerShell scanners work and includes an optional wrapper for advanced troubleshooting.
Part 1: Creating a PowerShell scanner
To create a new PowerShell scanner:
- Click Scanners in the left navigation pane.
- Click Create Scanner in the top‑right corner.
- Give the scanner a descriptive name.
- From the Type dropdown, select PowerShell.
This opens the PowerShell scanner configuration page.
Add Your PowerShell Script
The Script section defines the PowerShell code that runs on each device.
You can:
-
Import a
.ps1file, or - Paste the script directly into the editor.
The script should focus solely on collecting data and returning it in a format PDQ Connect can process.
Note: Each PowerShell scanner returns up to 100 rows and 36 columns per device. If a script exceeds either limit, PDQ Connect silently truncates the results once the limit is reached.
Script Output Requirements
PowerShell scanners process the PowerShell object stream, not console output.
To be compatible with PDQ Connect, your script must output structured PowerShell objects (such as PSCustomObject) and nothing else.
✅ Correct output
[PSCustomObject]@{
AntivirusEnabled = $true
AntispywareEnabled = "Antispyware is enabled"
Timestamp = Get-Date
}
Write-Host "Antivirus is enabled" Write-Output "Antispyware is enabled" Get-Date
Avoid Output‑Formatting Cmdlets
Do not use output‑formatting or console‑only cmdlets in PowerShell scanners, including:
Write-HostFormat-TableFormat-ListOut-String
These cmdlets convert structured objects into display‑only text intended for interactive PowerShell sessions. Once converted, the original object properties are no longer available for PDQ Connect to consume.
Best practice
Return raw objects only. PDQ Connect handles formatting and presentation automatically.
Do not mix text output and objects
If a script outputs both plain text and structured objects, PDQ Connect cannot reliably process the results.
Any text‑based output (including Write-Host or string literals) causes PDQ Connect to ignore the object schema and treat all output as unstructured data.
PSCustomObject, and that no text is written directly to the output stream.Avoid logging or status messages
Informational messages such as:
"Starting scan..." "Completed scan."
can interfere with object processing, even if valid objects are also returned.
Ensure your script emits only structured objects and suppresses all logging or progress output.
PowerShell Scanner Script Template
The following template provides a simple starting point for writing scanner‑compatible scripts.
# PowerShell Scanner Script Template
# ---------------------------------
# Purpose:
# Collect data for use in a PDQ Connect PowerShell scanner.
#
# Requirements:
# - Output structured objects only
# - Do not write to the console
# - Do not use formatting or ConvertTo-Json
# Collect data
$osInfo = Get-CimInstance -ClassName Win32_OperatingSystem
# Return structured output
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
OSName = $osInfo.Caption
OSVersion = $osInfo.Version
InstallDate = $osInfo.InstallDate
LastBootTime = $osInfo.LastBootUpTime
}
Selecting a Test Device and Validating Output
Before deploying a scanner across your environment, you must validate it on a test device.
- In the Select test device section, choose an online device.
- Click Run script.
Validation allows you to:
- Confirm the script runs successfully
- Review detected columns and data types
- Ensure output is structured as expected before scanning additional devices
Important: Columns are locked in at validation time and apply universally across all scanned devices, even if some devices produce more properties than others.
If the script produces additional properties or objects on a different device—but those properties were not present during validation—they will not appear in the scanner results. To include those additional columns, you must re‑run the validation on a device where the script outputs those properties.
For best results, select a test device that is likely to return the most complete dataset, ensuring all desired columns are captured during validation before scanning additional devices.
Understanding Output and Data Types
After validation, PDQ Connect displays the script output in a tabular format.
- Each returned object becomes a row
- Each object property becomes a column
PDQ Connect automatically detects a data type for each column. Supported types are String, Integer, Float, Boolean, and Date. Date values are formatted into a consistent, usable format for display.
Each column includes a data type selector in the UI. This doesn't affect the raw values your script returns, but it controls how PDQ Connect stores the data for use in Filters and Groups. This can be useful in situations like when PowerShell returns Boolean values as 0 or 1 and you want them treated as true/false rather than numbers.
Enabling and Saving the Scanner
A PowerShell scanner must be enabled before it will begin scanning devices.
You can enable the scanner:
- During creation, using the Enable toggle at the bottom‑right of the configuration page, or
- Later, from the main Scanners page
Once you are satisfied with the script and validated output, click Save.
An enabled scanner will scan devices according to PDQ Connect’s normal scanning behavior.
Viewing Results on a Device
PowerShell scanner results are available at the device level:
- Open a device in PDQ Connect.
- Navigate to Scanners.
- Select PowerShell.
This view shows the most recently collected results for that device and can be used for inventory review, filtering, and targeting.
Troubleshooting: Why Didn’t My Scanner Work?
If your PowerShell scanner produces unexpected or unusable results, check the following common issues:
| Symptom | Likely cause & fix |
| Only numbers appear in results | The script is outputting plain strings instead of objects. Use PSCustomObject to wrap all values. |
| Expected columns are missing | Output was formatted or written to the console. Remove formatting cmdlets and return raw objects. |
| Schema disappears after adding logging | Mixed output (text + objects) is not supported. Move all values — including status text — into PSCustomObject properties. |
| Fewer rows than expected | Output exceeded the 100-row limit and was silently truncated. Filter or scope the script output to stay within the limit. |
Most issues can be resolved by ensuring the script outputs only structured objects.
Part 2: How the PowerShell Scanner Works (Advanced)
This section is intended for advanced users and script authors.
Most customers can successfully use PowerShell scanners without reading this section.
PowerShell scanners execute scripts in a non‑interactive context and evaluate results as data, not as console output.
To support display, filtering, and targeting in PDQ Connect, all scanner output must ultimately be converted into clean, predictable JSON. PDQ Connect performs this JSON conversion automatically on the backend to ensure consistent structure and data types.
For this reason:
- Scanner scripts should return native PowerShell objects
- Scripts should not attempt to control JSON serialization
- Formatting and console‑style output is not supported
PowerShell Scanner Wrapper
PDQ Connect uses internal logic (a “wrapper”) when running PowerShell scanners to process and normalize script output before converting it into JSON for use by the Connect application.
At a high level, the wrapper:
- Executes the user’s script
- Collects everything written to the PowerShell output stream
- Normalizes the results into a predictable, flat structure
- Converts the final output into clean JSON
If a user‑submitted script already includes a trailing ConvertTo‑Json, that portion is automatically removed before execution. This prevents double serialization and ensures PDQ Connect remains in control of how scanner results are processed and stored.
Important
Scripts should return objects only. JSON conversion is handled automatically by PDQ Connect.
Testing Scripts Locally Using the Scanner Wrapper
Some scripts work as expected in an interactive PowerShell session but behave differently when run as a scanner.
To support advanced troubleshooting, a modified version of the scanner wrapper is provided below. This version is adapted for execution in a PowerShell prompt but mirrors the same logic PDQ Connect uses on the backend when running a PowerShell scanner.
The wrapper is provided as a diagnostic aid only. Most customers do not need to use it.
Local Test Wrapper (Optional)
# Load and sanitize external script, stripping any trailing ConvertTo-Json
param (
[Parameter(Mandatory)]
[ValidateScript({ Test-Path $_ -PathType Leaf })]
[string]$ScriptPath
)
$originalScript = Get-Content -Path $ScriptPath -Raw
$convertToJsonPattern = '\|\s*ConvertTo-Json\b[^\r\n]*\s*$'
$cleanedScript = [regex]::Replace(
$originalScript.TrimEnd(),
$convertToJsonPattern,
'',
'IgnoreCase'
).TrimEnd()
$scriptBlock = [scriptblock]::Create($cleanedScript)
& $scriptBlock |
ForEach-Object {
if ($null -eq $_) { return }
if ($_ -is [hashtable] -or $_ -is [System.Collections.Specialized.OrderedDictionary]) {
$_ = [pscustomobject]$_
}
$out = [ordered]@{}
foreach ($p in $_.PSObject.Properties) {
$value = $p.Value
if ($value -is [datetime]) {
$value = $value.ToString('o')
}
$out[$p.Name] = $value
}
[pscustomobject]$out
} | ConvertTo-Json -Depth 1 -Compress
If a script produces the expected results when tested with this wrapper, it will behave the same way when run as a PowerShell scanner in PDQ Connect.
Additional Reading
PSCustomObject to shape scanner results.