External content by Sébastien Anselment, July, 2025;
If one needs input and/or output parameters with invoke of PowerShell scripts one will run in a deadlock because there is no support for such parameters. Check this user voice for more details. That's why this article describes a workaround using the great solution "PowerShell Universal" (PSU):
Homepage: PowerShell Universal | PowerShell Universal
Pricing: Pricing | PowerShell Universal (Per Server $499,99 containing 1 year of Updates and Support)
One of the features enables one to centralize all PowerShell scripts in this plattform and to create REST API endpoints for individual scripts. As WEBCON supports input and output parameters in the action "Invoke REST Web service" one can use this to call PowerShell scripts. The free version of PSU is all one needs to implement everything that is described in this article. Because there is no support for security and authentication configuration it is necessary to buy a PSU server license for productional use.
A nice tutorial playlist can be found on YouTube here. The first four videos describe all steps it needs to get a great overview and all for the setup of PSU. Don't forget to allow in the local firewall incoming request to the TCP port (default port is 5000) from your WEBCON server(s) as source. Otherwise WEBCON will never get a successfull connection to PSU.
This article describes all steps to create a small running demo that gets two summands and returns their sum with basic validation, error/exception handling and a running sceleton for new use cases without running in all deadlocks, as I have been in the beginnings with PSU.
Enter the URLfor the endpoint, choose the correct method POST and set some other fields to create the endpont, click on the OK button:
Now you can enter your PowerShell code and don't forget after all changes by clicking the small save button on the upper right:
The example code receives two integer parameters and returns their sum. First we have to get out the $Body out of the WEBCON endpoint invoke:
$data = ConvertFrom-Json $Body
The JSON body set in the configuration of the invoke REST web service action in WEBCON will be explained later and looks like this. There are two required parameters for the summand1 and summand2 and one optional parameter summand3. To illustrate validation error the form field "Summand2" will not be marked as required in the filed matrix later on for demo purpose:
{
"required": {
"summand1": #{2658}#,
"summand2": #{AUTP_Value:7}#
},
"optional": {
"summand3": #{AUTP_Value:5}#
}
}
Next this two input parameter objects are assigned to variables for required and for optional parameters of the input form fields:
$requiredParams = $data.Required
$optionalParams = $data.Optional
Next all required parameters of the object get iterated, the value is set to $value variable and a server validation is done to check if the value is null or empty to return an error back to WEBCON. If the value is given the variablee is created dynamically:
foreach ($key in $requiredParams.PSObject.Properties.Name) {
$value = $requiredParams.$key
if ([string]::IsNullOrEmpty("$value")) {
$isError = $true
$errorMessage += "Required WEBCON parameter '$key' is missing or empty."
} else {
#Create variable for required parameter
Set-Variable -Name $key -Value $value -Scope Script
}
}
Same is done if the object of the optional parameters isn't empty but without the validation of the attributes values because they are only optional:
if ($optionalParams) {
foreach ($key in $optionalParams.PSObject.Properties.Name) {
$value = $optionalParams.$key
Set-Variable -Name $key -Value $value -Scope Script
}
}
If everything is fine the main code can be run. It is enclosed by an if statement checking there is no validation error that prevents to calculate the code, here the sum:
if (-not $isError) {
$summand1 = [int]$summand1
$summand2 = [int]$summand2
#Add both summands
$sum = $summand1 + $summand2
if ($summand3) {
$sum += [int]$summand3
$log = "Addition of the integers '$summand1' and '$summand2' and '$summand3' gives sum '$sum'."
} else {
$log = "Addition of the integers '$summand1' and '$summand2' gives sum '$sum'."
}
}
Finally the return object can be build. A great exchange with Daniel Krüger brought me to this object structure. First an object result containing all necessary attributes for further process in WEBCON and second two additional attributes for the error/exception handling. PowerShell Universal always returns the returned value as array. That's why the JSON string gets explicitely created instead of only returning $result. An array can only get mapped to a WEBCON item list and this is not what one wants because the returned parameters need to get mapped to "normal" form fields. The errorMessage value contains a PowerShell map that needs an item list in the mapping configuration of the response. This is shown later in the WEBCON configuration section:
$result = [PSCustomObject]@{
result = [PSCustomObject]@{
log = $log
sum = $sum
}
isError = $isError
errorMessage = $errorMessage
}
$json = $result | ConvertTo-Json -Depth 10 -Compress
return $json
The whole PowerShell script is this:
$ProgressPreference = "SilentlyContinue"
$InformationPreference = "SilentlyContinue"
$WarningPreference = "SilentlyContinue"
$isError = $false
$errorMessage = @()
$data = ConvertFrom-Json $Body
$requiredParams = $data.Required
$optionalParams = $data.Optional
foreach ($key in $requiredParams.PSObject.Properties.Name) {
$value = $requiredParams.$key
if ([string]::IsNullOrEmpty("$value")) {
$isError = $true
$errorMessage += "Required WEBCON parameter '$key' is missing or empty."
} else {
#Create variable for required parameter
Set-Variable -Name $key -Value $value -Scope Script
}
}
if ($optionalParams) {
foreach ($key in $optionalParams.PSObject.Properties.Name) {
$value = $optionalParams.$key
Set-Variable -Name $key -Value $value -Scope Script
}
}
if (-not $isError) {
$summand1 = [int]$summand1
$summand2 = [int]$summand2
#Add both summands
$sum = $summand1 + $summand2
if ($summand3) {
$sum += [int]$summand3
$log = "Addition of the integers '$summand1' and '$summand2' and '$summand3' gives sum '$sum'."
} else {
$log = "Addition of the integers '$summand1' and '$summand2' gives sum '$sum'."
}
}
$result = [PSCustomObject]@{
result = [PSCustomObject]@{
log = $log
sum = $sum
}
isError = $isError
errorMessage = $errorMessage
}
$json = $result | ConvertTo-Json -Depth 10 -Compress
return $json
Create a new app with a process and all stuff named "Calculate sum":
Create three integer form fiels for the three summands:
Create a group for the REST response of our endpoint /tools/calculateSum with:
Then configure the field matrix. The two first summands will be marked as required normally but for this article the field "Summand2" won't be marked as required to demonstrate the error handling of optional empty parameters later:
Now create a new automation in the Configuration of the process and call it e.g. "REST PSU 01 tools/calculateSum". Create two local parameters in the configuration of the automation summandParam2 and summandParam3. The summandParam2 is only needed to show how optional form fields must get treated to prevent a Bad Request (400) response invoking the endpoint if the parameter is required in PSU. This step is not necessary for form fields that are marked as required in the field matrix normally:
BadRequest (400) error message returns this because of invalid syntax:
Then add those actions to the automation:
Check if Summand2 (only for demo purpose of error handling) and optional Summand3 are empty and set the local parameters summandParam2 and summandParam3 to null or to the respective value:
The Body type is "JSON" and the JSON part value is as follows. In this case one could directely use the form field "Summand2" being normally marked as required instead of the local parameter "summandParam2". But to demonstrate also the way for optional fields that can have empty values where PSU requires this as parameter the needed workaround via local automation parameters is used here:
{
"required": {
"summand1": #{2658}#,
"summand2": #{AUTP_Value:7}#
},
"optional": {
"summand3": #{AUTP_Value:5}#
}
}
Set "JSON" as Body type. If the endpoint is already set up correctly as described above one can click on the load button to invoke the endpoint and to set the structure in the value mapping. Now do the mapping as follows:
The final step is to configure the workflow in the Workflow Designer. The Start button has a default path "Calculate" in Wizzard Mode assigned to the current user leading to the start button again and the automation is added:
The configuration of the path's action just adds the above automation to the flow as follows:
Now you are done and can start your first workflow instance and play around with values for the summand fields and click the "Calculate" button.
To illustrate this the form field needs not to be marked as required as otherwise the field could not be left empty to occure the validation error and returned messages:
To conclude this article a small summary of a futher going use case using this setup:
The technical entry process of new employees has multiple PSU endpoints. The first is used to normalize the names of the new employee to create an email address following our company naming convention. A second endpoint is used to generate the samaccountname. The third endpoint creates the AD user and sets all attributes that are entered in the WEBCON form when a new employee is added. And the fourth endpoint creates the SAP user. Right now this is done via PowerShell script that invokes a SOAP service. This will be transformed in WEBCON to a native SOAP invoke,
Happy usage of your new knowledge! Please do not hesitate to ask questions and to add comments.