Mathias R. Jessen's helpful answer provides an effective solution, but let me expand on the explanation:
The PowerShell SDK's .AddScript()
method is somewhat poorly named in that it doesn't execute a script file, but an arbitrary piece of PowerShell code. That is, it expects a string containing entire PowerShell statements, in other words: the contents of a script file - not the script file's path.
Given that in PowerShell a piece of reusable code is represented as a script block, something like .AddScriptBlock()
would be a less confusing name (though note that you must not enclose the string containing the statements to execute in { ... }
when you call .AddScript()
).[1]
Mathias's answer shows how .AddCommand()
is the right method to use, because a command in PowerShell is anything that represents something that can be directly executed: aliases, functions, cmdlets, external executables - and also script files.
As for what you tried:
String d:\test.ps1
is interpreted as a piece of PowerShell code (the same way it would be if you submitted this string on the command line). That code happens to call a script file, but does so without arguments.
That is, your script was called, but without the parameter you added via .AddParameter()
.
- Also note that if the script path happened to contain spaces or embedded variable references, you'd have to use embedded quoting and call the result via
&
, the call operator; e.g.,
.AddScript(@"& 'd:\test 1.ps1'");
- see this answer to a closely related question for details.
However, note that your .AddParameter()
call technically still worked, but it was the script block as a whole that received the parameter, not the (one) statement inside it - the call to d:\test.ps1
.[2]
Technically, it would have been possible to relay the arguments to the script-file invocation, by way of splatting the automatic $args
variable (in which all arguments are collected, in the absence of explicit parameter declarations via a param(...)
block):
ps.AddScript(@"d:\test.ps1 @args");
That said, if all your code does is to invoke a single script file (with arguments), the .AddCommand()
solution is both simpler and more efficient.
As an aside: .AddScript()
, unlike .AddCommand()
, is not subject to the executing machine's PowerShell execution policy, assuming that the statements passed don't try to invoke script files; that is, statements composed only of expressions and commands other than script files (*.ps1
) execute irrespective of what execution policy is in effect, though note that some modules automatically try to execute script files on import.
[1] .AddScript("...")
, expressed in PowerShell code, effectively does the following:
. { ... }
That is, it parses the string as a script block, and executes it via .
, the dot-sourcing operator (when .Invoke()
is later called).
[2] As stated, what you pass to .AddScript()
is parsed into a script block, and script blocks - like functions and script files - can accept arguments, both positionally via the automatic $args
variable and - with explicitly declared parameters via a param(...)
block - named. To use a simple example: .AddScript('Write-Output $args[0]').AddArgument('foo')
is the equivalent of . { Write-Output $args[0] } 'foo'