How to pass a variable in batch/javascript hybrid

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Izya Kurvitch
Posts: 21
Joined: 15 Jul 2019 15:14

How to pass a variable in batch/javascript hybrid

#1 Post by Izya Kurvitch » 22 Jan 2025 11:53

Here's simple code:

Code: Select all

0</*! ::
@echo off
set "c=0.618"
cscript //nologo //e:javascript "%~f0" %* add("%c%")
pause
goto :EOF
*/0;

function add(c){
return c;
}
WScript.Echo(eval(WScript.Arguments(0)));
Expecting return is 0,618 as it gives when "c" is a number.
But when "c" is something like this: "c="jhfd":{"mhhdu":[{"trhjs:"vfdf://rfhg.hdfrgg.yuyyt/d/t/klhjkjk/78.1/8ree/86.vfd"}]," it returns an error...

Question: how could i pass correctly such a variable from batch section to javascript one, or how can i open a local file in javascript section and store it to variable? Or maybe there're another ways, without using a function, for example, to get similar result? Thanks to all.

aGerman
Expert
Posts: 4684
Joined: 22 Jan 2010 18:01
Location: Germany

Re: How to pass a variable in batch/javascript hybrid

#2 Post by aGerman » 23 Jan 2025 10:59

Escaping all the characters that have a special meaning in batch can be an annoying task. Furthermore it's a well known issue that the scripting engines of VBScript and JScript remove all quotes from the arguments you pass to a script and there's nothing that you could do to prevent this. So, don't go down this road.

Variables defined in a CMD process are environment variables. Child processes inherit a copy of the environment from the parent. In other words, as long as you define your "c" variable before you call cscript.exe, a copy of this variable is available in the environment block of the cscript process.

Code: Select all

0</*! ::
@echo off
set "c="jhfd":{"mhhdu":[{"trhjs:"vfdf://rfhg.hdfrgg.yuyyt/d/t/klhjkjk/78.1/8ree/86.vfd"}],"
cscript //nologo //e:jscript "%~f0"
pause
goto :EOF
*/0;

var objWSh = new ActiveXObject('WScript.Shell');
var env_c = objWSh.Environment('PROCESS')('c');
WScript.Echo(env_c);
Steffen

Izya Kurvitch
Posts: 21
Joined: 15 Jul 2019 15:14

Re: How to pass a variable in batch/javascript hybrid

#3 Post by Izya Kurvitch » 23 Jan 2025 15:44

aGerman wrote:
23 Jan 2025 10:59
Escaping all the characters that have a special meaning in batch can be an annoying task. Furthermore it's a well known issue that the scripting engines of VBScript and JScript remove all quotes from the arguments you pass to a script and there's nothing that you could do to prevent this. So, don't go down this road.

Variables defined in a CMD process are environment variables. Child processes inherit a copy of the environment from the parent. In other words, as long as you define your "c" variable before you call cscript.exe, a copy of this variable is available in the environment block of the cscript process.

Code: Select all

0</*! ::
@echo off
set "c="jhfd":{"mhhdu":[{"trhjs:"vfdf://rfhg.hdfrgg.yuyyt/d/t/klhjkjk/78.1/8ree/86.vfd"}],"
cscript //nologo //e:jscript "%~f0"
pause
goto :EOF
*/0;

var objWSh = new ActiveXObject('WScript.Shell');
var env_c = objWSh.Environment('PROCESS')('c');
WScript.Echo(env_c);
Steffen
Thank you so much :D ! Really saving of my time, was seeking for answer 2 days :( :?: . Devil's coverd in details :twisted: ... And another question I've got: how can I return without any losses a charset that is not ASCII, indonesian I pose... Here's a little add:

Code: Select all

0</*! ::
@echo off
set "c="jhfd":{"mhhdu":[{"trhjs:"vfdf://rfhg.hdfrgg.yuyyt/d/t/klhjkjk/78.1/8ree/86.vfd:การดำเนินการในแชท"}],"
for /f "tokens=2,6 delims={:," %%a in ('cscript //nologo //e:jscript "%~f0"') do @echo %%a*%%b
pause
goto :EOF
*/0;

var objWSh = new ActiveXObject('WScript.Shell');
var env_c = objWSh.Environment('PROCESS')('c');
var r  =  env_c.replace(/[][{}]/g, '').replace(/"/g, '');
WScript.Echo(r);
Needed to recieve: mhhdu*การดำเนินการในแชท.
Now I've got mhhdu*р╕Бр╕▓р╕гр╕Фр╕│р╣Ар╕Щр╕┤р╕Щр╕Бр╕▓р╕гр╣Гр╕Щр╣Бр╕Кр╕Ч
or mhhdu*????????????????? if I have "chcp 65001" before definig "c" .

aGerman
Expert
Posts: 4684
Joined: 22 Jan 2010 18:01
Location: Germany

Re: How to pass a variable in batch/javascript hybrid

#4 Post by aGerman » 23 Jan 2025 17:00

This requires quite some trickery where you should execute the the JScript in a WSF job that respects the "encoding" attribute. However, this is still not good enough to make it work for the underlying pipe in a FOR /F loop. So, you need a UTF-16 encoded temporary file...

proof of concept

Code: Select all

<?xml :
: version="1.0" encoding="utf-8" ?>
<!-- :
@echo off
>nul chcp 65001
set "c="jhfd":{"mhhdu":[{"trhjs:"vfdf://rfhg.hdfrgg.yuyyt/d/t/klhjkjk/78.1/8ree/86.vfd:การดำเนินการในแชท"}],"
cscript //nologo "%~f0?.wsf"
for /f "tokens=2,6 delims={:," %%a in ('type "foo.tmp~"') do echo %%a*%%b
del "foo.tmp~"
pause
goto :EOF
: -->
<job>
<script language="JScript"><![CDATA[
var objWSh = new ActiveXObject('WScript.Shell');
var objFSO = new ActiveXObject('Scripting.FileSystemObject');
var env_c = objWSh.Environment('PROCESS')('c');
var r = env_c.replace(/[][{}]/g, '').replace(/"/g, '');
var f = objFSO.CreateTextFile('foo.tmp~', true, true); // created for UTF-16 I/O
f.Write(r);
f.Close()
]]></script>
</job>
Consider to use a language with better UTF-8 support.

Steffen

Izya Kurvitch
Posts: 21
Joined: 15 Jul 2019 15:14

Re: How to pass a variable in batch/javascript hybrid

#5 Post by Izya Kurvitch » 23 Jan 2025 18:42

aGerman wrote:
23 Jan 2025 17:00
This requires quite some trickery where you should execute the the JScript in a WSF job that respects the "encoding" attribute. However, this is still not good enough to make it work for the underlying pipe in a FOR /F loop. So, you need a UTF-16 encoded temporary file...

proof of concept

Code: Select all

<?xml :
: version="1.0" encoding="utf-8" ?>
<!-- :
@echo off
>nul chcp 65001
set "c="jhfd":{"mhhdu":[{"trhjs:"vfdf://rfhg.hdfrgg.yuyyt/d/t/klhjkjk/78.1/8ree/86.vfd:การดำเนินการในแชท"}],"
cscript //nologo "%~f0?.wsf"
for /f "tokens=2,6 delims={:," %%a in ('type "foo.tmp~"') do echo %%a*%%b
del "foo.tmp~"
pause
goto :EOF
: -->
<job>
<script language="JScript"><![CDATA[
var objWSh = new ActiveXObject('WScript.Shell');
var objFSO = new ActiveXObject('Scripting.FileSystemObject');
var env_c = objWSh.Environment('PROCESS')('c');
var r = env_c.replace(/[][{}]/g, '').replace(/"/g, '');
var f = objFSO.CreateTextFile('foo.tmp~', true, true); // created for UTF-16 I/O
f.Write(r);
f.Close()
]]></script>
</job>
Consider to use a language with better UTF-8 support.

Steffen
Thanks a lot! So much to lern... :)

Sponge Belly
Posts: 233
Joined: 01 Oct 2012 13:32
Location: Ireland
Contact:

Re: How to pass a variable in batch/javascript hybrid

#6 Post by Sponge Belly » 26 Jan 2025 11:08

Hi Steffen,

Brilliant workaround for ensuring Unicode I/O. 8)

But please explain this line:

Code: Select all

for /f "tokens=2,6 delims={:," %%a in ('type "foo.tmp~"') do echo %%a*%%b
Why all the tokens and delims, and why the asterisk between %%a and %%b? And why use TYPE inside the in (...) clause of the for /f loop. Why not just write:

Code: Select all

for /f "tokens=2,6 delims={:," %%a in ("foo.tmp~") do echo %%a*%%b
Lastly, what is the reason for this line?

Code: Select all

var r = env_c.replace(/[][{}]/g, '').replace(/"/g, '');
It’s some Unicode thing, isn’t it? Like Izya said, so much to learn…

Thanks!

- SB

aGerman
Expert
Posts: 4684
Joined: 22 Jan 2010 18:01
Location: Germany

Re: How to pass a variable in batch/javascript hybrid

#7 Post by aGerman » 26 Jan 2025 17:40

Hi Sponge Belly

I can't actually answer some of your qestions.
Why all the tokens and delims, and why the asterisk between %%a and %%b?
That's copy/paste from Izya's code. It extracts certain substrings and the asterisk is added to the output for a reason that I can't tell.
Lastly, what is the reason for this line?
Similarly here. It's a regex pattern match to remove some characters. It seems to be the main reason why Izya calls the JScript portion. However, this seems to be just a simplified example and I don't know the real use case ...

And why use TYPE inside the in (...) clause of the for /f loop. Why not just write:
That's the only question I'm able to answer.
Because the file is UTF-16 encoded (due to argument 'true' for the 3rd parameter of the CreateTextFile() method). And this is because writing out UTF-8 from within JScript fails terribly. So, I had to use UTF-16 to work around this issue.
The TYPE command performs the conversion from UTF-16 to the current console codepage (previously set to UTF-8 using CHCP).

Steffen

Post Reply