If you construct a string such as -t foo and pass it via a variable to an external program, it is passed as a single, double-quoted argument (that is, donet will literally see "-t foo" on its command line) - and therefore won't be recognized as parameter name-value combination.
You must pass -t and foo separately, as elements of an array instead.
When you use an array as an argument for an external program, PowerShell passes the array elements as individual, space-separated arguments:
# Create an array such as '-t', 'foo', '-t', 'bar', ...
$tableArgs =
$tables | ForEach-Object {
'-t', "$_"
}
# Note the use of $tableArgs as-is, which causes PowerShell to pass
# e.g. ... -t foo -t bar ... behind the scenes.
dotnet ef dbcontext scaffold $strConn Npgsql.EntityFrameworkCore.PostgreSQL --context MyModel $tableArgs -v -f
To provide a simpler example: The equivalent of foo -s -o "bar baz" file1 is:
$a = @('-s', '-o', 'bar baz', 'file1') # construct the array of arguments
foo $a # or: foo @a
As the first code snippet implies, you're free to mix explicitly specified arguments with those provided via an array.
As an aside:
If the array containing the argument is stored in a variable, you may alternatively use splatting, i.e yo may pass @tableArgs (@ instead of $). However, given that with external programs and arrays this is the same as passing an array (variable) directly, there is no strict advantage in doing so, though you may prefer the @ sigil for conceptual clarity.
- However, (explicit) splatting with
@ is necessary in order to pass programmatically constructed arguments to PowerShell commands, where it is more commonly based on a hashtable whose keys identify the target parameters, which enables passing named arguments.
On a general note: Whether or not you pass arguments literally, via variables, or by way of an array, PowerShell's passing of arguments with embedded " chars. as well as passing the empty string as an argument to external programs is broken in Windows PowerShell and PowerShell (Core) 7 up to v7.2.x, and requires workarounds - see this answer for details.
Invoke-Expressionif you want to execute a command line from a string.Invoke-Expressiontechnically works, it is generally best avoided, as there are usually superior - and safer - alternatives. Indeed, constructing the arguments as individual elements of an array is the preferable solution here.