Skip to content

PowerShell Runspaces For UNIFYConnect

Overview

Previous versions of UNIFYConnect ran Windows PowerShell scripts in-process, allowing extensible functionality for people familiar with scripting languages.

From UNIFYConnect v6 onwards, a shift to PowerShell 7 highlighted issues with executing these scripts in-process, particularly with relation to memory usage and performance.

UNIFYConnect v7.2 added the ability to reuse runspaces inside the service (Managed PowerShell Runspaces), avoiding the overhead of recreating and reloading modules on each script execution. This improved performance but did not solve the memory-usage problem.

UNIFYConnect v8.0 added an (out-of-process runner), retaining runspace reuse while allowing the worker process to be recycled without affecting the UNIFYConnect service.

Managed PowerShell Runspaces (v7.2+)

The use of managed PowerShell runspaces allows the reuse of PowerShell runspaces from a pool of active runspaces. This reduces the overhead of creating a new runspace and improves the performance.

NOTE

While managed runspaces are enabled, modifications to external PowerShell modules may not be picked up, as PowerShell caches module imports. To ensure module changes are picked up, use the Refresh Runspaces option. For ongoing development scenarios, it's recommended to disable managed runspaces, and re-enable once complete.

Use Enable or Disable to change managed runspace use for all UNIFYConnect engines at runtime. Managed runspaces are enabled by default unless an engine configuration overrides them. Reset To Default restores the settings defined in each engine's configuration. Refresh Runspaces immediately disposes of cached runspaces, releases their resources, and forces new runspaces to be created.

NOTE

When the managed PowerShell runspace state has been changed at runtime, it is recommended to restart the service to ensure efficient resource usage - as PowerShell stores global state that can't be refreshed, causing memory to grow over time. Note that this setting is not permanent. For lasting changes, update the configuration files directly.

image

Out-of-Process PowerShell Execution (v8.0+)

Out-of-process PowerShell execution runs scripts in a separate worker process rather than inside the main UNIFYConnect service. This isolates script execution and allows the worker process to be recycled without restarting the service.

In v8.0, in-process execution is the default. An individual script usage can select WorkerProcess with the powerShellExecution setting described below. To force every supported PowerShell usage to run in the worker, set ForceOop in the powerShellSettings section of Services/appsettings.json:

json
"powerShellSettings": {
  "ForceOop": true
}

The packaged worker is located at Services/Workers/PowerShell/Unify.IdentityBroker.PowerShellWorker.exe on Windows and Services/Workers/PowerShell/Unify.IdentityBroker.PowerShellWorker on Linux. Normally its path is detected automatically. Use WorkerExePath only to override that location:

json
"powerShellSettings": {
  "ForceOop": false,
  "WorkerExePath": "D:\\UNIFYConnect\\Services\\Workers\\PowerShell\\Unify.IdentityBroker.PowerShellWorker.exe"
}

The equivalent command-line options are --powershell-force-oop and --powershell-worker-exe-path.

WARNING

Values passed between the service and worker are serialized. Test existing scripts before enabling out-of-process execution, particularly scripts that depend on process-local .NET objects, static state, or modules with native dependencies. Use the APIs exposed through the script's $components object to interact with UNIFYConnect.

Configuration

Common Engine Configuration

The following settings can be set in the configuration file for each engine. Default values are used when no engine-level PowerShell configuration object is present.

PropertyDescriptionRequired
runspaceManagementModeAllowed values are SharedRunspace (the default) and None. Required when an engine-level PowerShell configuration object is present.Conditional
usageSettingsA collection of settings for the engine's PowerShell script usages. Required when an engine-level PowerShell configuration object is present; use an empty array if no usages are overridden.Conditional
scriptType under usageSettingsThe type of script to which the settings apply. Each engine has a set of supported values listed below.Yes
powerShellExecution under usageSettingsAllowed values are InProcess (the default) and WorkerProcess.No
lockWaitTimeout under usageSettingsHow long to wait for a runspace in use to become available. A default value is defined for each script type.No
poolGrowthLimit under usageSettingsThe maximum number of pooled runspaces. A default value is defined for each script type.No
outOfProcessSettingsSettings that control worker-process lifetime and resource limits.No
workerLifetimeLimit under outOfProcessSettingsThe maximum worker-process lifetime. The default is 24 hours.No
workerMemoryLimit under outOfProcessSettingsThe worker-process memory limit in bytes. The default is 1 GiB.No
workerMaxConcurrentExecutions under outOfProcessSettingsThe maximum number of concurrent scripts a worker process can execute. The default is 200.No
$versionThe latest configuration-object version is "1.0".Yes

Connector Engine Configuration

PropertyDescriptionRequired
scriptTypeCan take any of the following values: GetAll, PollIdChanges, PollIdEntity, PollEntityChanges, Add, Update, Delete, DeleteAll, ModifyAnchor, ChangePassword, Schema.Yes
poolGrowthLimitThe default for all script types is 5.No
lockWaitTimeoutThe default is -00:00:00.001 for all script types (i.e. no waiting for an available runspace).No

Example

json
"powerShellConnectorRunspaceSettings": {
  "$version": "1.0",
  "runspaceManagementMode": "SharedRunspace",
  "usageSettings": [
    {
      "scriptType": "GetAll",
      "powerShellExecution": "WorkerProcess",
      "lockWaitTimeout": {
        "$fmt": "timeSpan",
        "$value": "01:05:00"
      },
      "poolGrowthLimit": 2
    }
  ],
  "outOfProcessSettings": {
    "workerLifetimeLimit": {
      "$fmt": "timeSpan",
      "$value": "04:05:00"
    },
    "workerMemoryLimit": 500000000,
    "workerMaxConcurrentExecutions": 100
  }
}

Adapter Engine Configuration

PropertyDescriptionRequired
scriptTypeCan take any of the following values: Transform, ReverseTransform, TransformSchema, JoinSelection.Yes
poolGrowthLimitThe default for JoinSelection is 6. The default for the other script types is 5.No
lockWaitTimeoutThe default is -00:00:00.001 for all script types (i.e. no waiting for an available runspace).No

Example

json
"transformationPowerShellRunspaceSettings": {
  "$version": "1.0",
  "runspaceManagementMode": "SharedRunspace",
  "usageSettings": [
    {
      "scriptType": "Transform",
      "powerShellExecution": "InProcess",
      "lockWaitTimeout": {
        "$fmt": "timeSpan",
        "$value": "01:05:00"
      },
      "poolGrowthLimit": 5
    }
  ],
  "outOfProcessSettings": {
    "workerLifetimeLimit": {
      "$fmt": "timeSpan",
      "$value": "04:05:00"
    },
    "workerMemoryLimit": 500000000,
    "workerMaxConcurrentExecutions": 100
  }
}

Logging Engine Configuration

PropertyDescriptionRequired
scriptTypeCan take any of the following values: LoggingYes
poolGrowthLimitThe default is 5.No
lockWaitTimeoutThe default is -00:00:00.001 (i.e. no waiting for an available runspace).No

Example

json
"powerShellRunspaceSettings": {
  "$version": "1.0",
  "runspaceManagementMode": "SharedRunspace",
  "usageSettings": [
    {
      "scriptType": "Logging",
      "powerShellExecution": "InProcess",
      "lockWaitTimeout": {
        "$fmt": "timeSpan",
        "$value": "01:05:00"
      },
      "poolGrowthLimit": 7
    }
  ],
  "outOfProcessSettings": {
    "workerLifetimeLimit": {
      "$fmt": "timeSpan",
      "$value": "04:05:00"
    },
    "workerMemoryLimit": 500000000,
    "workerMaxConcurrentExecutions": 100
  }
}

Auditing Engine Configuration

PropertyDescriptionRequired
scriptTypeCan take any of the following values: AuditingYes
poolGrowthLimitThe default is 5.No
lockWaitTimeoutThe default is -00:00:00.001 (i.e. no waiting for an available runspace).No

Example

json
"powerShellRunspaceSettings": {
  "$version": "1.0",
  "runspaceManagementMode": "SharedRunspace",
  "usageSettings": [
    {
      "scriptType": "Auditing",
      "powerShellExecution": "InProcess",
      "lockWaitTimeout": {
        "$fmt": "timeSpan",
        "$value": "01:05:00"
      },
      "poolGrowthLimit": 4
    }
  ],
  "outOfProcessSettings": {
    "workerLifetimeLimit": {
      "$fmt": "timeSpan",
      "$value": "04:05:00"
    },
    "workerMemoryLimit": 500000000,
    "workerMaxConcurrentExecutions": 100
  }
}

Channel Engine Configuration

PropertyDescriptionRequired
scriptTypeCan take any of the following values: ChannelYes
poolGrowthLimitThe default is 5.No
lockWaitTimeoutThe default is -00:00:00.001 (i.e. no waiting for an available runspace).No

Example

json
"powerShellRunspaceSettings": {
  "$version": "1.0",
  "runspaceManagementMode": "SharedRunspace",
  "usageSettings": [
    {
      "scriptType": "Channel",
      "powerShellExecution": "InProcess",
      "lockWaitTimeout": {
        "$fmt": "timeSpan",
        "$value": "01:05:00"
      },
      "poolGrowthLimit": 7
    }
  ],
  "outOfProcessSettings": {
    "workerLifetimeLimit": {
      "$fmt": "timeSpan",
      "$value": "04:05:00"
    },
    "workerMemoryLimit": 500000000,
    "workerMaxConcurrentExecutions": 100
  }
}