Calling an executable from PowerShell is easy - most of the time, you just put an &
in front. To illustrate, let’s take this C# executable:
static void Main(string[] args)
{
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine("[" + i + "] = '" + args[i] + "'");
}
}
If we call it like this:
& .\Argsy.exe arg1 "argument 2"
We get:
[0] = 'arg1'
[1] = 'argument 2'
PowerShell variables can also be passed to arguments:
$myvariable = "argument 2"
& .\Argsy.exe arg1 $myvariable
# Output:
[0] = 'arg1'
[1] = 'argument 2'
Note that the value of $myvariable
contained a space, but PowerShell was smart enough to pass the whole value as a single argument.
This gets tricky when you want to conditionally or dynamically add arguments. For example, you might be tempted to try this:
$args = ""
$environments = @("My Environment", "Production")
foreach ($environment in $environments)
{
$args += "--environment "
$args += $environment + " "
}
& .\Argsy.exe $args
However, you’ll be disappointed with the output:
[0] = '--environment My Environment --environment Production '
The right way
The way to do this instead is to create an array. You can still use the +=
syntax in PowerShell to build the array:
$args = @() # Empty array
$environments = @("My Environment", "Production")
foreach ($environment in $environments)
{
$args += "--environment"
$args += $environment
}
& .\Argsy.exe $args
Which outputs what we’d expect:
[0] = '--environment'
[1] = 'My Environment'
[2] = '--environment'
[3] = 'Production'
You can also mix regular strings with arrays:
& .\Argsy.exe arg1 "argument 2" $args
# Output:
[0] = 'arg1'
[1] = 'argument 2'
[2] = '--environment'
[3] = 'MyEnvironment'
[4] = '--environment'
[5] = 'Production'
Edge case
There’s is a very odd edge case to what I said above about passing a single string with all the arguments. Take this example, which is similar to the one above:
$args = "--project Foo --environment My Environment --environment Production"
& .\Argsy.exe $args
# Output:
[0] = '--project Foo --environment My Environment --environment Production'
To make it work as intended, just put a quote around the first argument, and the behavior changes completely! (The backticks are PowerShell’s escape characters)
$args = "`"--project`" Foo --environment My Environment --environment Production"
& .\Argsy.exe $args
# Output:
[0] = '--project'
[1] = 'Foo'
[2] = '--environment'
[3] = 'My'
[4] = 'Environment'
[5] = '--environment'
[6] = 'Production'
The behavior doesn’t change if the first argument isn’t quoted:
$args = "--project `"Foo`" --environment My Environment --environment Production"
& .\Argsy.exe $args
# Output:
[0] = '--project Foo --environment My Environment --environment Production'
Ahh, PowerShell. Always full of surprises!
Tags:
Related posts

TEMP% has different values for a Windows Service running as Local System
You probably already know that Environment variables can be defined at either machine scope, or user scope. The value at the user scope typically overrides the value defined at machine scope.

PowerShell and exit code 0
Octopus Deploy has had two different ways to execute PowerShell scripts. Initially, we hosted PowerShell inside an AppDomain and invoked a pipeline.

Improving PowerShell compatibility
Octopus allows PowerShell scripts to be executed during a deployment. PowerShell is incredibly powerful and makes a great tool for deployment automation, so it's a feature we rely on heavily.