windows_powershell
Experimental. A PowerShell script on a Windows host, for what no module covers yet. Guards say when it has already done its job.
Experimental. Windows support is new, and this module may change between releases.
Use windows_powershell for what no Windows module covers yet. Values go in args, and the script reads them as $A.name: they arrive as data, so a quote or a $(...) in one is just text.
Example usage
Section titled “Example usage”Create a directory once:
step "app_dir" { windows_powershell { script = "param($A) [void][IO.Directory]::CreateDirectory($A.dir)" args = { dir = "C:\\app" } creates = "C:\\app" }}Run only while a check says the work isn’t done:
step "long_paths" { windows_powershell { script = "Set-ItemProperty -LiteralPath 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem' -Name LongPathsEnabled -Value 1" unless = "(Get-ItemProperty -LiteralPath 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem').LongPathsEnabled -eq 1" }}Arguments
Section titled “Arguments”| Name | Type | Required | Description |
|---|---|---|---|
args |
map of string | No | Values the script reads as $A.name. They reach it as data, never as code. |
args_wo |
map of string | No | Like args, but kept out of state: state records only args_hmac, and the values are blanked from output and errors. Use it for secrets. |
creates |
string | No | Skip the script while this path exists. |
removes |
string | No | Skip the script while this path is missing. |
script |
string | Yes | PowerShell script. Start it with param($A), and read arguments as $A.name rather than interpolating them into the text. |
timeout |
string | No | How long the script may run before it is stopped. Defaults to “30m”. |
triggers |
dynamic | No | Any value; the script runs again whenever it changes. |
unless |
string | No | Skip the script while this PowerShell check holds: it holds unless it throws, its last output is $false, or a native program it ran last exited non-zero. It runs at every plan, so it must change nothing. It gets args but never args_wo, which a plan doesn’t have. |
Read-only attributes
Section titled “Read-only attributes”Conn3x sets these; reference them as conn3x_windows_powershell.<circuit>__<step>["<host>"].<name>.
| Name | Type | Description |
|---|---|---|
args_hmac |
string | HMAC-SHA256 of args_wo, keyed by CONN3X_HMAC_KEY or ~/.config/conn3x/hmac.key. Null without args_wo. |
revision |
string | Changes each time Conn3x changes this on the host. Handlers watch it. |
satisfied |
bool | Whether the guards hold on the host. |
stderr |
string | Error output of the last run, truncated to 4 KiB. |
stdout |
string | Output of the last run, truncated to 4 KiB. |
A step lowers to the conn3x_windows_powershell resource, one instance per host, and connects with its circuit’s ssh block.
How it works
Section titled “How it works”Failing. A script fails by throwing. Errors stop it by default, because $ErrorActionPreference is Stop. It also fails when the last native program it ran exits non-zero; for a tool with other success codes, such as robocopy, finish with $global:LASTEXITCODE = 0. Calling exit is reported as a failure: use return to finish early, and throw to fail.
Guards. Like command, the script runs when the step is created, when anything that defines it changes, and when a refresh finds its guards no longer hold. unless runs at every plan, so it must change nothing.
Secrets. args_wo stays out of the plan and state. State records only args_hmac, and the values are blanked from output and errors. A refresh doesn’t have them, so an unless check that needs them sees them only during an apply.
Secrets and logging. Where a policy turns on PowerShell’s module logging, Windows records what’s passed to any cmdlet. Conn3x keeps args_wo away from cmdlets on its way to your script, so don’t pass a secret to one yourself: use a .NET method, as in [IO.File]::WriteAllText($A.path, $A.secret).
Timeouts. A script is stopped after timeout. Conn3x stops the whole process tree when it cancels a run, but if the connection itself drops, as when the machine running Conn3x crashes, the script carries on running on the host.
Connecting. The ssh block works as it does on Linux, with its host key pinned or in known_hosts. Windows Server 2025 ships OpenSSH. Server 2022 doesn’t, so bootstrapping adds it first, as the Azure example’s script does. Either way, Conn3x installs its own host key as part of bootstrapping the host. become only checks that the login is elevated, since Windows has no sudo. agent and become_password_file are errors. Keep user as the bare name, such as azadmin, which still works after the host is promoted to a domain controller.
Removal
Section titled “Removal”Deleting a windows_powershell step does nothing on the host.