Page 1 of 5

js/vbs/html/hta and more hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 03:43
by siberia-man
* * * * * *
Everything here below is correct. However during discussions some parts of this message became obsolete.
The resulting message accumulating all good points of this thread is located by the following link:
viewtopic.php?p=65390#p65390

Briefly. In this thread is discussed the script generating scripts "two-in-one".

Such kind of scripts is called "hybrids", because they unite both batch and another language, so these scripts are executed by CMD and other interpreters.

Also I'd like to introduce the term "chimera". Chimera differs from hybrid in that it requires additional settings to run chimera (for instance, temp files, some environment variables, some undocumented features and/or tricks).
* * * * * *


js in cmd/bat

these solutions are world-wide and well-known.

Code: Select all

@set @x=0 /*
@echo off
cscript /nologo /e:javascript %0
goto:EOF */

WScript.Echo('Hello from JScript');

Code: Select all

@if (true == false) @end /*
@echo off
cscript //nologo //e:javascript "%~dpnx0" %*
goto :EOF */

WScript.Echo('Hello from JScript');
html in cmd/bat

this is the first version. It uses the trick to clean the resulting page on from the wrong markups.

Code: Select all

:<nul>nul

@echo off
start mshta "%~f0"
goto :EOF

<script type="text/javascript">
document.body.innerHTML = '';
</script>

<html>
<head>
<title>HTML-in-BATCH</title>
</head>
<body>
<h1>Hello, world!</h1>
</body>
</html>
the second version found by the programmer from Russia is the best. http://forum.script-coding.com/viewtopi ... 317#p79317

Code: Select all

<!-- :
@echo off
start "" mshta.exe "%~f0"
exit /b
-->

<html>
<head><title>HTA window</title></head>
<body><h1>Hello, world!</h1></body>
</html>
The better way to use mshta instead of cscript. The better is in the terms of friendliness, development and support (compare with ugly mshta "javascript:..."). This can be used for both js-in-cmd or html-in-cmd. (found by npocmaka_ in http://www.dostips.com/forum/viewtopic. ... 783#p33783).

Code: Select all

@if (true == false) @end /*!
@echo off
mshta "about:<script src='file://%~f0'></script><script>close()</script>" %*
goto :EOF */

alert("Hello, world!");
vbs in cmd/bat

This is not true hybrid because it uses a js-layer between cmd and vbs. In fact this is js-in-cmd solution running vbs within js. Take a look: two ways similar each other (taken from http://forum.script-coding.com/viewtopi ... 691#p79691)

Code: Select all

@if (true == false) @end /*
@echo off
set "SYSDIR=SysWOW64"
if "%PROCESSOR_ARCHITECTURE%" == "x86" if not defined PROCESSOR_ARCHITEW6432 set "SYSDIR=System32"
"%WINDIR%\%SYSDIR%\cscript.exe" //nologo //e:javascript "%~f0" %*
goto :EOF */

(function(readFile, code)
{
    var e;
    try {
        var vb = new ActiveXObject('MSScriptControl.ScriptControl');
        vb.Language = 'VBScript';
        vb.AddObject('WScript', WScript, true);
        vb.AddCode(code);
    } catch(e) {
        var file = readFile();
        var prologLen = file.slice(0, file.indexOf(code)).split('\n').length;
        var vbe = vb.Error;
        WScript.Echo(
            WScript.ScriptFullName + 
            '(' + ( prologLen + vbe.Line - 1 ) + ', ' + vbe.Column + ') ' + 
            vbe.Source + ': ' + vbe.Description);
    }
})(
function()
{
    var fso = new ActiveXObject('Scripting.FileSystemObject');
    var f = fso.OpenTextFile(WScript.ScriptFullName, 1, true);
    var file = f.ReadAll();
    f.Close();
    return file;
}, 
(function()
{
    return arguments.callee.toString().replace(/^[\s\S]+\/\*|\*\/[\s\S]+$/g, '');
/* ' VBScript

WScript.Echo "Hello, world!"

*/
})());

Code: Select all

@if (true == false) @end /*
@echo off
set "SYSDIR=SysWOW64"
if "%PROCESSOR_ARCHITECTURE%" == "x86" if not defined PROCESSOR_ARCHITEW6432 set "SYSDIR=System32"
"%WINDIR%\%SYSDIR%\cscript.exe" //nologo //e:javascript "%~f0" %*
goto :EOF */

var prologLen = 0;
var vb = new ActiveXObject('MSScriptControl.ScriptControl');
vb.Language = 'VBScript';
vb.AddObject('WScript', WScript, true);
try {
    vb.AddCode((function () {
        var fso = new ActiveXObject("Scripting.FileSystemObject");
        var f = fso.OpenTextFile(WScript.ScriptFullName, 1, false);
        do prologLen++; while (f.ReadLine() != "/* ' VBScript");
        var code = f.ReadAll();
        f.Close();
        return code;
    })());
} catch (e) {
    var vbe = vb.Error;
    WScript.StdErr.WriteLine(
        WScript.ScriptFullName + 
        '(' + ( prologLen + vbe.Line ) + ', ' + vbe.Column + ') ' + 
        vbe.Source + ': ' + vbe.Description);
}
/* ' VBScript

WScript.Echo "Hello, world!"

'*/

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 03:55
by aGerman
Another VBScript example

Code: Select all

::'@echo off &cscript //nologo //e:vbscript "%~f0"
::'>nul pause
::'exit /b
WScript.Echo "test"


There is a SUB character (0x1a) next to each apostrophe. Just in case it doesn't appear if you copy the code.

Regards
aGerman

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 04:00
by foxidrive
aGerman wrote:Another VBScript example
There is a SUB character (0x1a) next to each apostrophe. Just in case it doesn't appear if you copy the code.


I can't see how that will execute the batch code. Is the SUB character before the apostrophe?

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 04:19
by aGerman
No it isn't.

For Batch interpretation:
:: initiates a Batch comment. The SUB is interpreted as line break in this case. That means the expression next to the SUB will be executed.

For VBScript interpretation:
Colons are interpreted as separators. (E.g. Dim var : Set var = New RegExp). They don't have any effect if they are written at the beginning of a line. The apostroph initiates a comment though. The following SUB doesn't influence it.

Regards
aGerman

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 04:21
by siberia-man
I copied and pasted the code from the post by aGerman. I can see those ascii26 AFTER each apostrophs.

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 04:24
by aGerman
I can see those ascii26 AFTER each apostrophs.

Yes, that's the SUB character. It should work then.

Regards
aGerman

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 04:33
by foxidrive
Thanks to you both. I can see the SUB characters too in a copy and paste.

I'm amazed at the ingenuity of people to figure out such workarounds.

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 04:38
by aGerman
I'm amazed at the ingenuity of people to figure out such workarounds.

I should have mentioned that it was dbenham for my example. I can't find the thread where he originally posted it. But I remember it was here at DosTips ...

Regards
aGerman

EDIT Found it.
http://www.dostips.com/forum/viewtopic.php?f=3&t=2863&p=13170#p13170

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 13:30
by npocmaka_
siberia-man wrote:
the second version found by the programmer from Russia is the best. http://forum.script-coding.com/viewtopic.php?pid=79317#p79317

Code: Select all

<!-- :
@echo off
start "" mshta.exe "%~f0"
exit /b
-->

<html>
<head><title>HTA window</title></head>
<body><h1>Hello, world!</h1></body>
</html>




This is amazing . In this way you can have both (browser versions ) of javascript and vbscript in one file and have no poisonous echo :


Code: Select all

<!-- :
@echo off
 mshta.exe "%~f0" %*
exit /b
 rem
-->
<html>
<head>
<title>Command Line Agruments</title>

<HTA:APPLICATION
     ID="objTestHTA"
     APPLICATIONNAME="Command Line Agruments"
     SINGLEINSTANCE="yes"
>
</head>

<SCRIPT Language="VBScript">

alert(objTestHTA.commandLine)
Sub Window_onLoad
    arrCommands = Split(objTestHTA.commandLine, chr(34))
    For i = 3 to (Ubound(arrCommands) - 1) Step 2
        Msgbox arrCommands(i)
    Next
End Sub

</SCRIPT>

<body>
</body>
</html>



(thought for something similar with frames) . But will this work on fat32 ? Is this redirecting to / from ADS ?

EDIT -its the same as ":<!-- " no ADS

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 13:35
by npocmaka_
and this..
http://stackoverflow.com/questions/9074 ... ut-using-a

Code: Select all

:sub echo(str) :end sub
echo off
'>nul 2>&1|| copy /Y %windir%\System32\doskey.exe %windir%\System32\'.exe >nul

'& echo/
'& cscript /nologo /E:vbscript %~f0
'& echo/
'& echo BATCH: Translation is at best an ECHO.
'& echo/
'& pause
'& rem del /q "%windir%\System32\'.exe"
'& exit /b

WScript.Echo "VBScript: Remorse is the ECHO of a lost virtue."
WScript.Quit

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 21 Apr 2014 19:34
by Liviu
siberia-man wrote:js in cmd/bat
these solutions are world-wide and well-known.

Code: Select all

@if (true == false) @end /*
@echo off
cscript //nologo //e:javascript "%~dpnx0" %*
goto :EOF */

WScript.Echo('Hello from JScript');

Just as a side note, but since this example in particular attempts to pass the '%*' command line to JScript, it may be worth mentioning that cmd and WSH (the Windows Script Host) parse arguments differently - which matters in some cases where quotes or special characters are involved.

For example, the test run of the following hybrid cmd/js sees 3 arguments in batch code, but only 1 in JScript.

Code: Select all

@if (true == false) @end /* ----------------------------------------- .cmd ----
@echo off
echo(
echo cmd.args = [%*]
echo(
if not '%1'=='' echo cmd.arg1 = [%1]
if not '%2'=='' echo cmd.arg2 = [%2]
if not '%3'=='' echo cmd.arg3 = [%3]
echo(
cscript //nologo //e:javascript "%~f0" %*
goto :eof */

var wshShell = WScript.CreateObject("WScript.Shell"); //-------------- .js ----

for(var n = 1; n <= WScript.Arguments.length; n++)
  WScript.Echo("js.arg" + n + "  = [" + WScript.Arguments(n - 1) + "]");

Code: Select all

C:\tmp>cmd-js 1="2",3

cmd.args = [1="2",3]

cmd.arg1 = [1]
cmd.arg2 = ["2"]
cmd.arg3 = [3]

js.arg1  = [1=2,3]


Liviu

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 22 Apr 2014 10:10
by penpen
Hmm :( , the best hybrid js/vbs/batch script i am able to create is this:

Code: Select all

Rem = ''; /*
::'' Batch part
Rem^ & @echo off
Rem^ &echo Hello bat world!
Rem^ &cscript //NoLogo //E:JScript test.bat
Rem^ &cscript //NoLogo //E:VBScript test.bat
Rem^ &goto :eof

' VBScript part
WScript.Echo "Hello vbs world!"

' */ '\
'; /* JSript part */ '\
'; WScript.Echo ("Hello js  world!"); '\
';
The batch part echoes nearly the complete first two (batch code) lines ... .

penpen

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 22 Apr 2014 23:04
by Liviu
siberia-man wrote:html in cmd/bat
the second version found by the programmer from Russia is the best. http://forum.script-coding.com/viewtopic.php?pid=79317#p79317

Code: Select all

<!-- :
@echo off
start "" mshta.exe "%~f0"
exit /b
-->
[... html code here ...]

Cool trick, that XML '<!-- -->' comment crossed with a CMD '<etc :' redirected label.

A variation on the same idea seems to work for the cmd/wsf hybrid below - CMD can call embedded JS and VBS, and those two can call each other within a given <job>. Checked ok under xp.sp3 and win7x64.sp1.

Code: Select all

<?xml : version="1.0" encoding="UTF-8" ?> ^<!------------------------- cmd ----
@echo off
echo cmd
cscript //nologo "%~f0?.wsf" //job:JS //job:VBS
exit /b
---------------------------------------------------------------------- wsf --->
<package>
  <job id="JS"> <!----------------------------------------------------- js --->
    <script language="VBScript"><![CDATA[
      sub vbsEcho() : WScript.Echo "cmd.js.vbs" : end sub
    ]]></script>
    <script language="JScript"><![CDATA[
      WScript.Echo("cmd.js");
      vbsEcho();
    ]]></script>
  </job>
  <job id="VBS"> <!--------------------------------------------------- vbs --->
    <script language="JScript"><![CDATA[
      function jsEcho() { WScript.Echo("cmd.vbs.js"); }
    ]]></script>
    <script language="VBScript"><![CDATA[
      WScript.Echo "cmd.vbs"
      call jsEcho
    ]]></script>
  </job>
</package>

Code: Select all

C:\tmp>cmd-wsf.cmd
cmd
cmd.js
cmd.js.vbs
cmd.vbs
cmd.vbs.js

Leaving aside the multi-language and CDATA complications, this also works to embed straight VBScript code into a batch file.

Code: Select all

<!-- : --------------------------------------------------------------- cmd ----
@cscript //nologo "%~f0?.wsf" & exit /b & rem ------------------------ vbs --->
<job><script language="VBScript">
WScript.Echo "cmd.vbs - no CDATA so <" & "/script> would cause XML error here"
</script></job>

Code: Select all

C:\tmp>cmd-vbs.cmd
cmd.vbs - no CDATA so </script> would cause XML error here

FWIW the oddities that make the above work are:
- cscript identifies ".wsf" files by extension alone, it has no documented switch or override like it has for individual //E scripting engines - however, appending "?.wsf" to the full filename appears to work i.e. the filename before "?" is loaded but still treated as an ".wsf" type (and even more odd '?' works but '*:\;etc' don't);
- .wsf appears to require an explicit <?xml version="1.0" ?> in order to recognize <![CDATA[ ]]> syntax, and per XML standards that has to be the first line of the file - however, the MS parser allows an ":" to be inserted in <?xml : version="1.0" ?> without complaining, and the batch interpreter doesn't complain either about an '?' in the presumed "<" filename.

Liviu

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 23 Apr 2014 00:47
by siberia-man

Code: Select all

"%~f0?.wsf"

Very interesting trick allowing to run a batch file as wsf scenario. I tried to embed wsf into bat/cmd but all my attempts bumped to impossibility to run bat file as wsf (as it is possible for vbs or js scenarios). Is there source where I could learn more about it? Seems it uses some bug in cmd.exe (or wsh, or hidden feature of one of them).

Re: js/vbs/html/hta hybrids and chimeras in cmd/bat

Posted: 23 Apr 2014 02:02
by npocmaka_
Here's my attempt to combine batch with wsf:

Code: Select all

@echo off
goto :skip_xml_comment
<!--
:skip_xml_comment

echo(
echo Echo from the batch
echo(

( ren %0 %0.wsf
 cscript %0.wsf
 ren %0.wsf %0 )


exit /b 0
-->

<package>
   <job id="vbs">
      <script language="VBScript">

         WScript.Echo "Echo from the VBS"

      </script>
   </job>
</package>


But is risky as it includes self renaming.

Cool trick with the "%~f0?.wsf" . Shall be tested with powershell :-D

I was wondered if it's possible to register the ".bat" extension to WSH as a dummy extension language and how eventually that could be used but didn't reach so far yet (it's still in my list with crazy ideas).