Home > Net >  Call Windows executable from PowerShell script, passing all arguments
Call Windows executable from PowerShell script, passing all arguments

Time:09-06

I've looked all over, and I can't find the answer. If this is a duplicate, please point me to the question, but most things I've seen have answers that go around in circles and talk bout all sorts of complicated things with no direct answer.

My question is simple. I have the following Windows batch file foo.bat:

@ECHO OFF
bar.exe %*

If I call foo.bat foobar 123 from the command line, it invokes bar.exe foobar 123. This works with no command-line arguments. This works with multiple command-line arguments.

What is the equivalent PowerShell script that does basically the same thing: invoke another executable, passing all CLI parameters the user provided?

I wouldn't expect this would be difficult, but I sure can't find any straightforward answer.

CodePudding user response:

The PowerShell equivalent of your foo.bat file is:

bar.exe @args

PowerShell exposes all (unbound) positional arguments[1] as an array stored in the automatic $args variable.

By prefixing $args with @ instead of $, argument splatting is employed, which means that the elements of the $args array are passed as individual arguments to bar.exe

  • Note: This isn't strictly necessary when calling external programs (such as bar.exe) - $args would work there too - but is more versatile in that it can also pass named arguments correctly through to other PowerShell commands, which typically have declared parameters that can be bound by name (e.g., -Path C:\temp to bind value C:\temp to declared parameter -Path)

As for working with $args in general:

  • $args.Count tells you how many (unbound) positional arguments were passed,
  • $args[0] returns the first such argument, $args[1] the second, and so on.

However, it is usually preferable to formally declare parameters in PowerShell scripts and functions, which can then also be bound by name (e.g., -FooParam foo instead of just foo). See this answer for more information.


[1] If your script doesn't formally declare any parameters (via a param(...) block - see about_Scripts and the linked answer), all arguments are by definition unbound (i.e. not mapped to a declared parameter) and positional (not prefixed by a target parameter name). However, if your script does declare parameters, $args only contains those arguments, if any, that were passed in addition to those binding to declared parameters. If your script is an advanced script (or function), $args isn't supported at all, because passing unbound arguments is then categorically prevented. See this answer for more information.

  • Related