Skip to content

Commit e2716da

Browse files
author
ecfan
committed
Draft
1 parent 1d9f4f9 commit e2716da

File tree

2 files changed

+74
-122
lines changed

2 files changed

+74
-122
lines changed

articles/logic-apps/add-run-powershell-scripts.md

Lines changed: 74 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ This guide shows how to add the action in your workflow and add the PowerShell s
4343

4444
## Considerations
4545

46-
- The Azure portal saves your script as a PowerShell script file (.csx) in the same folder as your **workflow.json** file, which stores the JSON definition for your workflow, and deploys the file to your logic app resource along with the workflow definition. Azure Logic Apps compiles this file to make the script ready for execution.
46+
- The Azure portal saves your script as a PowerShell script file (.ps1) in the same folder as your **workflow.json** file, which stores the JSON definition for your workflow, and deploys the file to your logic app resource along with the workflow definition.
4747

48-
The .csx file format lets you write less "boilerplate" and focus just on writing a PowerShell function. You can rename the .csx file for easier management during deployment. However, each time you rename the script, the new version overwrites the previous version.
48+
The .ps1 format lets you write less "boilerplate" and focus just on writing PowerShell code. You can rename the .ps1 file for easier management during deployment. However, each time you rename the script, the new version overwrites the previous version.
4949

5050
- The script is local to the workflow. To use the same script in other workflows, [view the script file in the **KuduPlus** console](#view-script-file), and then copy the script to reuse in other workflows.
5151

@@ -60,86 +60,46 @@ This guide shows how to add the action in your workflow and add the PowerShell s
6060

6161
1. In the [Azure portal](https://portal.azure.com), open your Standard logic app resource and workflow in the designer.
6262

63-
1. In the designer, [follow these general steps to add the **Inline Code Operations** action named **Execute PowerShell Code action** to your workflow](create-workflow-with-trigger-or-action.md?tabs=standard#add-action).
63+
1. In the designer, [follow these general steps to add the **Inline Code Operations** action named **Execute PowerShell Code** to your workflow](create-workflow-with-trigger-or-action.md?tabs=standard#add-action).
6464

65-
1. After the action information pane opens, on the **Parameters** tab, in the **Code File** box, update the prepopluated sample code with your own script code.
65+
1. After the action information pane opens, on the **Parameters** tab, in the **Code File** box, update the prepopluated sample code with your own code.
6666

67-
- At the top of the script, [import the necessary namespaces](#import-namespaces) and [add any required assembly references](#add-assembly-references) as usual.
67+
- To access data coming from your workflow, see [Access trigger outputs, preceding action outputs, and your workflow](#access-trigger-action-outputs) later in this guide.
6868

69-
- Implement the **`Run`** method:
69+
- To return the script's results or other data to your workflow, see [Return data to your workflow](#return-data-to-workflow).
7070

71-
- The **`Run`** method name is predefined, and your workflow executes only by calling this **Run** method at runtime.
72-
73-
- To access data coming from your workflow, the **`Run`** method accepts this data through a parameter with **WorkflowContext** type. You can use the **WorkflowContext** object for the following tasks:
74-
75-
- [Access trigger outputs, preceding action outputs, and your workflow](#access-trigger-action-outputs).
76-
77-
- [Access environment variables and logic app setting values](#access-environment-variables-app-settings).
78-
79-
- To return the script's results or other data to your workflow, implement the **`Run`** method with a return type. For more information, see [Return data to your workflow](#return-data-to-workflow).
80-
81-
- To log the output from your script in PowerShell, implement the **`Run`** method to accept a function logger through a parameter with **`ILogger`** type, and use **`log`** as the argument name for easy identification. Avoid including **`Console.Write`** in your script.
82-
83-
> [!IMPORTANT]
84-
>
85-
> If you have a long-running script that requires graceful termination in case the function host shuts down,
86-
> include a cancellation token, which is required, with your function logger.
87-
88-
For more information, see the following sections:
89-
90-
- [Log output to a stream](#log-output-stream).
91-
92-
- [Log output to Application Insights](#log-output-application-insights).
71+
1. To review the workflow output in Application Insights, see [View output in Application Insights](#log-output-application-insights).
9372

9473
The following example shows the action's **Parameters** tab with the sample script code:
9574

96-
:::image type="content" source="media/add-run-csharp-scripts/action-sample-script.png" alt-text="Screenshot shows Azure portal, Standard workflow designer, Request trigger, Execute CSharp Script Code action with information pane open, and Response action. Information pane shows sample PowerShell script." lightbox="media/add-run-csharp-scripts/action-sample-script.png":::
75+
:::image type="content" source="media/add-run-powershell-scripts/action-sample-script.png" alt-text="Screenshot shows Azure portal, Standard workflow designer, Request trigger, Execute PowerShell Code action with information pane open, and Response action. Information pane shows sample PowerShell script." lightbox="media/add-run-powershell-scripts/action-sample-script.png":::
9776

9877
The following example shows the sample script code:
9978

100-
```csharp
101-
/// Add the required libraries.
102-
#r "Newtonsoft.Json"
103-
#r "Microsoft.Azure.Workflows.Scripting"
104-
using Microsoft.AspNetCore.Mvc;
105-
using Microsoft.Extensions.Primitives;
106-
using Microsoft.Extensions.Logging;
107-
using Microsoft.Azure.Workflows.Scripting;
108-
using Newtonsoft.Json.Linq;
109-
110-
/// <summary>
111-
/// Executes the inline PowerShell code.
112-
/// </summary>
113-
/// <param name="context">The workflow context.</param>
114-
/// <remarks> The entry-point to your code. The function signature should remain unchanged.</remarks>
115-
public static async Task<Results> Run(WorkflowContext context, ILogger log)
116-
{
117-
var triggerOutputs = (await context.GetTriggerResults().ConfigureAwait(false)).Outputs;
118-
119-
/// Dereferences the 'name' property from the trigger payload.
120-
var name = triggerOutputs?["body"]?["name"]?.ToString();
121-
122-
/// To get the outputs from a preceding action, you can uncomment and repurpose the following code.
123-
//var actionOutputs = (await context.GetActionResults("<action-name>").ConfigureAwait(false)).Outputs;
124-
125-
/// The following logs appear in the Application Insights traces table.
126-
//log.LogInformation("Outputting results.");
127-
128-
/// var name = null;
129-
130-
return new Results
131-
{
132-
Message = !string.IsNullOrEmpty(name) ? $"Hello {name} from CSharp action" : "Hello from CSharp action."
133-
};
134-
}
79+
```powershell
80+
# Use these cmdlets to retrieve outputs from prior steps
81+
# oldActionOutput = Get-ActionOutput -ActionName <name of old action>
82+
# oldTriggerOutput = Get-TriggerOutput
13583
136-
public class Results
137-
{
138-
public string Message {get; set;}
84+
$customResponse = [PSCustomObject]@{
85+
Message = "Hello world!"
13986
}
87+
88+
# Use Write-Host/ Write-Output/Write-Debug to log messages to application insights
89+
# Write-Host/Write-Output/Write-Debug and 'returns' will not return an output to the workflow
90+
# Write-Host "Sending to application insight logs"
91+
92+
# Use Push-WorkflowOutput to push outputs forward to subsequent actions
93+
Push-WorkflowOutput -Output $customResponse
14094
```
14195

142-
For more information, see ["#r" - Reference external assemblies](/azure/azure-functions/functions-reference-csharp?tabs=functionsv2%2Cfixed-delay%2Cazure-cli#referencing-external-assemblies).
96+
The following example shows a custom sample script:
97+
98+
```powershell
99+
$action = Get-TriggerOutput
100+
$results = "Hello from PowerShell!"
101+
Push-ActionOutputs -body $results
102+
```
143103

144104
1. When you're done, save your workflow.
145105

@@ -157,11 +117,11 @@ This guide shows how to add the action in your workflow and add the PowerShell s
157117

158118
1. Go to your logic app's root location: **site/wwwroot**
159119

160-
1. Go to your workflow's folder, which contains the .csx file, along this path: **site/wwwroot/{workflow-name}**
120+
1. Go to your workflow's folder, which contains the .ps1 file, along this path: **site/wwwroot/{workflow-name}**
161121

162122
1. Next to the file name, select **Edit** to open and view the file.
163123

164-
## Custom commandlets
124+
## Custom PowerShell commandlets
165125

166126
### Get-TriggerOutput
167127

@@ -179,7 +139,7 @@ None.
179139

180140
### Get-ActionOutput
181141

182-
Gets the output from another action in the workflow. This object is returned as a **PowershellWorkflowOperationResult**.
142+
Gets the output from another action in the workflow and returns an object named **PowershellWorkflowOperationResult**.
183143

184144
#### Syntax
185145

@@ -195,13 +155,20 @@ Get-ActionOutput [ -ActionName <String> ]
195155

196156
### Push-WorkflowOutput
197157

198-
Pushes an output to the workflow from the **Execute PowerShell Code** action. Please note values from Write-Host/Write-Debug/Write-Output will not be returned to the workflow. Returning a value with a ‘return’ statement will also not be returned to the workflow. Those commandlets can be used to write trace messages that can be viewed within application insights.
158+
Pushes output from the **Execute PowerShell Code** action to your workflow, which can pass back any object type. If the return value is null, you get a null object error from the commandlet.
159+
160+
> [!NOTE]
161+
>
162+
> The **Write-Host**, **Write-Debug**, and **Write-Output** commandlets don't return values to your workflow.
163+
> The **return** statement also doesn't return values to your workflow. However, you can use these commandlets
164+
> to write trace messages that appear in Application Insights.
199165
200166
#### Syntax
201167

202168
```azurepowershell
203-
Push-WorkflowOutput [-Output <Object>] [-Clobber]
169+
Push-WorkflowOutput [-Output <Object>] [-Clobber]
204170
```
171+
205172
#### Parameters
206173

207174
| Parameter | Type | Description |
@@ -213,61 +180,46 @@ Push-WorkflowOutput [-Output <Object>] [-Clobber]
213180

214181
## Access workflow trigger and action outputs in your script
215182

216-
To access data from your workflow, use the following methods available for the **`WorkflowContext`** context object:
217-
218-
- **`GetTriggerResults`** method
219-
220-
To access trigger outputs, use this method to return an object that represents the trigger and its outputs, which are available through the **`Outputs`** property. This object has **JObject** type, and you can use square brackets (**[]**) indexer to access various properties in the trigger outputs.
221-
222-
For example, the following sample code gets the data from the **`body`** property in the trigger outputs:
223-
224-
```csharp
225-
public static async Task<Results> Run(WorkflowContext context, ILogger log)
226-
{
227-
var triggerOutputs = (await context.GetTriggerResults().ConfigureAwait(false)).Outputs;
228-
var body = triggerOutputs["body"];
229-
}
230-
```
231-
232-
- **`GetActionResults`** method
233-
234-
To access action outputs, use this method to return an object that represents the action and its outputs, which are available through the **`Outputs`** property. This method accepts an action name as a parameter, for example:
183+
The output values from the trigger and preceding actions are returned using a custom object, which have multiple parameters. To access these outputs and make sure that you return the value that you want, use the [**Get-TriggerOutput**](#get-triggeroutput), [**Get-ActionOutput**](#get-actionoutput), and [**Push-WorkflowOutput**](#push-workflowoutput) commandlets plus any appropriate parameters described in the following table, for example:
235184

236-
```csharp
237-
public static async Task<Results> Run(WorkflowContext context, ILogger log)
238-
{
185+
```powershell
186+
$trigger = Get-TriggerOutput
187+
$statusCode = $trigger.status.ToString();
188+
$action = Get-ActionOutput -ActionName Compose
189+
$actionOutput = $action.outputs['actionOutput'].ToString();
190+
$populatedString = "Send the $statusCode for the trigger status and $actionOutputName."
239191
240-
var actionOutputs = (await context.GetActionResults("actionName").ConfigureAwait(false)).Outputs;
241-
var body = actionOutputs["body"];
242-
}
243-
```
244-
245-
<a name="access-environment-variables-app-settings"></a>
246-
247-
## Access environment variables or app setting value
192+
Push-WorkflowOutput -Output $populatedString
193+
```
248194

249-
To get an environment variable or an app setting value, use the **`System.Environment.GetEnvironmentVariable`** method, for example:
195+
> [!NOTE]
196+
>
197+
> In PowerShell, if you reference an object that has **JValue** type inside a complex object, and you
198+
> add that object to a string, you get a format exception. To avoid this error, use **ToString()**.
250199
251-
```csharp
252-
public static void Run(WorkflowContext context, ILogger log)
253-
{
254-
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
255-
log.LogInformation(GetEnvironmentVariable("AzureWebJobsStorage"));
256-
log.LogInformation(GetEnvironmentVariable("WEBSITE_SITE_NAME"));
257-
}
200+
### Parameters
258201

259-
public static string GetEnvironmentVariable(string name)
260-
{
261-
return name + ": " +
262-
System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
263-
}
264-
```
202+
| Parameter | Type | Description |
203+
|-----------|------|-------------|
204+
| **Name** | String | The name for the trigger or action. |
205+
| **Inputs** | JToken | The input values passed into the trigger or action. |
206+
| **Outputs** | JToken | The outputs from the executed trigger or action. |
207+
| **StartTime** | DateTime | The start time for the trigger or action. |
208+
| **EndTime** | DateTime | The end time for the trigger or action. |
209+
| **ScheduledTime** | DateTime | The scheduled time to run the trigger or action or trigger. |
210+
| **OriginHistoryName** | String | The origin history name for triggers with the **Split-On** option enabled. |
211+
| **SourceHistoryName** | String | The source history name for a resubmitted trigger. |
212+
| **TrackingId** | String | The operation tracking ID. |
213+
| **Code** | String | The status code for the result. |
214+
| **Status** | String | The run status for the trigger or action, for example, **Succeeded** or **Failed**. |
215+
| **Error** | JToken | The HTTP error code. |
216+
| **TrackedProperties** | JToken | Any tracked properties that you set up. |
265217

266218
<a name="return-data-to-workflow"></a>
267219

268-
## Return data to your workflow
269-
220+
## Return outputs to your workflow
270221

222+
To return any outputs to your workflow, you must use the [**Push-WorkflowOutput** commandlet](#push-workflowoutput).
271223

272224
<a name="log-output-application-insights"></a>
273225

@@ -296,7 +248,7 @@ PowerShell modules are self-contained, reusable units that include various com
296248
- Variables: Store data for use within the module.
297249
- Other types of resources.
298250

299-
Modules organize and make it easier to distribute PowerShell code. You can use modules to package related functionality together, making it more manageable and shareable. The **Execute PowerShell Code** action lets you automatically import both public and private PowerShell modules.
251+
A module organizes PowerShell code, making it easier to distribute. For example, you can create your own modules to package and make related functionality more manageable and shareable. The **Execute PowerShell Code** action lets you import both public and private PowerShell modules.
300252

301253
## Public modules
302254

@@ -380,11 +332,11 @@ In this release, the web-based editor includes limited IntelliSense support, whi
380332

381333
Make sure that you use **Push-WorkflowOutput**.
382334

383-
### Execute PowerShell Code action fails: "The term 'Hello-World' is not recognized..."
335+
### Execute PowerShell Code action fails: "The term '{some-text}' is not recognized..."
384336

385337
If you incorrectly add your module to the **requirements.psd1** file or when your private module doesn't exist in the following path: **C:\home\site\wwwroot\Modules\{moduleName}, you get the following error:
386338

387-
**The term 'Hello-World' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name or if a path was included, verify the path is correct and try again.**
339+
**The term '{some-text}' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name or if a path was included, verify the path is correct and try again.**
388340

389341
### Execute PowerShell Code action fails: "Cannot bind argument to parameter 'Output' because it is null."
390342

90.2 KB
Loading

0 commit comments

Comments
 (0)