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:

  1. Click Scanners in the left navigation pane.
  2. Click Create Scanner in the top‑right corner.
  3. Give the scanner a descriptive name.
  4. 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 .ps1 file, 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
}
 
Incorrect output
Write-Host   "Antivirus is enabled"
Write-Output "Antispyware is enabled"
Get-Date
 
When a script outputs plain strings or formatted text, the object structure is lost before PDQ Connect receives the data. As a result, columns and values cannot be detected or stored correctly.
 

Avoid Output‑Formatting Cmdlets

Do not use output‑formatting or console‑only cmdlets in PowerShell scanners, including:

  • Write-Host
  • Format-Table
  • Format-List
  • Out-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. 

To correct this, ensure that all values, including status or informational text, are returned as properties on a 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
}
Use this template when creating new scanners or adapting existing scripts for PDQ Connect.
 

Selecting a Test Device and Validating Output

Before deploying a scanner across your environment, you must validate it on a test device.

  1. In the Select test device section, choose an online device.
  2. 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:

  1. Open a device in PDQ Connect.
  2. Navigate to Scanners.
  3. 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

Because the PowerShell scanner relies on structured output, we recommend the following article on using PSCustomObject to shape scanner results.
 

Everything you wanted to know about PSCustomObject

Was this article helpful?