1

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!

4
  • 1
    Remove the "" on each side - otherwise you're passing the literal string value "c:\dev, d:\lib" Commented Feb 5, 2021 at 12:37
  • removing "" would cause a syntax error. In vbscript " is used as the escape character. so if i was to print """c:\dev"", ""d:\lib""" into vb console it would return "c:\dev", "d:\lib" Commented Feb 5, 2021 at 12:43
  • No it would not, "... -target " & target & "" is a perfectly valid expression Commented Feb 5, 2021 at 15:03
  • @Mathias, true, though the & "" is then unnecessary. The fundamental problem here, however, is the use of the -File CLI parameter, which fundamentally doesn't support passing arrays; -Command (-c) must be used. Commented Feb 5, 2021 at 17:05

2 Answers 2

2

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.

    • E.g., "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:
      • All arguments are stripped of syntactic (non \"-escaped) " quotes.
      • The resulting tokens are space-concatenated to form a single string.
      • The resulting string is then interpreted as PowerShell code, i.e. as if you had submitted it from inside a PowerShell session.
    • This therefore enables all of PowerShell's features, such as passing arrays with ,, '...' (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,
  • and \ 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.

Sign up to request clarification or add additional context in comments.

Comments

1

You could use the following vbscript:

target1 = """c:\dev, d:\lib"""
Set objShell = CreateObject("Wscript.Shell") 
objShell.run("powershell.exe -Command .\file.ps1 -target " & target1)

And this powershell script:

param (
    [string[]]$target
)
foreach ($t in $target) {
    write-output $t
}
Read-Host -Prompt "Press Enter to exit"

Without -Command the argument is always interpreted as a single string.

1 Comment

Good point about the need for -Command if arrays are to be passed. Note that the escaped embedded double quotes ("" inside """c:\dev, d:\lib""") ultimately have no effect here and PowerShell ultimately sees the array elements as unquoted (which works fine in this case); additional work is needed if the array elements need quoting individually (which Mango99 (ineffectively) attempted), such as for elements containing spaces.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.