19

How do you call a PowerShell script which takes named arguments from within a PowerShell script?

foo.ps1:

param(
[Parameter(Mandatory=$true)][String]$a='',
[Parameter(Mandatory=$true)][ValidateSet(0,1)][int]$b, 
[Parameter(Mandatory=$false)][String]$c=''
)
#stuff done with params here

bar.ps1

#some processing
$ScriptPath = Split-Path $MyInvocation.InvocationName
$args = "-a 'arg1' -b 2"
$cmd = "$ScriptPath\foo.ps1"

Invoke-Expression $cmd $args

Error:

Invoke-Expression : A positional parameter cannot be found that accepts 
argument '-a MSFT_VirtualDisk (ObjectId = 
"{1}\\YELLOWSERVER8\root/Microsoft/Windo...).FriendlyName -b 2'

This is my latest attempt - I've tried multiple methods from googling none seem to work.

If I run foo.ps1 from the shell terminal as ./foo.ps1 -a 'arg1' -b 2 it works as expected.

wonea
  • 4,783
  • 17
  • 86
  • 139
Chris L
  • 2,262
  • 1
  • 18
  • 33
  • 1
    While you did find an answer to this specific issue, best practices would suggest functions rather "loose code" in a file, and even better, modules (.psm1 files). And try to avoid Invoke-Expression (see [Invoke-Expression Considered Harmful](http://bit.ly/1kGYFf5) ). – Michael Sorens Aug 15 '14 at 15:20

2 Answers2

25

After posting the question I stumbled upon the answer. For completeness here it is:

bar.ps1:

#some processing
$ScriptPath = Split-Path $MyInvocation.InvocationName
$args = @()
$args += ("-a", "arg1")
$args += ("-b", 2)
$cmd = "$ScriptPath\foo.ps1"

Invoke-Expression "$cmd $args"
Chris L
  • 2,262
  • 1
  • 18
  • 33
  • You have syntactic error in your answer - on this line $args += ("-b" 2) missing comma between "-b" and 2. – honzakuzel1989 Apr 14 '16 at 07:17
  • Chosen value 2 for parameter "-b" is not suitable because foo.ps1 contains ValidateSet with values 0,1. – honzakuzel1989 Apr 14 '16 at 07:19
  • 1
    Nice and clean :). Wasted allot of time trying to pass the args :/. – Drasius Jun 17 '16 at 05:55
  • 1
    I have argument $dirPath with has spaces in path. Example: "D:\work dir\app". And it throws an error when passing like this: $args += ("-appDir", "$dirPath"). I get error: "The term 'D:\work' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct an d try again." How to pats path with spaces? – Drasius Jun 17 '16 at 08:17
  • I did work around ('Set-Location' ..) suggested in this page http://stackoverflow.com/questions/18537098/spaces-cause-split-in-path-with-powershell – Drasius Jun 17 '16 at 10:12
  • A note: `$args` is an automatic variable and should **not** be used as a variable name. Additionally, `Invoke-Expression` is vulnerable to exploits and you should utilize the call operator `&` – Maximilian Burszley Dec 21 '17 at 16:36
8

Here is something that might help future readers:

foo.ps1:

param ($Arg1, $Arg2)

Make sure to place the "param" code at the top before any executable code.

bar.ps1:

& "path to foo\foo.ps1" -Arg1 "ValueA" -Arg2 "ValueB"

That's it !

phi1.614
  • 81
  • 2
  • 5