> For the complete documentation index, see [llms.txt](https://cortex-docs.paloaltonetworks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cortex-docs.paloaltonetworks.com/cortex-xsiam-developer-guide/cortex-xsiam-development-guide/integrations-and-scripts/developing/powershell.md).

# PowerShell

PowerShell integrations and scripts are executed using PowerShell Core. PowerShell Core v6.2 and higher is supported.

<details>

<summary>Docker images</summary>

Similar to Python, PowerShell integrations and scripts run in a Docker container. All of the Docker images that support PowerShell are named with a prefix of either `demisto/powershell` or `demisto/pwsh`. If you need to create a new image follow the instructions at demisto/dockerfiles project: <https://github.com/demisto/dockerfiles>.

</details>

<details>

<summary>Directory structure</summary>

Similar to Python, PowerShell integrations and scripts should follow the same [directory structure](/cortex-xsiam-developer-guide/cortex-xsiam-development-guide/integrations-and-scripts/components/integration-directory-structure.md) as Python integrations and scripts, with one difference: unit test files must be named: `<IntegrationFileName>.Tests.ps1`, following the [Pester unit testing](https://pester.dev/docs/quick-start) naming convention. You can use `demisto-sdk split` to convert an exported PowerShell integration or script to the correct directory structure. For more information, see the [Demisto SDK](https://app.gitbook.com/s/nozw5MT5S8KZD2eF8roV/demisto-sdk-commands/split).

</details>

<details>

<summary>Linting</summary>

PSScriptAnalyzer is used for linting and static code analysis of PowerShell integrations and scripts. If you receive a false positive from the Analyzer, you can suppress the rule by decorating the function/script with `SuppressMessageAttribute`. Specify a `Justification` in the attribute as to why the suppression is necessary. An example usage of suppression can be seen in [CommonServerPowerShell.ps1](https://github.com/demisto/content/blob/master/Packs/Base/Scripts/CommonServerPowerShell/CommonServerPowerShell.ps1). For more information about PSScriptAnalyzer suppression, see the [PSScriptAnalyzer documentation](https://github.com/PowerShell/PSScriptAnalyzer) .

</details>

<details>

<summary>Unit testing</summary>

The Python unit testing guidelines also apply for PowerShell. Unit tests should avoid performing communication with external APIs and should instead use mocking when possible. Testing actual interaction with external APIs should be performed via [Test Playbooks](/cortex-xsiam-developer-guide/cortex-xsiam-development-guide/testing/test-playbooks.md). For running unit tests we use [Pester](https://pester.dev/).

**Import CommonServerPowerShell.ps1**

Your code must import `CommonServerPowerShell.ps1` by adding the following to the beginning of the file:

```programlisting
. $PSScriptRoot\CommonServerPowerShell.ps1
```

When the integration or script code is unified by demisto-sdk for deployment to the instance the import line is automatically removed.

**Use Main in integration/script code**

When writing unit tests you import the integration or script file from the `*.Tests.ps1` file. Therefore, the file must be written so that it will not execute when it is imported. This can be done with a simple `Main` function which is called depending on how the file was executed. Adding the following code ensures the script is not run when imported by the unit tests:

```programlisting
# Execute Main when not in Tests
if ($MyInvocation.ScriptName -notlike "*.Tests.ps1") {
    Main
}
```

**Write unit tests**

All unit tests should be written in a separate PowerShell file named `<IntegrationFileName>.Tests.ps1`. The unit test file should import the integration or script code file by adding the following line at the beginning of the file:

```programlisting
. $PSScriptRoot\<IntegrationFileName>.ps1
```

Group related unit tests using the `Describe` block. Use `Context` for grouping tests that use the same mock logic. Write your tests using the `It` command. Example unit tests can be seen for the [VerifyJSON script](https://github.com/demisto/content/tree/master/Packs/CommonScripts/Scripts/VerifyJSON). For more details, see the [Pester documentation](https://pester.dev/docs/quick-start).

**Mocking**

Pester supports mocking PowerShell functions. You can mock any function defined in `CommonServerPowerShell.ps1` and functions included in standard PowerShell and imported modules. Pester doesn't support mocking object methods. This includes methods of the `$demisto` object. You can, however, modify the `$demisto` object properties in a test. For example, you can set the `ContextArgs` property to control the return of `$demisto.Args()` method. Example code:

```programlisting
$demisto.ContextArgs = @{arg1 = 'val1' }
```

In addition, you can mock functions called by the `$demisto` object. For example, you can mock `DemistoServerLog` which is called by the `$demisto` object methods: `Info, Debug, Error`. Example of mocking can be seen for the [VerifyJSON script](https://github.com/demisto/content/tree/master/Packs/CommonScripts/Scripts/VerifyJSON) script. See more information about [mocking with Pester](https://pester.dev/docs/usage/mocking).

</details>

<details>

<summary>Run lint and test</summary>

**Run with Docker (demisto-sdk)**

The build runs the unit tests within the Docker image that the integration/script runs with. We recommend using this method to run linting and test as it uses the same environment (Docker container) with all modules and operating system dependencies that are used by the integration/script. To run both linting and testing run: `demisto-sdk pre-commit -i <path to code directory>`.

For example: `demisto-sdk pre-commit -i Packs/Legacy/Scripts/VerifyJSON`

{% hint style="info" %}

### Note

You can skip PSScriptAnalyzer or unit testing using the command line parameters `--no-pwsh-analyze` and `--no-pwsh-test`.
{% endhint %}

**PowerShell command line**

As a prerequisite, verify you have installed [Pester](https://pester.dev/docs/introduction/installation), [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer#installation) and all dependent modules.

Run `demisto-sdk pre-commit -i ...` to copy `CommonServerPowerShell.ps1` and `demistomock.ps1` to the integration/script directory. Enter the pwsh console and go to the integration/script directory.

To run unit tests use Pester: `Invoke-Pester`.

To run PSScriptAnalyzer: `Invoke-ScriptAnalyzer -Path <code file>`

Check the command help for information on how to specify which tests to run.

Sample output:

![pwsh-lint-cmd-output.png](/files/4ZOoL6mbU3eKE7nizcSo)

</details>

<details>

<summary>VS Code IDE</summary>

We recommend using VS Code as your PowerShell editor. The [PowerShell Extension](https://code.visualstudio.com/docs/languages/powershell) developed by Microsoft comes with built-in support for PSScriptAnalyzer and Pester unit testing (including debugging).

Sample output of PSScriptAnalyzer in VS Code alerting about an unused variable:

![vs-code-pwsh-analyazer.png](/files/XGpRsKDQpxC36QbN3TX8)

Sample debug session using VS Code:

![vscode-pwsh-debug.gif](/files/opWLATPD8Y49qyjGjKMi)

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cortex-docs.paloaltonetworks.com/cortex-xsiam-developer-guide/cortex-xsiam-development-guide/integrations-and-scripts/developing/powershell.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
