Тема: WSH: трансляция объекта WScript
COM-сервер WshScript.wsc предоставляет возможность использования стандартного объекта WScript там, где он недоступен непосредственно (например, в HTA).
WshScript.wsc
<?xml version='1.0' encoding='windows-1251' standalone='yes'?>
<component id='WshScript'>
<registration progid='WshScript'/>
<public>
<property name='Name' dispid='0'><get /></property>
<property name='WScript'><get /></property>
<method name='Add'/>
<method name='Remove'/>
</public>
<resource id='LocalizedName'>Сценарий сервера сценариев Windows</resource>
<script language='JScript'><![CDATA[
var WshGlobal;
(function () {
var
WshShell=new ActiveXObject("WScript.Shell"),
WshEnvironment=WshShell.Environment("Process");
var
window_name=String(Math.random());
SavedEnvString=WshEnvironment("WshScript_window_name");
WshEnvironment("WshScript_window_name")=window_name;
WshShell.Run("WScript.exe \"%windir%\\System32\\WshScript1.js\"", 0, true);
var ShellWindows=(new ActiveXObject("Shell.Application")).Windows();
for (var i=ShellWindows.Count; --i>=0;) {
var IE=ShellWindows.Item(i);
try {
var Script=IE.Document.Script;
if (Script.name==window_name) {
WshGlobal=Script.WshGlobal; IE.Quit();
if (SavedEnvString)
WshEnvironment("WshScript_window_name")=SavedEnvString;
else
WshEnvironment.Remove("WshScript_window_name");
return;
}
} catch (Err) {}
}
})();
/************************************/
function get_Name() {return getResource("LocalizedName");}
function get_WScript() {return WshGlobal.WScript;}
function Add(EventName, EventHandler) {WshGlobal[EventName]=EventHandler;}
function Remove(EventName) {delete WshGlobal[EventName];}
]]></script>
</component>
WshScript.js
// %windir%\System32\WshScript.js
// Испольуется WshScript.wsc для получения объекта WScript
(function () {
var IE=new ActiveXObject("InternetExplorer.Application");
IE.Navigate("about:blank"); while (IE.Busy) WScript.Sleep(50);
var Script=IE.Document.Script;
Script.WshGlobal=this;
Script.name=
(new ActiveXObject("WScript.Shell")).
ExpandEnvironmentStrings("%WshScript_window_name%");
})();
for (;;) WScript.Sleep(0x7fffffff);
WshScript1.js
// %windir%\System32\WshScript1.js
// Испольуется WshScript.wsc для синхронизации с WshScript.js
var WshShell=new ActiveXObject("WScript.Shell");
WshShell.Run("CScript.exe \"%windir%\\System32\\WshScript.js\"", 0, false);
var window_name=WshShell.ExpandEnvironmentStrings("%WshScript_window_name%");
var ShellWindows=(new ActiveXObject("Shell.Application")).Windows();
for (;;) {
for (var i=ShellWindows.Count; --i>=0;)
try {
if (ShellWindows.Item(i).Document.Script.name==window_name)
WScript.Quit();
} catch (Err) {}
WScript.Sleep(50);
}
Файлы WshScript.wsc, WshScript.js и WshScript1.js размещаются в каталоге %windir%\System32\, при этом WshScript.wsc необходимо зарегистрировать в системе как COM-сервер.
COM-сервер WshScript.wsc предоставляет ряд свойств и методов:
- свойство WScript (только чтение) возвращает стандартный объект WScript;
- метод Add(EventName, EventHandler) добавляет обработчик события для объекта, созданного с помощью WScript.CreateObject();
- метод Remove(EventName) удаляет созданный ранее обработчик события.
Файл test.hta демонстрирует использование COM-сервера WshScript.wsc и транслируемого объекта WScript.
test.hta
<HTML>
<HEAD>
<META http-equiv='Content-Type' content='text/html; charset=windows-1251'>
<SCRIPT language='JavaScript' type='text/javascript'><!--
var WshScript=new ActiveXObject("WshScript"), WScript=WshScript.WScript;
alert(WScript.ScriptFullName);
WScript.Sleep(5000);
var WshShell=WScript.CreateObject("WScript.Shell");
var WshScriptExec=WshShell.Exec("cmd.exe");
WshScriptExec.StdIn.WriteLine("dir");
WshScriptExec.StdIn.WriteLine("exit");
alert(WshScriptExec.StdOut.ReadAll());
onunload=function () {WScript.Quit();};
// --></SCRIPT>
<SCRIPT language='VBScript' type='text/vbscript'><!--
Dim IE
Sub document_onclick()
Set IE = WScript.CreateObject("InternetExplorer.Application", "IE_")
IE.Visible = True
WshScript.Add "IE_OnQuit", GetRef("IE_OnQuit")
End Sub
Sub IE_OnQuit()
IE.Visible = False 'чтобы увидеть следующее сообщение,
'т.к. фокус окну HTA не передаётся
alert "Окно Internet Explorer будет закрыто."
End Sub
' --></SCRIPT>
</HEAD>
<BODY>
<P>При щелчке мышью по странице будет открыто окно Internet Explorer,
при закрытии которого будет выведено сообщение
«Окно Internet Explorer будет закрыто.».</P>
<P><SMALL>Повторный щелчок до закрытия Internet Explorer
может привести к ошибке.</SMALL></P>
</BODY></HTML>
При запуске этого hta происходит следующее:
- выводится полный путь к файлу WshScript.js (объект WScript которого транслируется);
- делается пауза на 5 секунд средствами объекта WScript;
- демонстрируется работа с консольными приложениями, запускаемыми с помощью WshShell.Exec() (без появления "чёрного окна", т.к. WshScript.js выполняется в невидимом окне): запускается команда dir и выводится результат её работы;
- отображается окно hta; щелчок в окне приводит к созданию окна Internet Explorer с обработкой его события "OnQuit": при закрытии этого окна hta выдаст сообщение;
- при закрытии окна hta вызывается WScript.Quit(), чтобы завершить процесс CScript.exe; это действие является обязательным, иначе процесс останется в памяти.
Теперь о принципах работы. При создании объекта COM-сервера "WshScript" происходит следующее:
- создаётся переменная среды WshScript_window_name, в которую записывается случайная строка; эта строка впоследствии используется как имя служебного невидимого окна Internet Explorer, которое необходимо для работы;
- запускается скрипт WshScript1.js с ожиданием его завершения;
- скрипт WshScript1.js асинхронно запускает скрипт WshScript.js и ожидает появления окна Internet Explorer с именем WshScript_window_name; когда такое окно появляется, скрипт WshScript1.js завершает свою работу;
- скрипт WshScript.js запускает Internet Explorer, создавая скрытое окно с именем WshScript_window_name; скрипт передаёт свойству "Script" объекта "Document" окна Internet Explorer свой глобальный контекст ("this"), из которого потом можно будет вытащить объект WScript; этот скрипт никогда не завершит работу, пока не будет вызван метод Quit() его объекта WScript (организуется бесконечный цикл);
- когда работа скрипта WshScript1.js завершена, управление передаётся обратно в COM-сервер, а в системе уже есть скрытое окно Internet Explorer с именем WshScript_window_name;
- в системе разыскивается окно Internet Explorer с именем WshScript_window_name, и из свойства "Script" его объекта "Document" извлекается глобальный контекст скрипта WshScript.js; свойство "WScript" этого контекста и будет искомым объектом WScript, который предоставляется COM-сервером как своё публичное свойство "WScript"; окно Internet Explorer закрывается.
Автор идеи - wisgest.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.