When to use a PowerShell host, when to stay in JavaScript, and why REST APIs are the foundation of everything Aria Orchestrator does.
vRO's scripting engine is Mozilla Rhino 1.7R4 — a Java-based JavaScript runtime frozen at roughly ECMAScript 5.1. It runs entirely inside the JVM on the vRO appliance and has no OS-level access of any kind: no shell execution, no process spawning, no Win32 API surface, no PowerShell runtime.
This is not a limitation that can be worked around from within a scriptable task or action. Rhino can parse JSON, call REST endpoints via the REST plugin, and manipulate vCenter objects through the vSphere API wrapper — but it cannot natively run a .ps1 script or invoke a PowerShell cmdlet.
A PowerShell host is a registered Windows machine (or the vRO appliance via SSH) running the vmware-vro-powershell-host service. vRO connects to it over a TCP socket and ships PowerShell commands for execution there, returning results as structured objects.
The "inline PowerShell" exposed by the PowerShell scripting plugin is transparently proxied to this host — it is not local execution. If no host is registered, all such calls fail.
JavaScript// This looks inline but executes on the remote PS host
var host = PowerShellHostManager.getHost("MyPSHost");
var result = host.invokeScript("Get-Date");
System.log(result.invocationResult);
The performance difference between a native REST call and a PowerShell-proxied one is significant — not just in speed, but in failure surface.
| Factor | JavaScript (REST Plugin) | PowerShell Host |
|---|---|---|
| Execution location | vRO appliance JVM | Remote Windows host |
| Process spawn overhead | None | 500ms–2s per invocation |
| Network dependency | To target API only | PS host + target API |
| Failure modes | Rhino errors, REST failures | Host down, WinRM, auth, PS errors |
| Debug surface | vRO logs only | vRO logs + PS host logs |
| Infrastructure to maintain | None | Windows host + service |
Use a PowerShell host when the data source or operation is fundamentally cmdlet-native and has no REST equivalent — or when the available REST API is significantly less capable than the corresponding PowerShell module.
| Use Case | Why PS Wins |
|---|---|
| Active Directory operations | No AD module in Rhino; Get-ADGroupMember with full flags outpaces Microsoft Graph for many operations |
| Exchange / Exchange Online cmdlets | Exchange is PS-native; REST coverage is incomplete |
| Windows WMI / CIM queries | No WMI bindings exist in vRO |
Existing .ps1 scripts | Reuse without rewrite; stable tested code |
Operations requiring Import-Module | Module loading is impossible in Rhino |
| Windows filesystem operations | No OS access from JS |
JavaScriptvar host = PowerShellHostManager.getHost("AD-PS-Host");
var script = "Get-ADGroupMember -Identity 'Server-Admins' | Select-Object -ExpandProperty SamAccountName";
var result = host.invokeScript(script);
System.log("[ADCheck] Members: " + result.invocationResult);
If the operation has a REST API or a native vRO plugin, keep it in JavaScript. The REST plugin is purpose-built for this work, lives inside the JVM, and eliminates the PS host dependency entirely.
| Data Source | Owned By | Do Work In |
|---|---|---|
| Azure ARM / Resource Manager | REST API | JavaScript |
| Aria Automation | REST API | JavaScript |
| Infoblox WAPI | REST API | JavaScript |
| ServiceNow / ITSM Platform | REST API | JavaScript |
| vCenter / ESXi | VcPlugin (vSphere API) | JavaScript |
| vRO workflow execution | vRO internal API | JavaScript |
| Config element lookups | vRO internal | JavaScript |
| JSON parsing / data manipulation | Rhino engine | JavaScript |
JavaScript — Anti-Pattern// DON'T: spin up a PS host just to make an API call
// vRO → PS host → REST call → results → back to vRO
// Every hop is waste — and a potential failure point
// DO: use the REST plugin directly — faster, no host dependency
var host = RESTHostManager.getHost("AzureREST");
var req = host.createRequest("GET", "/subscriptions/" + subId + "/resourceGroups", "");
req.setHeader("Authorization", "Bearer " + token);
var resp = req.execute();
var parsed = JSON.parse(resp.contentAsString);
A common question: if a PS host makes an API call that returns 6,000 objects, should PS manipulate the data before returning it to vRO? The answer depends entirely on who owns the data source.
If the data comes from a REST API that vRO can call directly, the PS host should never be in the picture at all. vRO's REST plugin fetches the data, JSON.parse() deserializes it, and a standard for loop filters it — all inside the JVM, with no external host dependency.
JavaScript — Correct Pattern// REST call → parse → filter — all in JS, no PS host needed
var req = restHost.createRequest("GET", "/api/v2/vms", "");
var resp = req.execute();
var allVms = JSON.parse(resp.contentAsString).value;
var filtered = [];
for (var i = 0; i < allVms.length; i++) {
if (allVms[i].powerState === "poweredOn") {
filtered.push(allVms[i].name);
}
}
If the data comes from a cmdlet-native source (Active Directory, Exchange, WMI), PS should own the entire operation — including filtering. Return only what vRO needs. Don't hand back raw collections of thousands of objects when a Where-Object or Select-Object can trim it first.
| Question | If Yes | If No |
|---|---|---|
Does the script use Import-Module? | PS host — module loading is impossible in Rhino | Likely belongs in JS |
| Are there AD / Exchange / WMI cmdlets? | PS host — no equivalent in Rhino | Evaluate REST alternative |
| Is it just REST calls + JSON parsing? | Move to JS — REST plugin handles this natively | May still need PS for other reasons |
| Does the target have a documented REST API? | Use it from JS | PS host may be the only option |
vRO has no native UI, no direct database access, and no agent on managed systems. It is a pure orchestration engine. This means everything vRO does to the outside world, it does through an API.
Even VcPlugin — which feels like native vCenter access — is a strongly-typed SDK wrapper over the vSphere SOAP/REST API. vRO did not receive special OS-level access to ESXi. It received a well-structured client over the same API that any other integration tool uses.
Because everything is API-driven, vRO's orchestration capability scales directly with how many APIs have been integrated. A vRO instance with REST hosts for Azure, Infoblox, Aria, and an ITSM platform can orchestrate an entire provisioning lifecycle — compute, DNS, IPAM, and ticketing — in a single workflow, with no agents, no PS hosts, and no remote sessions.
PS hosts exist because some platforms lack REST APIs — or their REST APIs are incomplete relative to their PowerShell modules. Active Directory is the canonical example. Microsoft's Graph API covers some AD operations, but cmdlet coverage with full pipeline support still outpaces what Graph exposes for many common infrastructure tasks.
When a vendor provides a strong REST API, use it from JavaScript. When they provide a strong PS module and a limited REST API, use the PS host — but only for that specific gap. It should not become the default integration pattern.
JSON.parse() and standard array iteration are sufficient for all data shaping tasks on REST-sourced data. There is no reason to delegate this to a PS host. If PS owns the data source (e.g., AD), it should pre-filter before returning to vRO.Import-Module have no Rhino equivalent. These are the legitimate PS host use cases. If a PS script contains no cmdlets — only REST calls and JSON wrangling — it should be rewritten as a vRO JavaScript action.