I'm trying to pass a string array to powershell through vbscript. I got the params in the file.ps1 script:
param (
[string[]]$target
)
I'm trying to call file.ps1 through vbscript.
I want $target = @('c:\dev','d:\lib')
to be passed in.
I currently have in my vbscript :-
target1 = """c:\dev"", ""d:\lib"""
Set objShell = CreateObject("Wscript.Shell")
objShell.run("powershell.exe -noexit -ExecutionPolicy Unrestricted -file .\file.ps1 -target1 """ & target & """")
which returns:
c:\dev, d:\lib
and which isn't the powershell string array format "c:\dev", "d:\lib"
Update - Thanks mklement0 and alex-dl for your answers!
alex-dl's helpful answer contains an effective solution, as long as the array's elements don't need quoting, but let me try to break it down conceptually in more detail:
The -File
parameter of PowerShell's CLI, powershell.exe
(pwsh
in PowerShell (Core) 7+) fundamentally does not support passing arrays to PowerShell code, because all arguments are interpreted strictly as whitespace-separated, with verbatim content.
"c:\dev", "d:\lib"
on the command line is parsed as two arguments:
c:\dev,
(note the trailing ,
, syntactic "
quotes stripped)d:\lib
You must use the -Command
(-c
) option in order to pass arrays.
-Command
fundamentally changes how the arguments are parsed:
\"
-escaped) "
quotes.,
, '...'
(single-quoting), ..., and notably also means that references to PowerShell variables (e.g. $HOME
) are recognized (unlike with -File
).See this answer for more guidance on when to use -File
vs. -Command
(-c
).
Therefore, the best approach in your case is:
target = "'c:\dev', 'd:\lib'" ' Note the embedded '...'-quoting
Set objShell = CreateObject("Wscript.Shell")
' Note the use of -c (-command) instead of -file
objShell.Run("powershell.exe -noexit -ExecutionPolicy Unrestricted -c .\file.ps1 -target " & target)
Using embedded '...'
-quoting simplifies passing the array elements in a way that PowerShell sees them as individually quoted (with the values at hand, this isn't strictly necessary, but it may be in other cases).
Doing this with embedded "..."
-quoting gets unwieldy, because each embedded "
must then be escaped as \""
(sic):
""
to escape the "
inside the VBScript string,\
to ensure that \"
is ultimately passed on the command line, which PowerShell requires for escaping "
on the command line[1] (whereas PowerShell-internally, it is `"
or (alternatively, inside a double-quoted string) ""
).target = "\""c:\dev\"", \""d:\lib\"""
Set objShell = CreateObject("Wscript.Shell")
objShell.Run("powershell.exe -noexit -ExecutionPolicy Unrestricted -c .\file.ps1 -target " & target)
[1] While in Windows PowerShell you can situationally get away with ""
instead of \"
, it can break, especially if the overall -c
argument is enclosed in "..."
.
This problem has been fixed in PowerShell (Core) 7+, where you can now use ""
and \"
interchangeably.
E.g., when invoked from cmd.exe
,
powershell -c " ""ab c"".length "
breaks, whereas
pwsh -c " ""ab c"".length "
works.