Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running Batch file from JScript in HTA

I'm creating this HTA app with JScript that writes a BAT file and opens it in cmd afterwards.

If I manually open the created BAT file from windows it works like it should.
When I open it through my HTA, the file opens but only outputs Echo and pause.

Please keep in mind, I'm very very new at programming.

Here is the JScript.

// Write the Bat file
// When run from HTA all I get is the "Echo Done" and "Pause"
// When I run from Windows without HTA, all of it works.
function writeBat() {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var s = fso.CreateTextFile("C:/test/test.bat");
    s.WriteLine('@echo off');
    s.WriteLine('set output=C:/test/new/');
    s.WriteLine('FOR %%a in (*.mkv) DO ("C:/Program Files/MKVToolNix/mkvmerge.exe" -o "%output%%%~na.mkv" "%%a")');
    s.WriteLine('echo Done.');
    s.WriteLine('pause');
    s.Close(); }

// Run the Bat file.
function runBat() {
var MyObject = new ActiveXObject("wscript.shell");
MyObject.Run("C:/test/test.bat"); }

Here is the Batch file.

@echo off
set output=C:/test/new/
FOR %%a in (*.mkv) DO ( "C:/Program Files/MKVToolNix/mkvmerge.exe" -o "%output%%%~na.mkv" "%%a")
echo Done.
pause

And the HTML

<form>
<input type="button" value="Write Bat" onClick="writeBat()">
<input type="button" value="Run Bat" onClick="runBat()">
</form>
like image 925
Jon Avatar asked Sep 25 '22 06:09

Jon


1 Answers

Well, you found your answer. The context of the HTA is in a different working directory from the context of the batch script. You have to have the batch script cd or pushd to "%~dp0". This is pretty standard for batch scripts added to context menus and so forth.

s.WriteLine('pushd "%~dp0"');

... as you have already done is the correct solution. You should also

s.WriteLine('@echo off & setlocal');

... to limit the scope of the variables in this batch script to the runtime of the batch script itself.


But the main reason I'm posting an answer is for the purpose of providing more information on the Chakra engine. Even with IE9, 10, 11, Edge, whatever installed, the Windows Script Host maintains the feature set as it existed in JScript 5.7. According to MSDN documentation:

Starting with JScript 5.8, by default, the JScript scripting engine supports the language feature set as it existed in version 5.7. This is to maintain compatibility with the earlier versions of the engine. To use the complete language feature set of version 5.8, the Windows Script interface host has to invoke IActiveScriptProperty::SetProperty.

What that is saying is, if you want to use methods in JScript 5.8 or newer (such as JSON methods, Object.keys, Array.prototype.forEach(), and so on), you basically have to write your own Windows Script Host interpreter. But, with HTA, there's an easy hack that will enable IE9 features. Simply add the following line to the top of your HTA file:

<meta http-equiv="x-ua-compatible" content="IE=9" />

Before:

<script>
function get() {
    try {
        var json = JSON.parse(document.getElementById('json').value);
        alert(json.var1);
    }
    catch(e) {
        alert(e.message);
    }
}
</script>
<textarea id="json">{"var1": "It works!"}</textarea>
<button onclick="get()">Go!</button>

Output:

'JSON' is undefined

After:

<meta http-equiv="x-ua-compatible" content="IE=9" />
<script>
function get() {
    try {
        var json = JSON.parse(document.getElementById('json').value);
        alert(json.var1);
    }
    catch(e) {
        alert(e.message);
    }
}
</script>
<textarea id="json">{"var1": "It works!"}</textarea>
<button onclick="get()">Go!</button>

Output:

It works!


This hack isn't limited to HTA, though. It can also be made to work for console JScript and JScript.NET by creating an htmlfile COM object, writing the <meta> tag to it, then copying the newly exposed methods and objects into the current script host.

like image 70
rojo Avatar answered Oct 03 '22 06:10

rojo