Back to blog
FILE 0x77·DISABLING ZEBRA PRINTER BIDI WHEN POWERSHELL REFUSES TO HELP

Disabling Zebra printer Bidi when PowerShell refuses to help

April 27, 2026 · windows, printers, powershell

I write deployment scripts for Zebra ZQ521 mobile printers running CPCL. Two of the standard config knobs — disable bidirectional communication and disable advanced printing features — are both required for these printers to behave on Windows, and both refuse to set cleanly via the PowerShell cmdlets you'd expect.

What was happening

Both ends of the same problem:

Set-PrinterPort -Name USB001 -EnableBidi $false
# Set-PrinterPort: A parameter cannot be found that matches parameter name 'EnableBidi'.

Set-PrintConfiguration -PrinterName 'ZDesigner ZQ521' -AdvancedPrintingFeatures $false
# Set-PrintConfiguration: A parameter cannot be found that matches parameter name
# 'AdvancedPrintingFeatures'.

These parameter names appear in plenty of Microsoft documentation. They aren't actually exposed on every Windows build I have to support. The bootstrap script kept logging warnings for both and the printers kept showing up bidi-enabled with default features on.

What I found

Both flags live in the registry as bits inside a single Attributes DWORD under HKLM\SYSTEM\CurrentControlSet\Control\Print\Printers\<name>. The relevant bits:

0x00000400  PRINTER_ATTRIBUTE_WORK_OFFLINE
0x00000800  PRINTER_ATTRIBUTE_ENABLE_BIDI
0x00001000  PRINTER_ATTRIBUTE_RAW_ONLY

To disable bidi and force raw-only (which is what CPCL wants), clear the WORK_OFFLINE and ENABLE_BIDI bits and set RAW_ONLY. Then restart the spooler so the change takes.

The fix

$path = "HKLM:\SYSTEM\CurrentControlSet\Control\Print\Printers\ZDesigner ZQ521"
$attr = (Get-ItemProperty -Path $path -Name Attributes).Attributes
$attr = $attr -band (-bnot 0x400)   # clear WORK_OFFLINE
$attr = $attr -band (-bnot 0x800)   # clear ENABLE_BIDI
$attr = $attr -bor 0x1000           # set RAW_ONLY
Set-ItemProperty -Path $path -Name Attributes -Value $attr
Restart-Service Spooler

Verification was the other thing I wanted to nail down — I don't trust a printer config change without proof. Reading the same Attributes value back after the spooler restart and decoding the bits is enough.

What I'd do differently

Two notes for next time. First: pnputil /add-driver silently partially-installs when the INF file's referenced supporting files are scattered across subdirectories. Flatten the driver package into one folder before calling pnputil. This bit me in an earlier version of the same script. Second: Add-PrinterDriver -InfPath for multi-driver INF packages already in the driver store fails the first time with "invalid value" but registers the driver anyway. Catch and ignore that one specific error rather than retrying. Both are the kind of Windows printing landmines you can only really learn by stepping on them.