1

Тема: JScript: динамическое формирование окна HTA

Скрипт в формате WSF:

<?xml version='1.0' encoding='windows-1251' standalone='yes'?>
<job>
<resource id='HTML'><![CDATA[<HTML>
<HEAD><TITLE>WSH + HTA</TITLE>
<HTA:APPLICATION border='none'/>
</HEAD>

<BODY>
<FORM name='form1'>
  <INPUT id='btn1' type='button' value='Кнопка 1'>
  <INPUT id='btn2' type='button' value='Кнопка 2'>
  &nbsp;
  <INPUT type='reset' value='Закрыть'>
</FORM>

<P>При нажатии на кнопки "Кнопка 1" или "Кнопка 2" будет выведено сообщение
"Раз", а затем через 5&nbsp;сек. сообщение "Два". Задержка между сообщениями
создаётся с помощью метода WScript.Sleep().</P>

<P>Разница заключается в том, что обработчик события onclick кнопки "Кнопка 1"
выполняется в контексте запустившего процесс mshta.exe сценария, —
очевидно, что при таком подходе мы можем свободно использовать все методы
объекта WScript, а не только Sleep().</P>

<P>Обработчик события onclick кнопки "Кнопка 1" выполняется в контексте
окна HTA, — для этого нам понадобилось передать окну ссылку на объект WScript
(для первого случая это не требуется). Этот пример сделан, скорее,
для демонстрации возможности и такого подхода; но следует отметить, что только
этот подход будет работать при назначения обработчиков событий onload и
onunload окна.</P>
</BODY></HTML>
]]></resource>


<script language="JScript"><![CDATA[
var IE=new ActiveXObject("InternetExplorer.Application");
var mailbox_name=Math.floor(Math.random()*100000000).toString();
IE.Navigate("about:blank"); while (IE.Busy) WScript.Sleep(100);
IE.Document.Script.name=mailbox_name;

var window=null;
IE.Document.Script.Callback=function (arg) {
  IE.Document.Script.Callback=null;
  IE.Quit(); delete IE, mailbox_name;
  window=arg; window.eval("delete W, S;");
  return getResource("HTML");
};

var WshScriptExec=(new ActiveXObject("WScript.Shell")).Exec(
  "mshta.exe \"javascript:"+
    "W=(new ActiveXObject('Shell.Application')).Windows();"+
    "for(i=W.Count;--i>=0;)"+
      "try{"+
        "S=W.Item(i).Document.Script;"+
        "if(S.name=='" + mailbox_name + "')break;"+
      "}catch(e){}"+
    "S.Callback(window);"+
  "\""
);
while (!window) WScript.Sleep(100);


//window.document.form1.onreset=window.close;
window.document.form1.onreset=function () {window.close();};
//window.eval('window.document.form1.onreset=function () {window.close();};');
//window.document.form1.onreset=function () {WshScriptExec.Terminate();};

window.document.form1.btn1.onclick=function () {
  window.alert("Раз"); WScript.Sleep(5000); window.alert("Два");
};

window.WScript=WScript;
window.eval('\
  document.form1.btn2.onclick=function () {\
    alert("Раз"); WScript.Sleep(5000); alert("Два");\
  };\
')


while (WshScriptExec.Status==0) WScript.Sleep(300);
]]></script>
</job>

При запуске скрипта будет открыто окно HTA с несколькими кнопками. Никаких временных файлов не создаётся.
Автор примера - wisgest.

Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

2

Re: JScript: динамическое формирование окна HTA

Усовершенствованный вариант предыдущего примера, изменения:
- проверка окончания загрузки содержимого окна;
- отключено обновление окна (контекстное меню и клавиша F5), приводившее к ошибке;
- поиск временного вспомогательного невидимого окна IE по его HWND, а не по генерируемому случайным образом имени;
- сокращены некоторые пути, например, window.form1.btn1 вместо window.document.form1.btn1;
- исправлена ошибка в 3-м абзаце пояснительного текста: «Кнопка 2» вместо «Кнопка 1».

<?xml version='1.0' encoding='windows-1251' standalone='yes'?>
<job>
<resource id='HTML'><![CDATA[<HTML>
<HEAD><TITLE>WSH + HTA</TITLE>
<HTA:APPLICATION border='none' contextMenu='no'/>
</HEAD>

<BODY>
<FORM name='form1'>
  <INPUT id='btn1' type='button' value='Кнопка 1'>
  <INPUT id='btn2' type='button' value='Кнопка 2'>
  &nbsp;
  <INPUT type='reset' value='Закрыть'>
</FORM>

<P>При нажатии на кнопки "Кнопка 1" или "Кнопка 2" будет выведено сообщение
"Раз", а затем через 5&nbsp;сек. сообщение "Два". Задержка между сообщениями
создаётся с помощью метода WScript.Sleep().</P>

<P>Разница заключается в том, что обработчик события onclick кнопки "Кнопка 1"
выполняется в контексте запустившего процесс mshta.exe сценария, —
очевидно, что при таком подходе мы можем свободно использовать все методы
объекта WScript, а не только Sleep().</P>

<P>Обработчик события onclick кнопки "Кнопка 2" выполняется в контексте
окна HTA, — для этого нам понадобилось передать окну ссылку на объект WScript
(для первого случая это не требуется). Этот пример сделан, скорее,
для демонстрации возможности и такого подхода; но следует отметить, что только
этот подход будет работать при назначения обработчиков событий onload и
onunload окна.</P>
</BODY></HTML>
]]></resource>


<script language="JScript"><![CDATA[
var IE=new ActiveXObject("InternetExplorer.Application");
IE.Navigate("about:blank"); while (IE.Busy) WScript.Sleep(100);

var window=null;
IE.Document.Script.Callback=function (arg) {
  IE.Document.Script.Callback=null;
  IE.Quit(); delete IE;
  window=arg; window.eval("delete W, i;");
  return getResource("HTML");
};

var WshScriptExec=(new ActiveXObject("WScript.Shell")).Exec(
  "mshta.exe \"javascript:"+
    "W=(new ActiveXObject('Shell.Application')).Windows();"+
    "for(i=W.Count;--i>=0;)if(W.Item(i).HWND=='"+ IE.HWND +"')break;"+
    "W.Item(i).Document.Script.Callback(window);"+
  "\""
);
while (!window) WScript.Sleep(100);
while (window.document.readyState!="complete") WScript.Sleep(100);


window.document.onkeydown=function () {return window.event.keyCode!=116;};

//window.form1.onreset=window.close;
//window.form1.onreset=function () {window.close();};
window.eval('window.form1.onreset=function () {window.close();};');
//window.form1.onreset=function () {WshScriptExec.Terminate();};

window.form1.btn1.onclick=function () {
  window.alert("Раз"); WScript.Sleep(5000); window.alert("Два");
};

window.WScript=WScript;
window.eval('\
  form1.btn2.onclick=function () {\
    alert("Раз"); WScript.Sleep(5000); alert("Два");\
  };\
')


while (WshScriptExec.Status==0) WScript.Sleep(300);
]]></script>
</job>

Автор примера - wisgest.

Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.