Run vetted PowerShell scripts on a Windows collector from a workflow — place the .ps1 on the collector, register it, then call it from the built-in "Run PowerShell on Collector" workflow or the collector.powershell step, with the exit code and output captured back in the run.
Some of the work a network team automates has no API behind it — it is a PowerShell script somebody wrote years ago, the one that walks an F5 HA pair and enables AutoSync, or sweeps a BlueCat zone, or pulls a report off a Windows box that only answers to WinRM. Versus runs those scripts on the collector that already sits inside your network, and lets a workflow drive them. The script never travels through Versus: an administrator places it on the collector by hand, you register it the way you register a firmware image, and from then on a workflow only chooses which registered script runs and with what arguments. The collector runs it locally, on its own host, and reports the exit code and output back into the run.
That boundary is the whole point, so it is worth stating plainly before anything else: the cloud cannot send a script body to a collector. It can only name one that an on-prem admin already put there. Everything below follows from that.
Three pieces fit together:
| Piece | Where | Who |
|---|---|---|
The .ps1 file | The collector's scripts directory | An on-prem administrator, by hand |
| The registration | System → Collector Scripts | A Versus admin (Network-Admin) |
| The run | A workflow — the built-in tool, or the collector.powershell step | Anyone who can run the workflow |
Every collector watches a local scripts directory. By default that is scripts under the collector's state directory — on a Windows collector that is usually C:\var\lib\versus-agent\scripts. If you keep your scripts somewhere else, point the collector at it with the VERSUS_SCRIPTS_DIR environment variable and restart the agent.
Drop your .ps1 files in that directory. Only files ending in .ps1 are considered; anything else is ignored. Within about a minute the collector reports what it finds — the file name, its size, and a SHA-256 of its contents — and those files appear on the Collector Scripts page, ready to register. Nothing runs yet; reporting a file only makes it available to register.
Because the admin who placed the file is trusted, the collector runs it with -NoProfile -NonInteractive -ExecutionPolicy Bypass -File — an unsigned local script runs without a prompt. Keep the directory itself locked down the way you would any directory of scripts that run with the collector's privileges: what lands there is what Versus will run.
Open System → Collector Scripts. Under Scripts reported by collectors you will see each .ps1 every collector has reported, with its collector and size. A file you have already registered is marked; a new one has a Register button.
Registering is where you give the script the context a workflow needs:
pwsh) and falls back to Windows PowerShell, or you can pin one.-DeviceListPath C:\f5\devices.txt), which is how most scripts expect them. Turn it on only for a script that reads $args positionally.Once registered, the script shows in the lower table with a state badge. In sync means the file on disk still matches what you registered. Changed on disk means the admin replaced the file since — the script will still run, but you are told the content drifted so nothing changes under you silently. Missing means the collector is no longer reporting that file at all. You can Disable a script to take it out of circulation without unregistering it, and Unregister removes it from Versus — it never touches the file on the collector.
There are two ways to run a registered script, and they share the same engine.
Run PowerShell on Collector is a ready-made workflow — find it in the workflow list and click Run. It asks for three things: the registered script, its arguments, and a timeout. Pick the script from the dropdown (it shows the drift badge, so you know the collector is still reporting it), fill in the arguments, and run. This is the quickest way to run a script ad-hoc, and it is a complete, auditable run like any other — it appears in the run history with its log, its output, and who started it.
You can also run a script straight from the Collector Scripts page with the Run button on its row, which opens a small dialog, runs it, and streams the result back in place — handy for a quick check without leaving the page.
collector.powershell stepTo make a script one step of a larger workflow — run it after a change, or only when a decision branch is taken — drop the Run PowerShell on Collector step (collector.powershell) onto the canvas. It has four settings:
{{script_id}}.{parameter: value} mapped to the script's declared parameters, or one Name=value per line.The step hands the next steps three outputs: exit_code, stdout, and stderr — so a later step can branch on the result or fold the output into an email or a ticket.
Arguments are never pasted into a command line and handed to a shell — that is how injection happens. Versus builds them as a list of discrete values and passes them straight to PowerShell after -File.
What you supply is matched against the parameters you declared:
-Name value. An empty one is dropped.-Name when it is on, and is left out entirely when it is off.For a script you registered as positional, the values are passed in the order the parameters are declared, with no -Name in front. A run is capped at a sensible number and length of arguments, so a malformed input cannot balloon into an enormous command.
When the collector finishes, the run shows what happened:
If the collector cannot run the script at all — the file is gone, there is no PowerShell interpreter on the host, or the collector is offline — the step fails with a plain message saying why, which is different from the script running and exiting non-zero. You can tell "it never ran" from "it ran and failed" at a glance.
That is running PowerShell on a collector — an admin places the script, you register it with the arguments it expects, and a workflow runs it on the box inside your network and brings back the exit code and the output, with the script body never leaving the collector.