# Set PowerBrick Parameters Dynamically

> Use an Execute PowerShell Snippet brick to work out a value on each device and pass it to a later PowerBrick as a parameter value.

Source: https://docs.capaone.com/capaone/application-manager/powerbricks/dynamic-parameter-values/  
Product: CapaOne — a separate CapaSystems product; do not apply this page to any other.

A value you type into a PowerBrick parameter is applied unchanged to every device the package runs on. When devices need different values — depending on location, model, serial number, or what's already installed — you can calculate the value on the device instead. One package then covers every variant, and you don't have to maintain one package per site or model.

The pattern has two parts:

1. An [Execute PowerShell Snippet](/capaone/application-manager/powerbricks/bricks/execute-powershell-snippet/) brick works out the value and stores it in a global variable, for example `$global:WifiProfilePath`.
2. A later brick in the same sequence uses that variable as its parameter value.

The pattern works with any PowerBrick.

:::note[Before you start]
- You can create or edit a Script or Company App in **Application Manager**. See [Create a Script](/capaone/application-manager/create-a-script/).
- You know enough PowerShell to write the logic that picks the value.
:::

## How the value reaches the next brick

CapaOne combines all the bricks in an **Install** sequence into one PowerShell script and runs them in order, in the same PowerShell session. A global variable that one brick sets is still there when the next brick runs. The **Uninstall** sequence is a separate script, so a variable set during Install isn't available during Uninstall.

Each snippet runs inside its own PowerShell function. Use the `$global:` prefix every time you set the variable — a variable without it is gone as soon as the snippet ends.

## Parameters that accept a variable

You can use a variable in any parameter where you type free text, such as a path, name, or value field. CapaOne writes the parameter value into the script in double quotes, so PowerShell replaces the variable with its value when the brick runs.

A variable doesn't work in these parameter types:

- **On/off switches** — the value is always on or off.
- **Number fields** — the field accepts digits only.
- **Drop-down lists** — you can only pick one of the listed values.
- **Password fields** — the text you type is encoded and passed to the brick as it is, so a variable name is never replaced with its value. Type the password directly in the field.

Type the variable name on its own, for example `$global:MsiPath`. These forms aren't replaced with a value:

- A property or index, such as `$global:Device.Name` or `$global:Paths[0]`. Store the exact value in its own variable in the snippet instead.
- A subexpression or braces, such as `$($global:MsiPath)` or `${global:MsiPath}`.

You can combine a variable with fixed text, for example `$global:SiteFolder\Setup.msi`.

## Set a parameter value from a snippet

1. Open the Script or Company App and go to the PowerBricks editor.
2. Add an **Execute PowerShell Snippet** brick to the sequence.
3. In **PowerShell Snippet**, write the logic and assign the result to a global variable. If the snippet can't find a value for the device, stop the package with [`Exit-PSScript`](/capainstaller/powerpacks/exit-psscript/) so the log shows why.
4. Add the brick that needs the value **below** the snippet. Bricks run from top to bottom, so the snippet must come first.
5. In the parameter that should get the value, type the variable name exactly as you set it, for example `$global:WifiProfilePath`.
6. Save the package.

When the package runs, the later brick receives the value the snippet calculated on that device.

The snippet has the full CapaSystems PowerShell Scripting Library (`$cs.*` helpers) and the [PowerPack global variables](/capainstaller/powerpacks/powerpack-global-variables/). Files you upload to the package are in the folder `$Packageroot`. Add the [Download Content](/capaone/application-manager/powerbricks/bricks/download-content/) brick before the snippet if the snippet or a later brick uses those files.

## Examples

### Pick a Wi-Fi profile by location

One package deploys the right Wi-Fi profile to devices at three offices. Each office has its own exported profile file, and the office is identified by the first letters of the computer name.

1. Create a Script and upload the three profile files: `Copenhagen.xml`, `Aarhus.xml`, and `Odense.xml`.
2. Add a **Download Content** brick to the **Install** sequence.
3. Add an **Execute PowerShell Snippet** brick below it, with this code:

   ```powershell
   # Map the computer name prefix to the office profile file
   switch -Wildcard ($env:COMPUTERNAME) {
       'CPH-*' { $global:WifiSite = 'Copenhagen' }
       'AAR-*' { $global:WifiSite = 'Aarhus' }
       'ODE-*' { $global:WifiSite = 'Odense' }
   }

   if ([string]::IsNullOrWhiteSpace($global:WifiSite)) {
       Exit-PSScript -exitcode 1 -exitmessage "No Wi-Fi profile is defined for device $env:COMPUTERNAME."
   }

   $global:WifiProfilePath = "$Packageroot\$global:WifiSite.xml"
   $cs.Job_WriteLog("Selected Wi-Fi profile: $global:WifiProfilePath")
   ```

4. Add an **Import Wifi Profile** brick below the snippet.
5. In **Profile File Path**, replace the default value with `$global:WifiProfilePath`.
6. Save the Script and assign it to the devices.

| Order | PowerBrick | Parameter value |
| --- | --- | --- |
| 1 | Download Content | — |
| 2 | Execute PowerShell Snippet | The code above |
| 3 | Import Wifi Profile | **Profile File Path**: `$global:WifiProfilePath` |

Each device imports the profile for its own office. A device whose name doesn't match a prefix stops with exit code `1`, and the log names the device. To support a new office, upload its profile file and add one line to the `switch` block.

### Place the computer in an OU by network

One domain-join package places each computer in the organizational unit (OU) for its site. The site is identified by the IP address the device has on the local network.

1. Add an **Execute PowerShell Snippet** brick to the **Install** sequence, with this code:

   ```powershell
   # Find the IPv4 address on the adapter that has a default gateway
   $IpAddress = (Get-NetIPConfiguration |
       Where-Object { $_.IPv4DefaultGateway } |
       Select-Object -First 1).IPv4Address.IPAddress

   switch -Wildcard ($IpAddress) {
       '10.1.*' { $global:DomainOU = 'OU=Copenhagen,OU=Computers,DC=contoso,DC=local' }
       '10.2.*' { $global:DomainOU = 'OU=Aarhus,OU=Computers,DC=contoso,DC=local' }
   }

   if ([string]::IsNullOrWhiteSpace($global:DomainOU)) {
       Exit-PSScript -exitcode 1 -exitmessage "No OU is defined for IP address $IpAddress."
   }

   $cs.Job_WriteLog("Selected OU: $global:DomainOU")
   ```

2. Add a **Join Domain** brick below the snippet.
3. Fill in the domain account, **Password**, **Domain Name**, and **Preferred Domain Controller** as usual.
4. In **OU Path**, type `$global:DomainOU`.

| Order | PowerBrick | Parameter value |
| --- | --- | --- |
| 1 | Execute PowerShell Snippet | The code above |
| 2 | Join Domain | **OU Path**: `$global:DomainOU` |

Each computer object is created in the OU for the site the device is on when the package runs.

### Install the MSI that matches the processor architecture

One Company App installs the 64-bit MSI on 64-bit Windows and the 32-bit MSI on 32-bit Windows.

1. Create a Company App and upload both installers: `Setup-x64.msi` and `Setup-x86.msi`.
2. Add a **Download Content** brick to the **Install** sequence.
3. Add an **Execute PowerShell Snippet** brick below it, with this code:

   ```powershell
   if ([Environment]::Is64BitOperatingSystem) {
       $global:MsiPath = "$Packageroot\Setup-x64.msi"
   } else {
       $global:MsiPath = "$Packageroot\Setup-x86.msi"
   }

   $cs.Job_WriteLog("Selected installer: $global:MsiPath")
   ```

4. Add an **Install MSI** brick below the snippet.
5. In **MSI Path**, replace the default value with `$global:MsiPath`.

| Order | PowerBrick | Parameter value |
| --- | --- | --- |
| 1 | Download Content | — |
| 2 | Execute PowerShell Snippet | The code above |
| 3 | Install MSI | **MSI Path**: `$global:MsiPath` |

### Write the department to the registry from an asset list

One package writes each device's department to the registry, so other tools and scripts can read it. The department comes from a CSV file that maps serial numbers to departments.

1. Create a Script and upload `Assets.csv` with the columns `SerialNumber` and `Department`:

   ```text
   SerialNumber,Department
   5CD1234ABC,Finance
   5CD5678DEF,Sales
   ```

2. Add a **Download Content** brick to the **Install** sequence.
3. Add an **Execute PowerShell Snippet** brick below it, with this code:

   ```powershell
   $SerialNumber = (Get-CimInstance -ClassName Win32_BIOS).SerialNumber.Trim()
   $Asset = Import-Csv -Path "$Packageroot\Assets.csv" |
       Where-Object { $_.SerialNumber -eq $SerialNumber }

   if (-not $Asset) {
       Exit-PSScript -exitcode 1 -exitmessage "Serial number $SerialNumber is not in Assets.csv."
   }

   $global:Department = $Asset.Department
   $cs.Job_WriteLog("Department for $SerialNumber`: $global:Department")
   ```

4. Add a **Set Registry Value** brick below the snippet, with these values:
   - **Registry Hive:** `HKEY_LOCAL_MACHINE`
   - **Registry Variable Type:** `String`
   - **Registry Key:** `SOFTWARE\Contoso\Asset`
   - **Registry Variable Name:** `Department`
   - **Registry Variable Value:** `$global:Department`

| Order | PowerBrick | Parameter value |
| --- | --- | --- |
| 1 | Download Content | — |
| 2 | Execute PowerShell Snippet | The code above |
| 3 | Set Registry Value | **Registry Variable Value**: `$global:Department` |

When a device changes department, update `Assets.csv` in the package and redeploy it.
