<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; HTA & JScript: HTA silent stop and close - тихая остановка и закрытие]]></title>
	<link rel="self" href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=15788&amp;type=atom" />
	<updated>2020-11-01T13:16:44Z</updated>
	<generator>PunBB</generator>
	<id>http://forum.script-coding.com/viewtopic.php?id=15788</id>
		<entry>
			<title type="html"><![CDATA[HTA & JScript: HTA silent stop and close - тихая остановка и закрытие]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=143074#p143074" />
			<content type="html"><![CDATA[<p>Предлагаю рассмотреть отдельной темой, как можно <strong>остановить скрипт в HTA и при необходимости закрыть остановленный скрипт без пробегания последующих строк кода</strong>.</p><p>Разбор этой темы может быть полезен тем, кто пишет гибридный код или разрешает перезапускать приложению самому себя несколько раз.</p><p>Каждый новый перезапуск обычного гибридного приложения представляет из себя его новый экземпляр из отдельного участка кода, помещенного в if-else.<br />Вложенность if-else требует предваряющего объявления глобальных переменных и функций за ее пределами, что может снижать производительность, если предыдущим экземплярам эти глобальные переменные были не нужны. Плюс появляется лишняя лесенка в самом коде.</p><p>Но можно ли вызвать код точечно без структуры &quot;else&quot; с более поздним объявлением глобальных переменных, свойственных только для текущего экземпляра, не обрабатывая участки кода, не предназначенные новому экземпляру?<br />Мой ответ - можно. Для этого нужно остановить скрипт предыдущего экземпляра перед выполнением &quot;чужого&quot; кода.</p><p>На практике такой подход используется в примерах &quot;HTA &amp; JScript: HTA as 64 bit in focus - запуск HTA как 64 bit в фокусе&quot; и &quot;HTA &amp; JScript: Extended Drop Target - Юникод-приемник файлов и папок&quot;, рассмотренных на данном форуме.</p><br /><p><strong>Закрытие скрипта без пробегания последующих строк кода.</strong></p><p>Включите звук в ваших колонках и запустите следующий скрипт в HTA:</p><div class="codebox"><pre><code>&lt;script&gt;

close();
//onerror=function(){close();};throw 0;

close();
close();
for(var i=0;i&lt;100;i++)
    close();
var a=0;
a++;
a++;
a++;
close();

alert(&#039;&quot;Baby, can\&#039;t you see?\n&#039;+
&#039;I\&#039;m calling\n&#039;+
&#039;A guy like you\n&#039;+
&#039;Should wear a warning\n&#039;+
&#039;It\&#039;s dangerous\n&#039;+
&#039;I\&#039;m falling...&quot;&#039;+String.fromCharCode(169));

&lt;/script&gt;</code></pre></div><p>Вы услышите &quot;динь&quot; от &quot;alert&quot;, завершаюшего код. И это после сотен вызовов &quot;close&quot;!</p><p>Кто-то из вас мог об этом и не подозревать, но глубокое исследование при включенном общении скриптов между собой подтвердило, что закрытие для браузера еще не означает буквально закрытие: при линейном вызове он пробегается вплоть до самой последней строки скрипта.<br />При такой пробежке могут возникать и тихо ловиться разнообразные ошибки, особенно если скрипт не был готов к пробегаемой части кода, а также осуществляются нежелательные инициализации, например, сторонних объектов, которые предназначались без использования вложенности &quot;else&quot; для другого экземпляра приложения.</p><p>И это поведение браузера по умолчанию! Мне удалось отменить такие попытки браузера, направив его в обработку ошибок.</p><p>Раскомментируйте вторую строку, и браузер покорно сделает, что от него требуется - закроет скрипт сразу после вызова, и &quot;динь&quot; больше не будет.<br />Это действенный метод для закрытия скрипта без пробегания последующих строк кода.</p><br /><p><strong>Остановка скрипта. Нюансы.</strong></p><p>Характерной для WScript и CScript функции &quot;Sleep&quot; для JScript и VBScript в HTA нет, но есть &quot;setTimeout&quot;, что является большой разницей, так как последующая часть кода без таймаута в HTA продолжит извлекаться.</p><p>Остановить скрипт совсем в HTA все же можно, например, модальным диалогом, и лучше скрытым. Сделать это можно так:</p><div class="codebox"><pre><code>&lt;script&gt;
showModalDialog(&#039;javascript:setTimeout(function(){close();},3000);&#039;, 0, &#039;dialogWidth:0;unadorned:1;&#039;);
alert(&#039;I am shown in 3 seconds of waiting!&#039;);
&lt;/script&gt;</code></pre></div><p>Все хорошо, но есть один нюанс - что делать, если требуется продолжение или закрытие остановленного скрипта, но не по таймауту, который может самостоятельно контролировать модальный диалог, как показано в примере выше, а по определенному событию.<br />Исследование показывает, что общаться со скриптом модальный диалог не может.<br />На выручку приходит <a href="http://forum.script-coding.com/viewtopic.php?id=5573">обмен объектами между скриптами</a> от Xameleon.<br />Закрываем остановленный скрипт из другого окна, и на этом все. Как бы да, но нет.</p><p>Глубокое исследование показывает, что принудительное закрытие извне остановленного модальным диалогом скрипта приводит к нежелательному мерцанию плитки приложения на панели задач.<br />Что же там может мерцать, если, например, приложение и вовсе было заранее скрыто от показа на панели задач?<br />А мерцает спрятанный нами ранее модальный диалог, который как дикий зверь вырывается из под контроля на панель задач на какие-то миллисекунды во время принудительного закрытия родительского окна.<br />По всей видимости, для модального диалога такой случай не рассматривался разработчиками данного компонента как возможный.</p><p>Мне удалось докрутить решение до полноценного - договориться с модальным диалогом как с обычным окном, с которым также можно обменяться объектами.<br />После закрытия диалога извне основной скрипт разморозится, его выполнение продолжится, где далее нужно, как обычно, закрыть теперь уже сам скрипт методом &quot;close&quot; его же собственного окна и избавиться при необходимости от пробегания последующих строк кода рассмотренным выше способом.</p><p>А вот еще одна задача - как сделать так, чтобы скрипт был остановлен на выполнение последующих строк кода, но при этом сработал таймаут для другой функции и, что сложнее, без обмена объектами между скриптами?<br />Увы, простой предварительный вызов &quot;setTimeout&quot; не сработает вовремя: скрипт при такой постановке задачи оказывается заморожен раньше этого события.<br />Я нашел для решения такой задачи следующий способ - достаточно вызвать &quot;setTimeout&quot; в другом &quot;потоке&quot;, например, со стороны псевдоокна ActiveX объекта &quot;htmlfile&quot;:</p><div class="codebox"><pre><code>&lt;script&gt;
setTimeout(function(){alert(&#039;I am shown after all other messages!&#039;);}, 1000);

GetObject(&#039;\\&#039;,&#039;htmlfile&#039;).parentWindow.setTimeout(function(){alert(&#039;I am shown in 2 seconds of waiting!&#039;);}, 2000);

showModalDialog(&#039;javascript:setTimeout(function(){close();},3000);&#039;, 0, &#039;dialogWidth:0;unadorned:1;&#039;);
alert(&#039;I am shown in 3 seconds of waiting!&#039;);
&lt;/script&gt;</code></pre></div><br /><p><strong>Итоги. После разбора данной темы мы умеем:</strong><br /></p><ul><li><p>закрывать скрипт без пробегания последующих строк кода;</p></li><li><p>приостанавливать скрипт по собственному таймауту;</p></li><li><p>приостанавливать скрипт до наступления события извне;</p></li><li><p>вызывать методы остановленного скрипта без обмена объектами между скриптами.</p></li></ul><p>Скомбинируем наши умения в следующую задачу: требуется корректно закрыть остановленный скрипт отложенным вызовом внешнего скрипта с дополнительной паузой в работе внешнего скрипта и без пробегания последующих строк кода, в распоряжении есть все объекты, рассмотренные в данной теме.</p><p>Решение смотрим ниже.</p><br /><p><strong>Скриптовый пример имеет следующие специальные возможности:</strong><br /></p><div class="fancy_spoiler_switcher"><div class="fancy_spoiler_switcher_header" data-lang-open="открыть спойлер" data-lang-close="скрыть спойлер"><strong>+</strong>&nbsp;открыть спойлер</div><div class="fancy_spoiler"><ul><li><p>не требует установки какого-либо стороннего программного обеспечения и поддерживает любую версию Windows, начиная с XP (возможно и 2000) с определенными ActiveX объектами, не запрещенными по умолчанию;</p></li><li><p>полностью написан на JScript в файле скриптового формата HTA и использует следующие ActiveX объекты: WScript.Shell, Scriptlet.TypeLib, Shell.Application, htmlfile и Shell.Explorer.2, также известный как Microsoft Web Browser;</p></li><li><p>тестировался и адаптирован для Windows XP, Windows 7 и Windows 10;</p></li><li><p>не пишет каких-либо записей в реестр и не сохраняет каких-либо персональных данных на вашем жестком диске;</p></li><li><p>не выходит в сеть каким-либо способом;</p></li><li><p>получает тихую остановку скрипта в HTA и корректно закрывает отложенный скрипт.</p></li></ul></div></div><br /><p><strong>Скриптовый пример демонстрирует:</strong><br /></p><ul><li><p>как скрыть HTA во время его динамического создания;</p></li><li><p>как получить тихую остановку скрипта в HTA;</p></li><li><p>как корректно закрыть отложенный скрипт</p></li><li><p>и как решить подтвержденные проблемы с немедленным вызовом &quot;moveTo&quot; или &quot;resizeTo&quot; при старте в Windows XP.</p></li></ul><br /><p><strong>Работа с исходным кодом.</strong><br /></p><ol class="decimal"><li><p>Для запуска скриптового примера скопируйте его исходный код и сохраните его в текстовом файле, сменив его расширение на &quot;hta&quot;.</p></li><li><p>Запуск скриптового примера осуществляется двойным нажатием, как и в случае с обычной программой.</p></li><li><p>Перед запуском скрипта закройте или сверните все лишние окна, чтобы увидеть скриптовые сообщения. Для упрощения примера фокусировка окон в нем не предусмотрена.</p></li></ol><p>Рекомендую использовать <a href="http://akelpad.sourceforge.net/en/download.php">AkelPad</a> для просмотра сохраненного исходного кода примера <span class="bbu">с правильными отступами</span>.</p><p>Вы можете использовать скриптовый пример на свое усмотрение, но, пожалуйста, оставьте комментарий с прямой ссылкой на <a href="https://tastyscriptsforfree.wix.com/page/scripts">tastyscriptsforfree.wix.com/page/scripts</a> в этом случае.</p><div class="codebox"><pre><code>&lt;script&gt;
/*
HTA silent stop and close v1.0.1 (h t t p s://tastyscriptsforfree.wix.com/page/scripts)
Copyright 2017-2020 Vladimir Samarets. All rights reserved.
tastyscriptsforfree@protonmail.com

Release date: November 1, 2020.


Use this script sample entirely at your own risk.
This script sample is copyrighted freeware and I am not responsible for any damage or data loss it could unintentionally cause.
You may modify it but please leave a comment with direct link to https://tastyscriptsforfree.wix.com/page/scripts in that case.


*******
The purpose of this script sample:
the script sample is intended for demonstration of how to obtain silent stop for script in HTA and how to close delayed script gracefully.

*******
The script sample has the following special features:

it requires no third party software installation and supports any Windows version since XP with certain ActiveX objects not restricted by default;
it is entirely written in JScript in HTA scripting file format and uses the following ActiveX objects: WScript.Shell, Scriptlet.TypeLib, Shell.Application, htmlfile and Shell.Explorer.2
    also known as Microsoft Web Browser;
it was tested and adapted for Windows XP, Windows 7 and Windows 10;
it writes no registry values and stores no personal settings on your hard disk;
it doesn&#039;t access network in any way;
it obtains silent stop for script in HTA and closes delayed script gracefully.

*******
The script sample demonstrates:

how to hide HTA while having it dynamically created;
how to obtain silent stop for script in HTA;
how to close delayed script gracefully;
and how to deal with confirmed immediate &quot;moveTo&quot; or &quot;resizeTo&quot; issues at application start in Windows XP.

*******
Basic documentation and articles I used:

&#039;WSH: exchanging data and objects between scripts - 2&#039; by Xameleon (March, 2011) in Russian
    (h t t p://forum.script-coding.com/viewtopic.php?id=5573);

&#039;InternetExplorer and WebBrowser objects&#039; by Ludogovskiy Aleksander in Russian
    (h t t p s://script-coding.com/WSH/WebBrowser.html);

&#039;Windows Script 5.6 Documentation&#039; (script56.chm) by Microsoft Corporation
    (h t t p s://w w w.microsoft.com/en-us/download/confirmation.aspx?id=2764);
&#039;MSDN&#039; related documentation by Microsoft Corporation
    (h t t p s://docs.microsoft.com/en-us/);

Windows XP moveTo and resizeTo issues:
&#039;&quot;Access is denied&quot; by executing .hta file with JScript on Windows XP x64&#039; discussion on stackoverflow.com (January 21, 2009)
    (h t t p s://stackoverflow.com/questions/464679/access-is-denied-by-executing-hta-file-with-jscript-on-windows-xp-x64);
&#039;Something strange with HTAs&#039; discussion on social.technet.microsoft.com (September 19, 2011)
    (h t t p s://social.technet.microsoft.com/Forums/officeocs/en-US/92bf1e76-ebd5-4462-bd52-533e69305a5c/something-strange-with-htas?forum=ITCG).

*******
Basic software I used:

AkelPad 4.9.8 by Aleksander Shengalts and Alexey Kuznetsov (as development environment)
    (h t t p://akelpad.sourceforge.net/en/download.php);
OLE/COM Object Viewer v2.10.059 (oleview.exe) by Charlie Kindel, Michael Nelson, and Michael Antonio (for documentation purposes).
*/

document.title=&#039;I am the MASTER script!&#039;;
var ID = new ActiveXObject(&#039;Scriptlet.TypeLib&#039;).GUID.substr(0, 38);     //the unique ID obtaining
document.documentElement.firstChild.insertAdjacentHTML(&#039;afterBegin&#039;, &#039;&lt;object id=&#039; + ID +
    &#039; classid=clsid:8856F961-340A-11D0-A96B-00C04FD705A2&gt;&lt;param name=RegisterAsBrowser value=1&gt;&#039;);      //registering current HTA window in collection of windows

alert(&#039;Wait for 3 seconds till the OUTER script is started.&#039;);
GetObject(&#039;\\&#039;,&#039;htmlfile&#039;).parentWindow.setTimeout      //a timeout here is to show the master script is stopped long before the &quot;The outer script wants me to close now.&quot; message appears
(
    function()                                                                   //the outer script will be executed with a timeout on behalf of the &quot;htmlfile&quot; while the master script is being in stopped state
    {
        new ActiveXObject(&#039;WScript.Shell&#039;).Run(&#039;mshta &quot;about:&lt;title&gt;I am the OUTER script!&lt;\/title&gt;&lt;body&gt;I want the MASTER script to close.&lt;/body&gt;&lt;script&gt;&#039;+
            &#039;!function hide(e){try{moveTo(10000,10000);}catch(e){try{hide();}catch(e){hide();}}}();resizeTo(400,100);moveTo(screen.availWidth/2-200,screen.availHeight/2-200);&#039;+
            &#039;for(var ws=new ActiveXObject(\&quot;Shell.Application\&quot;).Windows(),i=ws.Count;i--&gt;0;)if((w=ws.Item(i))&amp;&amp;w.id==\&quot;&#039;+ID+&#039;\&quot;){setTimeout(function(){w.s.close();},3000);break;}&lt;\/script&gt;&quot;&#039;);
    }
    ,
    3000
);

showModalDialog(&#039;javascript:for(var ws=new ActiveXObject(&quot;Shell.Application&quot;).Windows(),i=ws.Count;i--&gt;0;)if((w=ws.Item(i))&amp;&amp;w.id==&quot;&#039;+ID+&#039;&quot;){w.s=document.Script;break;}&#039;, 0,
&#039;dialogWidth:0;unadorned:1;&#039;);                                     //silent stop of the script

close(alert(&#039;The OUTER script wants me to close now.\n\nI am going to close myself gracefully without any further attempts of executing the rest statements of my code.&#039;));

onerror=function(){close();};throw 0;                             //declining any further attempts of executing the rest statements of the code
alert(&quot;You won&#039;t hear my sound or see me if previous code line is present.&quot;);

&lt;/script&gt;</code></pre></div>]]></content>
			<author>
				<name><![CDATA[lifeflame]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=40203</uri>
			</author>
			<updated>2020-11-01T13:16:44Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=143074#p143074</id>
		</entry>
</feed>
