I have a script that reads a configuration file that results in a set of name value pairs that I would like to pass as arguments to a function in a second PowerShell script.
I do not know what parameters will be placed in this configuration file at design time, so right at the point where I need to invoke this second PowerShell script, I basically just have one variable that has the path to this second script, and a second variable that is an array of arguments to pass to the script identified in the path variable.
So the variable containing the path to the second script ($scriptPath
), might have a value like:
"c:\the\path\to\the\second\script.ps1"
The variable containing the arguments ($argumentList
) might look something like:
-ConfigFilename "doohickey.txt" -RootDirectory "c:\some\kind\of\path" -Max 11
How do I get from this state of affairs to the execution of script.ps1 with all of the arguments from $argumentList?
I'd like any write-host commands from this second script to be visible to the console from which this first script is invoked.
I have tried dot-sourcing, Invoke-Command, Invoke-Expression, and Start-Job, but I haven't found an approach that doesn't produce errors.
For example, I thought the easiest first route was to try Start-Job called as follows:
Start-Job -FilePath $scriptPath -ArgumentList $argumentList
...but this fails with this error:
System.Management.Automation.ValidationMetadataException:
Attribute cannot be added because it would cause the variable
ConfigFilename with value -ConfigFilename to become invalid.
...in this case, "ConfigFilename" is the first parameter in the param list defined by the second script, and my invocation is apparently trying to set its value to "-ConfigFilename", which is obviously intended to identify the parameter by name, not set its value.
What am I missing?
EDIT:
Ok, here is a mock-up of the to-be-called script, in a file named invokee.ps1
Param(
[parameter(Mandatory=$true)]
[alias("rc")]
[string]
[ValidateScript( {Test-Path $_ -PathType Leaf} )]
$ConfigurationFilename,
[alias("e")]
[switch]
$Evaluate,
[array]
[Parameter(ValueFromRemainingArguments=$true)]
$remaining)
function sayHelloWorld()
{
Write-Host "Hello, everybody, the config file is <$ConfigurationFilename>."
if ($ExitOnErrors)
{
Write-Host "I should mention that I was told to evaluate things."
}
Write-Host "I currently live here: $gScriptDirectory"
Write-Host "My remaining arguments are: $remaining"
Set-Content .\hello.world.txt "It worked"
}
$gScriptPath = $MyInvocation.MyCommand.Path
$gScriptDirectory = (Split-Path $gScriptPath -Parent)
sayHelloWorld
...and here is a mock-up of the calling script, in a file named invoker.ps1:
function pokeTheInvokee()
{
$scriptPath = (Join-Path -Path "." -ChildPath "invokee.ps1")
$scriptPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($scriptPath)
$configPath = (Join-Path -Path "." -ChildPath "invoker.ps1")
$configPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($configPath)
$argumentList = @()
$argumentList += ("-ConfigurationFilename", "`"$configPath`"")
$argumentList += , "-Evaluate"
Write-Host "Attempting to invoke-expression with: `"$scriptPath`" $argumentList"
Invoke-Expression "`"$scriptPath`" $argumentList"
Invoke-Expression ".\invokee.ps1 -ConfigurationFilename `".\invoker.ps1`" -Evaluate
Write-Host "Invokee invoked."
}
pokeTheInvokee
When I run invoker.ps1, this is the error I'm currently getting on the first call to Invoke-Expression:
Invoke-Expression : You must provide a value expression on
the right-hand side of the '-' operator.
The second call works just fine, but one significant difference is that the first version is using arguments whose paths have spaces in them, and the second does not. Am I mishandling the presence of spaces in these paths?