1

I am passing a multi-line string to a batch file from a vbscript. However, when I try to get the whole string from the batch file, it is only receiving the first line. How can I let the batch file know to read the whole string, and not stop at the newline character.

Input:
C:\ComponentA

C:\ComponentB

C:\ComponentC

VBScript:

multstring = "C:\Component_A" + Chr(13) + Chr(10) + "C:\ComponentB" +
       Chr(13) + Chr(10) + "C:\ComponentC" + Chr(13) + Chr(10)

script_path = "runscript.bat """ + multstring + """

Shell(script_path)

Batch:

set "scriptargs=%~1"
echo "%scriptargs%"
setlocal enableDelayedExpansion
echo !scriptargs!

Output I am Getting:

C:\ComponentA

Output Wanted:

C:\ComponentA

C:\ComponentB

C:\ComponentC

user2970916
  • 1,146
  • 3
  • 15
  • 37
  • 2
    **cmd does not work with multi line string.** Only one line at a time. You can pipe `|` your input to the script to be handled, but that will take some fancy script logic. I would recommend just concatenating your input into a single line with delimiters (like `;` ) and then just parsing it in the script with `for`. – David Ruhmann Feb 06 '15 at 15:53
  • @DavidRuhmann That's exactly what I ended up doing. Separating via a special delimiter. Thanks for the response. – user2970916 Feb 06 '15 at 16:33
  • Your posted VBS code is not valid - it cannot give the output you claim. Please be careful to post working examples when summarizing code. – dbenham Feb 07 '15 at 04:14
  • @DavidRuhmann - cmd can work with multi-line strings in environment variables. But it is true that multi-line values cannot be passed as command line arguments. – dbenham Feb 07 '15 at 04:34

2 Answers2

2

Multi-line strings cannot be passed to a batch file via command line arguments, but new lines can be included within environment variables.

VBS can define an environment variable with newlines, and then the batch script you call can read and display the value by using delayed expansion.

test.vbs

set wshShell = CreateObject("WScript.Shell")
set Env=wshShell.Environment("PROCESS")

multstring="C:\Component_A" + Chr(13) + Chr(10) + "C:\ComponentB" + _
            Chr(13) + Chr(10) + "C:\ComponentC" + Chr(13) + Chr(10)

Env("arg1") = multstring

script_path = "runscript.bat arg1"

wshShell.Run script_path

runscript.bat

@echo off
setlocal enableDelayedExpansion
echo !%1!
pause

Note that this works for a batch script that is called by VBS because the new batch script inherits a copy of the VBS environment.

If a batch script calls VBS, then the VBS cannot pass a value back to the caller via an environment variable because the VBS environment is lost once VBS ends.

dbenham
  • 127,446
  • 28
  • 251
  • 390
  • Nitpicking: You can pass multi line strings to batch files, but it's a bit tricky to access them – jeb Feb 07 '15 at 06:47
0

As dbenham mentioned, it's a good idea to pass multi line strings by reference.

But if you really need to pass them by value this is also possible.
The problem is to access them.

Here is an adapted variant of How to receive even the strangest command line parameters?.

@echo off
setlocal DisableExtensions DisableDelayedExpansion
REM Write the complete parameter to a temp file
@echo on
@(for %%A in (%%A) do (
    @goto :break
    REM # %1 #
    REM
)) > param.tmp
:break
@echo off

REM receive all lines from the temp file and store them in an array
setlocal EnableExtensions
set cnt=0
for /F "skip=3 delims=" %%a in (param.tmp) DO (
    set /a cnt+=1
    setlocal EnableDelayedExpansion
    for /F %%n in ( "!cnt!" ) do (
        setlocal DisableDelayedExpansion
        set "param%%n=%%a"
    )
)
setlocal EnableDelayedExpansion
set \n=^


REM Build the \n variable with a linefeed character, the two empty lines are required

REM Build from the array a single parameter
set /a cnt-=2
set "param1=!param1:~6!"    REM Remove the 'REM #' from the first line
set "param%cnt%=!param%cnt%:~0,-3!" REM Remove the trailing '#' from the last line
set "param="
for /L %%n in (1 1 !cnt!) do (
    if %%n GTR 1 set "param=!param!!\n!"
    set "param=!param!!param%%n:~1!"
)
echo The param is: '!param!'

Sample call from the console (the empty lines are required!):

test.bat ^"hello^

Line2^

Line3"

Carriage returns can't be accessed, as they are always removed by cmd.exe

But there are still problems, when suboptimal content is used.

Community
  • 1
  • 1
jeb
  • 78,592
  • 17
  • 171
  • 225
  • 1) You have quotes in your `SET "var=content" REM ...` remark content that are killing the code. 2) You are adding a trailing space to the result. 3) I don't see how you can distinguish \n from \r\n. 4) You have trailing space issues on some lines 5) You don't show how to call your script - I believe it requires a quoted delayed expansion of a variable `"!argVar!"`, which means you still would be passing the value by reference out of VBS, and would have to run the batch through `CMD /V:ON /C ...` – dbenham Feb 07 '15 at 13:48
  • 1) I don't know which lines you are refering to? 2) No, there are no trailing spaces, proofed by sample 3) You can't detect a `\r` with batch at all 4) Which lines? 5) I added a smaple, with passing `by value` – jeb Feb 07 '15 at 14:08
  • 1) Got it (and fixed it), I tested with other code, than the posted one :-) – jeb Feb 07 '15 at 14:18
  • When I test an argument with 4 lines, the first line has 2 trailing spaces appended, the second and third lines have 1 trailing space added, and the last line is OK. I tested by adding `echo(!param!>test.txt` at end, and looked at content with a hex editor. – dbenham Feb 07 '15 at 14:25
  • I see now that param.tmp has all `\r` stripped, and then each line is terminated with `\r\n`. So yes, detecting `\r` is impossible with this technique. – dbenham Feb 07 '15 at 16:59