Reputation: 188
I have PowerShell scripts that require to start other PowerShell scripts in a new session. The first script passes a set of arguments to the second script as an array. Everything works fine when all of the arguments have values, but when i try passing a $null
, the parameter is stripped and the list of arguments gets messed up.
To better understand the issue, you can do the following (this is just an example):
define C:\Test.ps1 as:
param($a,$b,$c)
" a $a " | Out-File C:\temp.txt
" b $b " | Out-File C:\temp.txt -append
" c $c " | Out-File C:\temp.txt -append
run in any ps console
PowerShell.exe -WindowStyle Hidden -NonInteractive -file C:\Test.ps1 @(1,2,3) #works as expected temp.txt contains
a 1
b 2
c 3
PowerShell.exe -WindowStyle Hidden -NonInteractive -file C:\Test.ps1 @(1,$null,5) #strips $null and writes the following to temp.txt
a 1
b 5
c
I need to preserve the $null
when creating the new session, the desired temp.txt would contain
a 1
b
c 5
The problem seems to be that the $null
gets stripped from the array directly and is already @(1,5)
when being interpreted by the new session.
I've tried declaring an empty array and adding elements to it one by one, also tried replacing the array with a System.Collections.Generic.List[System.Object]
and using the Add method, but still the $null
gets stripped.
My last ideas are, to test for a $null and assign a default value to the argument, in the calling script, then in the second script to test for the default value and reassign the $null, or create a hash with all the arguments, pass it as an argument and process and split them in the called script. I really don't like these ideas as it feels overkill for the task at hand.
Any help in understanding the basic problem, why $null gets stripped from the array and how to preserve it, or how to alter the creation of the new session to pickup the $null
is greatly appreciated.
Upvotes: 0
Views: 175
Reputation: 32200
When I've needed to serialize data between scripts, or preserve objects across script executions, I tend to use Export-Clixml
and Import-Clixml
, sometimes combined with splatting. The Clixml scripts will preserve objects as they existed previously in their entirety.
For example, in your sending script:
$a = 1;
$b = $null;
$c = 3;
@($a, $b, $c) | Export-Clixml 'C:\params.xml'
And then to retrieve the data:
$params = Import-Clixml 'C:\params.xml';
$x = $params[0];
$y = $params[1];
$z = $params[2];
Write-Output "$x,$y,$z";
You should get 1,,3
.
Often you can even use hash tables to help organize:
@{'a'=$a, 'b'=$b, 'c'=$c} | Export-Clixml 'C:\params.xml'
And then:
$x = $params.a;
$y = $params.b;
$z = $params.c;
But hashtables are a bit funky sometimes. Be sure to test.
As for what's going on, it looks like PowerShell skips null values when assigning parameters from an array like you're doing. The null value is in the array (@(1, $null, 3)[1] -eq $null
is True), it's just PowerShell skipping it.
Upvotes: 1
Reputation: 665
If you specify the param names, then PowerShell knows which parameters you're giving it.
PowerShell.exe -WindowStyle Hidden -NonInteractive -file C:\Test.ps1 -a 1 -c 5
gives you
a 1
b
c 5
More on PowerShell parameters here.
Upvotes: 0