In short, I'm just looking for the PowerShell equivalent of how a batch file can call a script with the same parameters...
"%~dpnx0" %*
...where "%~dpnx0" expands to the absolute path of the script and %* is expanded to the list of parameters. Is there an easy way to replicate %*? Or, at least, a way that works?
I have a PowerShell script that uses the System.Data.OleDb namespace to read data from an Excel workbook. Because there is no 64-bit implementation of the Microsoft Jet provider, the script needs to be run from a 32-bit PowerShell session. Rather than simply having the script fail with an error message if it's run from a 64-bit session, I'd like to have the 64-bit session invoke the script in and retrieve the results from a 32-bit session. I found that this can be done using the Start-Job cmdlet with the -RunAs32 switch, however I'm having trouble providing a value for the -ArgumentList parameter.
I came up with the following to search for whichever script parameters have values and build a command line out of them:
function GetValueText([Object] $value)
{
[String] $text = if ($value -eq $null) {
'$null';
} elseif ($value -is [String]) {
"'$value'";
} elseif ($value -is [Array]) {
'@({0})' -f (($value | ForEach-Object { GetValueText $_ }) -join ', ');
} else {
"$value";
}
return $text;
}
if ([IntPtr]::Size -gt 4)
{
[String] $scriptPath = $MyInvocation.MyCommand.Path;
[String[]] $parameters = @(
$MyInvocation.MyCommand.Parameters.Keys `
| ForEach-Object {
[Object] $parameterValue = Get-Variable -Name $_ -ValueOnly;
if ($parameterValue -ne $null)
{
[String] $parameterValueText = GetValueText $parameterValue;
'-{0}' -f $_;
$parameterValueText;
}
}
);
[Object] $job = Start-Job -FilePath $scriptPath -RunAs32 -ArgumentList $parameters;
[Object[]] $data = $job | Wait-Job | Receive-Job;
$data;
}
else
{
# Retrieve data...
}
When it gets to the Start-Job line it generates an error with message "Cannot convert value "-Argument1" to type "System.Int32[]"". -Argument1 is the script's first parameter and is of type [Int32[]], so does this mean that -ArgumentList only works with positional and not named parameters?
I've also tried simplifying it to...
param(
[String] $stringArg,
[Int32] $int32Arg
)
$PSBoundParameters;
if ([IntPtr]::Size -gt 4)
{
[String] $scriptPath = $MyInvocation.MyCommand.Path;
[Object] $job = Start-Job -FilePath $scriptPath -RunAs32 -ArgumentList @PSBoundParameters;
$job | Wait-Job | Receive-Job;
}
else
{
Get-Date;
}
...but when I run .\Test.ps1 'string' 12345 from a 64-bit session, it displays...
Key Value
--- -----
stringArg string
int32Arg 12345
Start-Job : Missing an argument for parameter 'ArgumentList'. Specify a parameter of type 'System.Object[]' and try again.
At X:\Test.ps1:11 char:72
+ [Object] $job = Start-Job -FilePath $scriptPath -RunAs32 -ArgumentList <<<< @PSBoundParameters;
+ CategoryInfo : InvalidArgument: (:) [Start-Job], ParameterBindingException
+ FullyQualifiedErrorId : MissingArgument,Microsoft.PowerShell.Commands.StartJobCommand
...so @PSBoundParameters seems to evaluate to $null. I'm not sure why this isn't working or what else to try.