1 (изменено: Rumata, 2013-10-07 17:24:13)

Тема: CMD/BAT + HTML: два в одном

По мотивам тем
CMD/BAT + JavaScript: два в одном
JScript:CMD - вариант с условной компиляцией
CMD/BAT + VBScript: два в одном

Очередное мое извращение на тему два-в одном. В этот раз (как видно из заголовка) попытка внедрить html разметку в пакетный файл. Над целесообразностью пока не задумывался. Может быть скрипт должен выполнить некие предварительные действия перед запуском mshta. Может быть как комплексный вариант приложения, обладающего двумя интерфейсами: консольным и графическим (HTA). В таком случае стоит уже говорить уже о CMD/BAT+JavaScript+HTML: три в одном.

Следующий пример - скелет для комбинирования html-разметки в пакетных файлах, состоящий из нескольких частей:
1. своеобразного пролога - определенной конструкции, которая позволяет объединить два разных мира
2. вступления - запускателя mshta
3. интермеццо - js-скрипта, который подчищает мусор, оставшийся после пакетного скрипта
4. основной части - суть html-разметки


:<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>
( 2 * b ) || ! ( 2 * b )

2 (изменено: wisgest, 2013-10-09 22:24:33)

Re: CMD/BAT + HTML: два в одном

Поизвращённее — с двойной загрузкой (не знаю, сочтёт ли кто-либо это полезным или поучительным):

@echo off & goto :BAT
<script type="text/javascript">
alert("\
При обновлении (F5) этого сообщения больше не будет.\n\n\
Более того: обновление будет работать даже если удалить исходный файл.\
");
var x=1;
window.onload = function () {
  document.write("\<\!-\-");
  document.write(
    (new ActiveXObject("Scripting.FileSystemObject")).
      OpenTextFile(location.pathname, 1).ReadAll()
  );
  document.close();
};
</script>
<comment>

:BAT
start mshta "%~f0"
goto :EOF

-->

<html>
<head>
<title>HTML-in-BATCH</title>
</head>
<body>
<h1>Hello, world!</h1>
<script type="text/javascript">
alert("x" in this);
window.onload = function () {
  var html = "";
  for (var i = 0; i < document.childNodes.length; i++)
    html += document.childNodes.item(i).outerHTML;
  alert(html);
};
</script>
</body>
</html>

3

Re: CMD/BAT + HTML: два в одном

На самом деле, в #2 повторно считывать файл было вовсе не обязательно (но подобный подход может пригодится в других случаях)!
Вместо

  document.write("\<\!-\-");
  document.write(
    (new ActiveXObject("Scripting.FileSystemObject")).
      OpenTextFile(location.pathname, 1).ReadAll()
  );

можно написать

  document.write("\<\!-\-" + document.documentElement.outerHTML);

(в этом случае в окончательный код попадает закрывающий тег </COMMENT>, но это не страшно, да и для исправления можно в конец исходного кода поместить ещё один открывающий <COMMENT>)

или

  document.write(
    "\<\!-\-" + document.getElementsByTagName("comment").item(0).innerHTML);

4

Re: CMD/BAT + HTML: два в одном

Поизвращённее
А смысл? Какую пользу дает код?

( 2 * b ) || ! ( 2 * b )

5 (изменено: wisgest, 2014-01-03 23:19:17)

Re: CMD/BAT + HTML: два в одном

Rumata пишет:

Очередное мое извращение на тему два-в одном.

Rumata пишет:

Поизвращённее
А смысл? Какую пользу дает код?

Код предназначен для того же, что и ваш (+ несколько отладочных alert-ов), соответственно, даёт такую же пользу.
Дополнительная побочная польза:

Более того: обновление будет работать даже если удалить исходный файл.

На самом деле, «поизвращённее» — всего лишь предупредительно-виноватая защита от того, что этот пример именно так будет воспринят читателем; хотя он, в данный момент, кожется мне наоборот более прямолинейно-лобовым чем ваш, по крайней мере более общим (в том смысле, что может применяться и при наложении других технологий и при переналожении одной и той же же технологии на саму себя). Лучше или хуже, этого я до сих пор не решил.

Раньше я думал над поднятым в этой теме вопросом, но никакого «валидного» решения в голову не приходило (так, чтобы лишние символы от bat-составляющей не попадали в BODY), и мне казалось, что решение невозможно, т.к. если появится символ недопустимый в HEAD, он и всё что идёт за ним автоматически попадает в BODY. Так что ваше решение с очисткой body.innerHTML оказалось для меня довольно неожиданным. Возможно, оно работает только в Internet Explorer, в любом случае — довольно неочевидное и уже за это заслуживает помещения в Коллекцию.

Увидев, что решение существует, я попробовал найти ещё какое-нибудь и понял, что для этого можно использовать приём повторной загрузки, использованный перед этим при решении вопроса о размещении нескольких заданий в одном JScript-файле («при переналожении одной и той же же технологии на саму себя», используется eval() и условная компиляция).

6

Re: CMD/BAT + HTML: два в одном

Я экспериментировал с решением проблемы - как удалить лиший код (bat-составляющая) из результирующего html-кода. первоначальный вариант был существенно длиннее. Потом я понял как это работает. Когда запускается mshta, тот, в свою очередь, запускает html-парсер, который начинает строить DOM из того, что есть:
1. Вначале строит HTML, потом BODY, в который попадает начало файла.
2. Затем встречаются теги HTML, BODY, и все начинается сначала. Но DOM уже построен и парсер снова перестраивает его с учетом того, что уже есть.
Однако если сразу запустить код с очисткой - body.innerHTML = '', - то BODY будет пустым, и, на стадии 2, результирующий DOM оказывается чист. Этого достаточно. Мне кажется, что дополнительные работы по очистке кода избыточны. Возможно - нет. Но я не знаю, насколько это решение востребовано. Если оно и интересует меня, то только с академической точки зрения - то есть вопрос "можно ли так сделать" решен.

( 2 * b ) || ! ( 2 * b )

7

Re: CMD/BAT + HTML: два в одном

У меня чисто работает:

<!--:nul :
@goto BAT
-->

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

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

8 (изменено: wisgest, 2014-01-19 03:46:59)

Re: CMD/BAT + HTML: два в одном

И даже так:

<!-- :
. . .

9

Re: CMD/BAT + HTML: два в одном

Круто! Весь cmd-код находится в html-комментарии. и не требуется, как это было в моем сообщении, дополнительный код для удаления лишней разметки. Вот только не стал бы разбивать без нужды весь cmd-код на части. Пусть будет так:


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

<html>
<head><title>HTA window</title></head>
<body><h1>Hello, world!</h1></body>
</html>
( 2 * b ) || ! ( 2 * b )

10 (изменено: wisgest, 2014-01-19 04:36:02)

Re: CMD/BAT + HTML: два в одном

Rumata пишет:

Вот только не стал бы разбивать без нужды весь cmd-код на части.

По крайней мере в XP SP1, как помню, если в начале HTA до первого из тегов <HTML>, <BODY>, <HEAD> или <SCRIPT> был умеренно большой комментарий, то всё содержимое отображалось как plain text вместо HTML.

+ Первоначальные варианты первой строки
<!--:nul rem
<!--:nul cls
<!--:nul goto BAT

— последние два работают из командных файлов, но не при ручном вводе команд, первый, как и

<!-- rem

не выдаёт ошибки и при ручном вводе.

11

Re: CMD/BAT + HTML: два в одном

Это частично пересекается с решением CMD/BAT + JavaScript: два в одном.

Встречал другой вариант запуска JS из CMD с использованием MSHTA. Не вижу большой выгоды от использования последнего в силу трудности поддержки и потери читабельности кода. Тем не менее вот еще одно решение с помощью которого можно выполнить JS-код:. Однако среда исполнения другая - браузер. Возможно, в некоторых случаях это может оказаться полезным.

hello_world.bat


@if (true == false) @end /*!

@echo off

mshta "about:<script src='file://%~f0'></script><script>close()</script>" %*

goto :EOF

*/

alert("Hello, world!");

( 2 * b ) || ! ( 2 * b )