1 (изменено: JSmаn, 2011-01-30 01:22:34)

Тема: JScript: Создание окна, а также трансляция WScript в HTA

Динамическое формирование окна

Функция CreateWindow создает окно HTA и возвращает ссылку на объект window.

CreateWindow(content, x, y, width, height)

Параметры:

content — необязательный. Строковой параметр. Содержит HTML-разметку окна HTA. По умолчанию "".
x — необязательный. Отступ слева. По умолчанию 0.
y — необязательный. Отступ сверху. По умолчанию 0.
width — необязательный. Ширина окна. По умолчанию 400.
height — необязательный. Высота окна. По умолчанию 300.

Пример использования:

var 
    content = "<hta:application showintaskbar=no><title>Sample</title>",
    window = CreateWindow(content);

Для удобства хранения HTML кода Вы можете использовать WSF.

Код функции:

function CreateWindow(content, x, y, width, height)
{
var HTASettings = "", e, window, Host = this; 

    try {HTASettings = content.match(/<hta[^>]+>/gim)[0].replace(/\r?\n/g, " ").replace(/"/g,"'")} catch (e){};
    
var 
    ID = (new Date).valueOf(),
    CodeForLinking = "\"<title> </title><script>moveTo(-300,-300); resizeTo(0,0)</script>"+HTASettings+"<object id="+ID+" classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object>\"",
    ShellWindows=(new ActiveXObject("Shell.Application")).Windows(),
    NumberOfWindows = ShellWindows.Count;

    (new ActiveXObject("WScript.Shell")).Run("mshta.exe javascript:"+CodeForLinking);
    while (NumberOfWindows==ShellWindows.Count) {WScript.Sleep(10);}

    for (var i=ShellWindows.Count; --i>=0;)
    try
    {
       if  (ShellWindows.Item(i).id == ID) 
       window = ShellWindows.Item(i).parent.parentWindow;
    } catch (e) {}
    
    try {
        window.document.open(); 
        window.Host = Host; 
        window.document.write([content||"", "<script language='JScript' id=\"a",ID,"\">eval; moveTo(", Number(x) || 0,",", Number(y) || 0, "); resizeTo(", Number(width) || 400,",", Number(height) || 300,"); document.getElementById(\"a",ID,"\").removeNode();","</script>"].join(""));
        
    } catch (e) {return}
    return window;
}

Трансляция WScript в окно HTA осуществляется автоматически. Этот объект будет доступен после того как будет построено дерево элементов полностью. Доступ к объекту осуществляется так: window.Host.WScript. Host — это ссылка на Global Object среды WSH.

Особенности функции:
1. Маленький объем кода.
2. Используются встроенные возможности Windows.
3. Окно доступно только тому скрипту, который его создал.
4. Не требуется создание временных файлов.
5. Не используется для связки Internet Explorer.

Эта идея может упростить решения задач, которые обсуждались в темах:
1. VBScript: конструирование и выдача диалогов с помощью HTA
2. JScript: динамическое формирование окна HTA
3. WSH: трансляция объекта WScript
4. HTA: использование WScript.Sleep()
5. VBScript: COM-сервер для управления окнами HTA

Также Вам может пригодиться функция CloseWindowOnQuit. Она закрывает указанное окно по окончанию работы скрипта, а также WaitWindow — ожидание закрытия окна.

function CloseWindowOnQuit(window)
{
    window.eval("setInterval('var e;try{Host.WScript}catch(e){close()}',100)");
}

function WaitWindow(window)
{
    while ((typeof window.document)=="object") WScript.Sleep(10);
}

var HTMLObject = new ActiveXObject("HTMLFile").parentWindow;

function WaitWindowAsync(wnd, callback)
{
    var id = HTMLObject.setInterval(function () {if ((typeof wnd.document)!="object") {HTMLObject.clearInterval(id); callback(wnd)}}, 10)
}

Пример использования:

var window = CreateWindow("<hta:application showintaskbar=no><title>Sample</title>");
CloseWindowOnQuit(window);
WScript.Sleep(4000);

Функция CreateWindowFromFile поможет Вам заменить WshShell.Run("mshta.exe"+Path).

function CreateWindowFromFile(Path, x, y, width, height)
{
    var content = (new ActiveXObject("Scripting.FileSystemObject")).GetFile(Path).OpenAsTextStream(1).ReadAll();
    return CreateWindow(content, x, y, width, height);
}

2 (изменено: Rumata, 2010-02-19 20:10:52)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Исключительно, чтобы придраться к коду

JSman пишет:

...
content — обязательный. Строковой параметр. Содержит HTML-разметку окна HTA.
...

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

Следующий код для необязательных параметров выглядит сложно и вычурно

!x && x!==0? x =100:null;

Попробуйте следующее - все таки это интуитивно понятнее. Так Вы гарантируете именно числовые значения

x = Number(x) || 0;

Аналог для строковых  и логических

s = String(s) || "default string" // строка, гарантированно значение по умолчанию
b = !!b // гарантированно логический тип
( 2 * b ) || ! ( 2 * b )

3

Re: JScript: Создание окна, а также трансляция WScript в HTA

Была у меня заветная недоделочка, основанная на таком же подходе…

function CreateHTA(AppStyle, ResizeToZero) {
  var HTAHostPath="mshta.exe";
  var WshShell=new ActiveXObject("WScript.Shell");
  try {
    HTAHostPath=WshShell.RegRead("HKCR\\CLSID\\"+
      WshShell.RegRead("HKCR\\AppID\\"+HTAHostPath+"\\AppId")+
      "\\LocalServer32\\");
  } catch(Error) {}
  var URL="javascript:document.write(\""+
    "<HTML><HEAD>"+
    "<OBJECT classId='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'>"+
    "<PARAM name='RegisterAsBrowser' value='1'></OBJECT>\");//"+
    Math.random().toString(0x20).slice(2);
  var WindowStyle=parseInt(AppStyle);
  if (isNaN(WindowStyle)) WindowStyle=1; else AppStyle=undefined;
  WshShell.Run("\""+HTAHostPath+"\" "+URL, WindowStyle);
  var ShellWindows=(new ActiveXObject("Shell.Application")).Windows();
  var HTAWindowIsFound=false;
  for (var t=50; --t>=0; WScript.Sleep(1))
    for (var i=ShellWindows.Count; --i>=0;) {
      var WebBrowser=ShellWindows.Item(i);
      try {
        var Document=WebBrowser.Container;
        if (unescape(Document.URL)==URL) {
          HTAWindowIsFound=true;
          if (ResizeToZero) Document.parentWindow.resizeTo(0, 0);
          if (AppStyle!=undefined)
            Document.write(
              "<HTA:APPLICATION "+AppStyle.replace(/>/g, "&gt;")+"/>");
          else
            Document.documentElement.removeNode();
          return Document.open();
        }
      } catch (Err) {if (HTAWindowIsFound) throw Err;}
    }
  throw new Error("Не удалось получить окно HTA");
}

• Функция возвращает объект Document, хотя я склонялся к тому, чтобы переделать на Window: первый случай удобнее, если содержимое документа создаётся на ходу, второй — если загружается из файла (или с любого URL), т.к. после загрузки в окно нового документа, работа с ним через Document приводила к ошибкам доступа.
• Аргумент AppStyle задаёт стиль окна либо как строку аргументов тега HTA:APPLICATION, либо как второй аргумент метода WshShell.Run() — эти значения взаимоисключающие: если задать первое, всё равно будет проигнорировано второе.
• Логический аргумент ResizeToZero задаёт начальные нулевые размеры окна; предполагалось заменить его на полноценное задание размеров…
(Оба аргумента необязательные).
• После вызова функции создаётся невидимое окно HTA, если только в качестве певого аргумента не передана строка аргументов тега HTA:APPLICATION.
Окно становится видимым после вставки в него элемента HTA:APPLICATION, либо после завершения загруки документа (вызова метода Document.close() при его динамическом формировании)
Для того чтобы в окно можно было загрузить существующий документ (из файла или с любого URL) атрибут navigable элемента HTA:APPLICATION должен иметь значение «yes» (это можно задать чрез первый аргумент функции).
--------------------------------------------------------------------------------
Несколько примеров
Управление окном Панели управления «Учётные записи пользователей» в WinXP

<?xml version='1.0' encoding='windows-1251'?>
<job>
<script src='CreateHTA.js' language='JScript'/>

<script language='JScript'><![CDATA[
var Document=CreateHTA("navigable='yes' border='none' ", true), window=Document.parentWindow;
window.location.replace("res://nusrmgr.cpl/nusrmgr.hta");
//WScript.Echo(window===window.open("", "_self"));
window.alert("Готово!");
//Document.links[0].click();
window.document.links[0].click();
]]></script>
</job>
<?xml version='1.0' encoding='windows-1251'?>
<job>
<script src='CreateHTA.js' language='JScript'/>

<script language='JScript'><![CDATA[
var Document=CreateHTA(2);
Document.write("Привет!");
Document.parentWindow.alert(Document.documentElement.outerHTML);
Document.title="Hi :-)";
//Document.parentWindow.alert(Document.documentElement.outerHTML);
Document.close();
Document.parentWindow.alert(Document.documentElement.outerHTML);
Document.write("<HTA:APPLICATION />");
Document.parentWindow.alert(Document.documentElement.outerHTML);
Document.close();
]]></script>
</job>
<?xml version='1.0' encoding='windows-1251'?>
<job>
<script src='CreateHTA.js' language='JScript'/>

<script language='VBScript'><![CDATA[
Dim Document: Set Document=CreateHTA("")
Document.write "Привет!"
Document.parentWindow.alert Document.documentElement.outerHTML
Document.title="Hi :-)"
'Document.parentWindow.alert Document.documentElement.outerHTML
Document.close
Document.parentWindow.alert Document.documentElement.outerHTML
]]></script>
</job>

4

Re: JScript: Создание окна, а также трансляция WScript в HTA

Rumata пишет:

x = Number(x) || 0;

Согласен, принимаю и вношу корректировку :-)

Rumata пишет:

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

Rumata, а что Вы предлагаете по умолчанию для content? А какова целесообразность использования пустого окна?

5 (изменено: Rumata, 2010-02-19 22:44:37)

Re: JScript: Создание окна, а также трансляция WScript в HTA

JSman пишет:

...
Rumata, а что Вы предлагаете по умолчанию для content? А какова целесообразность использования пустого окна?

например, так

function CreateWindow(content, x, y, width, height)
{
    content = content || "<hta:application showintaskbar=no><title>Sample</title>";

небольшие временнЫе затраты с лихвой окупятся удобством пользования - создается некоторое пустое окно без контента. Целесообразность низка. Но будет ли работать Ваша функция в примере ниже? Если - да, тогда это была моя мелкая придирка к Вашему коду и вопрос снимается.

var window = CreateWindow();
( 2 * b ) || ! ( 2 * b )

6 (изменено: JSmаn, 2010-02-20 01:46:27)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Чисто из-за соображений красоты сделал все параметры необязательными. Соответствующий корректив внес в первый пост.

Указанный ниже код создает пустое окно:

window = CreateWindow();

Теперь объект WScript (window.WScript) доступен сразу же после вызова CreateWindow (а конкретнее после того как только дерево элементов будет сформировано).

Также ввел вторую функцию: CloseWindowOnQuit — закрытие окна по окончанию работы скрипта. Она описана в посте №1 этой темы.

Пример использования:

var window = CreateWindow("<hta:application SHOWINTASKBAR=no><title>Sample</title>");
CloseWindowOnQuit(window);
WScript.Sleep(4000);

7 (изменено: Xameleon, 2010-02-21 00:03:19)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Решил присоединиться к теме. ) Благодаря помощи JSman перегнал код на VBS с частичными изменениями.

Получил класс модуль clsHTAWindow c одним методом Open

Параметры

content - HTML код страницы
features - настройки HTA окна без заголовка HTA:Application
x - координаты окна по горизонтали
y - координаты окна по вертикали
width - ширина окна
height - высота окна

Возвращаемый объект Window имеет дополнительное свойство hWnd - действительный идентификатор окна.

Class clsHTAWindow
    Private document,Application,ShellWindow,ShellWindows,ID,CodeForLinking,WshExec,N,form_id,Window,hWnd
    Function Open(content,features,x,y,width,height)
        On Error Resume Next
        Set document = CreateObject("htmlfile"):document.write content: Application = document.getElementsByTagName("APPLICATION")(0).outerhtml
        Set ShellWindows = CreateObject("Shell.Application").Windows: Randomize: ID = CStr(Clng(Rnd*100000))
        CodeForLinking = "<SCRIPT>moveTo(-1000,-1000);resizeTo(0,0);</SCRIPT><OBJECT id=" & ID & " classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><PARAM name=RegisterAsBrowser value=1></OBJECT>" & _
        "<OBJECT id='MSScriptControl' classid='clsid:0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC'><PARAM name=AllowUI value=1></OBJECT><HTA:APPLICATION " & Replace(left(features,100),"""","'") & " />"
        Set WshExec = CreateObject("WScript.Shell").Exec("mshta javascript:""" & CodeForLinking & """")
        For N=1 to 1000
            For Each ShellWindow in ShellWindows
                form_id = ShellWindow.id
                if form_id = ID Then 
                    N = 1000 
                    Exit For
                end if
            Next
        Next
        if Not IsObject(ShellWindow) Then err.Raise vbObjectError,"Open","Не удалось найти окно"
        Set Document = ShellWindow.parent
        Set Window = Document.parentWindow
        hWnd = Window.MSScriptControl.SitehWnd
        Document.write content
        Window.execScript("document.onkeydown = function(){if(event.keyCode == 116){return false}}")
        Window.execScript("window.hWnd=" & hWnd)
        Window.moveTo x,y : Window.resizeTo width,height
        Set Open = Window
    End Function

    Private Sub Class_Terminate
        On Error Resume Next
        if isObject(WshExec) Then WshExec.Terminate
    End Sub
End Class
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

8 (изменено: JSmаn, 2010-02-20 13:03:35)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Подключение обработчика событий

var window = CreateWindow();
window.document.body.attachEvent("onclick", function() {WSH.Echo()});

while ((typeof window.document)=="object") WScript.Sleep(10);

Кстати, когда окно закроется, то typeof window.document покажет «unknown».

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

window.document.write((content || "") + "<script language='JScript'>eval</script>");

9

Re: JScript: Создание окна, а также трансляция WScript в HTA

Оптимизировал код. Он теперь стал еще легче.

10 (изменено: JSmаn, 2010-02-21 03:38:17)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Xameleon интересовался, как сделать так, чтобы attachEvent заработал

window.document.body.attachEvent "onclick", GetRef("Test")

Я ее решил так:

Sub Test
msgbox window.document.body.outerhtml
End Sub

window.eval("var test;")
Set window.test = GetRef ("Test")
window.eval("window.document.body.attachEvent('onclick', function (){test()})")

11 (изменено: Rumata, 2010-02-21 19:09:33)

Re: JScript: Создание окна, а также трансляция WScript в HTA

разрешите и мне приобщиться к этой теме : ) Некоторые аргументы метода сомнительны (например, title). Однако я добавил избыточный аргумент runProps, чтобы можно было иметь некоторую гибкость в пользовании методом. Атрибуты приложения (те что указываются в теге <HTA:APPLICATION />) задаются в виде хеша, например {applicationName: 'oHTA'}. Это снимает заботу о большом количестве параметров и предоставляет гибкость при создании HTML приложения.

var Window = {};

(function(WSHost)
{

var nextID = 0;

/**
 * Создает новое HTML приложение и возвращает ссылку на его основной объект window.
 * Устанавливает две глобальных переменные: 
 * WSHost - для доступа к глобальной области WSH 
 * WScript - для доступа к WScript
 *
 * @param  String  Заголовок окна
 * @param  Object  атрибуты HTML приложения
 * @param  Object  аргументы метода WshShell.Run
 * @return Object
 * @access static
 */
Window.openHTA = function(title, htaProps, runProps)
{
    title = (title || 'hta:blank').replace(/"/g, '&quot;');
    htaProps = htaProps || {};
    runProps = runProps || {};

    var attrs = [];
    for (var p in htaProps) {
        attrs.push(p.toUpperCase() + ': \'' + htaProps[p] + '\'');
    }
    var props = attrs.join(' ');

    var lastID = nextID;
    nextID++;

    var html = [
        '"', 
        '<hta:application ' + props + ' />', 
        '<object id=' + lastID + ' classid=clsid:8856F961-340A-11D0-A96B-00C04FD705A2><param name=RegisterAsBrowser value=1></object>', 
        '<title>' + (title || 'hta:blank') + '</title>', 
        '"'
        ].join('');


    var appList = (new ActiveXObject('Shell.Application')).Windows();
    var appCount = appList.Count;

    (new ActiveXObject('WScript.Shell')).Run('mshta.exe javascript:' + html, Number(runProps.windowStyle) || 0, !! runProps.waitOnReturn);

    if ( !! runProps.waitOnReturn ) {
        return null;
    }

    while ( appCount == appList.Count ) {
        WScript.Sleep(10);
    }

    var window;

    for (var i = 0; i < appList.Count; i++) {
        var id;

        var e;
        try {
            id = appList.item(i).id;
        } catch (e) {
            continue;
        }

        if ( lastID == id ) {
            window = appList.item(i).parent.parentWindow;
            break;
        }
    }

    if ( ! window ) {
        return null;
    }

    window.document.getElementsByTagName('body')[0].innerHTML = '';
    window.WScript = WScript;
    window.WSHost  = WSHost;

    return window;
};

})(this);

Пример 1. Закрытие окна снаружи (HTA закрывается из WSH)

var t = 3000; // Задержка

var w = Window.openHTA();

var h = w.document.createElement('h1');
h.innerHTML = 'This is HTA created from WSH. This window will be closed by WSH after ' + (t / 1000) + ' seconds.';
w.document.body.appendChild(h);

// Через t секунд закрыть окно
WScript.Sleep(t);

w.close();

Пример 2. Закрытие окна изнутри (HTA закроет себя само, но управляющие конструкции создаются в WSH)

var t = 3000; // Задержка

var w = Window.openHTA();

var h = w.document.createElement('h1');
h.innerHTML = 'This is HTA created from WSH. Click somewhere within and it will be closed by itself after ' + (t / 1000) + ' seconds.';
w.document.body.appendChild(h);

// Закрыть через t секунд после клика внутри окна
w.document.attachEvent('onclick', function()
{
    w.setTimeout(function()
    {
        w.close();
    }, t);
});

// Ждать закрытия окна
var e;
try {
    while ( w.document ) {
    }
} catch (e) {
}
( 2 * b ) || ! ( 2 * b )

12

Re: JScript: Создание окна, а также трансляция WScript в HTA

Rumata, я все-таки отказался от идеи оставлять WebBrowser в странице. Мне нравится видеть код страницы нетронутым:)

Вот посмотрите что отображает alert:

var t = 3000; // Задержка

var w = Window.openHTA();

//*
var h = w.document.createElement('h1');
h.innerHTML = 'This is HTA created from WSH. This window will be closed by WSH after ' + (t / 1000) + ' seconds.';
w.document.body.appendChild(h);
w.alert(w.document.documentElement.outerHTML);
/**/
//w.document.documentElement.innerHTML = "";
WScript.Sleep(t);
w.close();

А также для отображения большого контента для странички придется после загрузки писать вот такой код:

window.document.documentElement.outerHTML = content;

Могу точно сказать, что такой способ будет медленнее чем document open &#8594; write &#8594; close.

13 (изменено: Rumata, 2010-02-22 12:32:02)

Re: JScript: Создание окна, а также трансляция WScript в HTA

JSman пишет:

Rumata, я все-таки отказался от идеи оставлять WebBrowser в странице. Мне нравится видеть код страницы нетронутым:)
...

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

window.document.getElementsByTagName('body')[0].innerHTML = '';

Хотя предложенный метод требует бОльших усилий от разработчика, но он добавляет гибкости. Имеющаяся гибкость может окупить скорость генерации страницы. Хотя этот тезис можно оспорить, но, хочу заметить, данный метод в некоторой степени совместим с существующим методом открытия страниц window.open.

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

14

Re: JScript: Создание окна, а также трансляция WScript в HTA

Rumata пишет:

Хотя предложенный метод требует бОльших усилий от разработчика, но он добавляет гибкости. Имеющаяся гибкость может окупить скорость генерации страницы.

Не могли бы объяснить о какой гибкости идет речь?

window.document.getElementsByTagName('body')[0].innerHTML = '';

Может быть лучше так?

window.document.body.innerHTML = '';

15

Re: JScript: Создание окна, а также трансляция WScript в HTA

JSman пишет:

...

window.document.getElementsByTagName('body')[0].innerHTML = '';

Может быть лучше так?

window.document.body.innerHTML = '';

Лучше - в смысле короче? Я точно знаю, что window.document.getElementsByTagName('body')[0] это DOM-объект соответствующий тегу <body>, но не уверен в этом относительно второго.

JSman пишет:

Не могли бы объяснить о какой гибкости идет речь?...

Гибкости, уже заложенной в javascript версии МСИЕ. То есть и обращение к innerHTML, и open/write/close, и методы создания html-объектов и встраивание из в дерево объектов страницы. Если это предусмотрено и Ваш методом, прошу не винить меня в излишнем многословии.

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

16 (изменено: Xameleon, 2010-02-23 01:57:04)

Re: JScript: Создание окна, а также трансляция WScript в HTA

to Rumata & JSman

Rumata пишет:

Лучше - в смысле короче? Я точно знаю, что window.document.getElementsByTagName('body')[0] это DOM-объект соответствующий тегу <body>, но не уверен в этом относительно второго.

Захотелось поучаствовать в обсуждении. Не могу утверждать точно, т.к внутренний механизм работы объектов MSHTML от нас скрыт, но по той документации, что есть в MSDN и по общему построению объектной модели, я могу сказать следующее

window.document.getElementsByTagName('body')[0] Да, это ссылка на объект тела документа. Если быть точным, на первый из коллекции найденых тэгов, но я себе представляю срабатывание этого кода по шагам так:
1) получение ссылки на document от объекта Window через его свойство.
2) вызов метода отбора тэгов body от объекта document.

На сколько я понимаю - getElementsByTagName - вызывает парсинг тела документа + создание в памяти объектов, которые становятся оболочкой для тэгов, а затем помещаются в коллекцию. (Ведь заранее эта коллекция не может существовать)

Если же рассматривать код обращения document.body мы используем прямую ссылку на объект document и сразу получаем ссылку на объект body. Опять же - на сколько я представляю - ссылка на него формируется только при изменении тела документа, а значит от простого обращения парсинг страницы не запускается. И видимо это должно работать быстрее и с меньшими затратами.

(!) Опять же могу ошибаться. Возможно при первом парсинге документа, тэги уже "облачаются" в объекты и помещаются в коллекции. Но я точно этого не знаю.

Подвожу итоги своих размышлений:  100000 раз "пофиг" как вызывать, т.к яркого изменения скорости в срабатывании той или иной строки такого кода заметить нельзя, если он вызывается 1 раз. Только если в цикле это делать, то возможно скорость будет чуть меньше.
Единственное, что заставляет меня выбрать именно вариант с document.body это банальная краткость кода и удобство чтения и понимание скрипта. ) Просто открыв код через несколько недель / месяцев / лет, значительно проще его понять если код короток. А уж если он ещё и с комментариями, то вообще отлично. )

P.S Прошу прощения у админов и модераторов, за столь длинный текст не о чём и вставку такого OFFTOP-а. ) Просто сижу дома неделю, болею, поговорить не с кем, жена учится, ICQ что то лагает, а по телефону говорить разучился. )

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

17

Re: JScript: Создание окна, а также трансляция WScript в HTA

Rumata, хочу сказать, что мне понравилась конструкция в Вашем коде.

(function (host){ … })(this)

Эта конструкция позволяет не создавать переменную на Global Object.

Также хочу отметить, что на сегодняшний день поиск hta-окна средствами встроенного webbrowser является наиболее оптимальным вариантом. Идея такого подхода принадлежит коллеге Xameleon. И я уверен, что других достойных вариантов не появится. Но почему-то решение оставалось продолжительное время довольно грубым, имело длинный и неоптимизированный код. И я, надеюсь, что устранил недостатки приведенным примером. Мое мнение такое, что хороший код должен быть коротким, быстрым, в нем используются только стандартные средства. Если есть у разработчиков критика моего кода, которая позволит породить более лучший вариант, то я буду просто рад, ибо это решение смахивает на «мозговой штурм».

Хочу обратиться модераторам: стоит ли ставить ссылки в темах в коллекции на это решение? Оформить его отдельной темой или добавить?

18

Re: JScript: Создание окна, а также трансляция WScript в HTA

[Модератор чешет затылок ]: я, увы, в JScript полный профан. Старый вариант коллеги Xameleon я ещё кое-как смог понять, а здесь я, увы, пас. Так что решайте сами. В Коллекцию, конечно, сие обязательно надо.

19 (изменено: Xameleon, 2010-02-23 03:41:45)

Re: JScript: Создание окна, а также трансляция WScript в HTA

to alexii:

Ну вроде не всё так плохо же ? ) Я код JSman-а с некоторыми изменениями в класс на VBS переделал.

http://forum.script-coding.com/viewtopi … 189#p33189

Вот же ?

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

20

Re: JScript: Создание окна, а также трансляция WScript в HTA

Если интересно, могу объяснить алгоритм работы функции.

21

Re: JScript: Создание окна, а также трансляция WScript в HTA

Xameleon
Я тоже за краткость кода, но (повторюсь) там где я уверен - уверен сам, уверен что это не внесет непонимания чтения кода. Если document.body и document.getElementsByTagName('body')[0] синонимичны и возвращают ссылку на один и тот же объект, то можно сократить и использовать первое.

JSman
Делал слабую попытку найти описание объекта webbrowser по его classid, но нашел только примеры и дальше одной страницы поисковика не ходил - удовлетворился полученной информацией и авторитетом коллег Серого форума, использующим этот объект для идентификации нового окна.

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

22

Re: JScript: Создание окна, а также трансляция WScript в HTA

Xameleon, не могли бы Вы привести пример использования метода Open из вашего класса clsHTAWindow?

23

Re: JScript: Создание окна, а также трансляция WScript в HTA

Крепыш пишет:

Xameleon, не могли бы Вы привести пример использования метода Open из вашего класса clsHTAWindow?

Конечно ) ! Наваял пример формы авторизации.

Option Explicit

Dim HTAWindow, window, document
Set HTAWindow = New clsHTAWindow

'создаём тело формы
Dim innerhtml
innerhtml = "<HTML>" & _
            "   <HEAD>" & _
            "       <TITLE>форма авторизации</TITLE>" & _
            "       <STYLE>" & _
            "       *{font-family:Verdana;font-size:12;}" & _
            "       </STYLE>" & _
            "   </HEAD>" & _
            "   <BODY scroll=no bgcolor='D4D0C8' style='border:0;'>" & _
            "       <TABLE>" & _
            "           <TR>" & _
            "               <TD>логин:</TD><TD><INPUT id=login value=user></TD>" & _
            "           <TR>" & _
            "           </TR>" & _
            "               <TD>пароль:</TD><TD><INPUT id=password type=password value=12345></TD>" & _
            "           </TR>" & _
            "           </TR>" & _
            "               <TD colspan=2><BUTTON id=button1 style='width:100%;'>Вход</BUTTON></TD>" & _
            "           </TR>" & _
            "       </TABLE>" & _
            "   </BODY>" & _
            "</HTML>"

'формируем окно            
Set window = HTAWindow.Open(innerhtml,"contextmenu=no border=dialog maximizebutton=no minimizebutton=no",-1000,-1000,0,0)

'получаем ссылку на документ
Set document = window.document

'меняем размер окна
const width = 250
const height = 140
window.resizeTo width,height
window.moveTo (window.screen.width-width)/2,(window.screen.height-height)/2

'подключаем событие нажания на кнопку к нашей процедуре авторизации
window.button1.onclick = GetRef("LoginUser")

Sub LoginUser
    Dim login, password
    login = window.login.value
    password = window.password.value
    window.alert("login: " & login & vbCrlf & "password: " & password)
    window.close
End Sub

'ставим цикл ожидания закрытия окна
Do
    WScript.Sleep 100
Loop Until TypeName(document) = "Object"
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

24

Re: JScript: Создание окна, а также трансляция WScript в HTA

Описание объектной модели WebBrowser
WebBrowser Control

Xameleon пишет:

getElementsByTagName - вызывает парсинг тела документа + создание в памяти объектов, которые становятся оболочкой для тэгов, а затем помещаются в коллекцию. (Ведь заранее эта коллекция не может существовать)

Парсинг элементов ведется только при загрузке документа и использовании сеттеров типа outerHTML, innerHTML, insertAdjacentHTML, innerText и прочего. Сразу после парсинга обновляется коллекция элементов, доступная этой инструкцией: document.getElementsByTagName("*"). Если параметром будет имя элемента, то создание коллекции идет на основе полной коллекции, а не парсинга. Следует отметить, что коллекция — это не массив, а совершенно другой объект. Обход всех элементов массива гораздо быстрее, чем в коллекции. Но создание коллекции быстрее, чем создание массива. Чтобы не перебирать все элементы в поисках тегов title, body, html, можно воспользоваться краткой записью доступа к наиболее популярным элементам: document.title — TITLE, document.documentElement — HTML, document.body — BODY.

25

Re: JScript: Создание окна, а также трансляция WScript в HTA

Можно ли выводить текст в hta-окно в реальном времени?

26

Re: JScript: Создание окна, а также трансляция WScript в HTA

Крепыш пишет:

Можно ли выводить текст в hta-окно в реальном времени?

Да, конечно. Также обратите внимание на использование функции CloseWindowOnQuit.

// Код гипертекстового приложения
var HTAContent = "<title>Application</title><h1>Это окно создано из WSH и закроется по окончанию скрипта.</h1>";

var window = CreateWindow(HTAContent);

CloseWindowOnQuit(window);

var p;

WScript.Sleep(1000);
p = window.document.createElement('p');
p.innerHTML = "Создан первый абзац";
p = window.document.body.appendChild(p);

WScript.Sleep(1000);
p = p.insertAdjacentHTML("afterEnd","<p>Создан второй абзац</p>");

WScript.Sleep(1000);
p = window.document.createElement('p');
p.innerHTML = "Создан третий абзац";
window.document.body.appendChild(p);

window.alert("Нажмите ОК для закрытия окна");

27

Re: JScript: Создание окна, а также трансляция WScript в HTA

Либо если с VBS-ым классом clsHTAWindow, то как нибудь так:

Dim HTAWindow: Set HTAWindow = New clsHTAWindow
Set window = HTAWindow.open("<TITLE>Тест</TITLE><BODY bgcolor='#eeeeee'></BODY>","border=dialog",100,100,300,200)

Do
    if TypeName(window) = "Object" Then
        Exit Do
    Else
        window.document.body.innerHtml = Time
        WScript.Sleep 1000
    End if
Loop
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

28 (изменено: andreyua, 2010-04-01 19:26:10)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Объясните нубу:
Значит я создаю документ file.vbs

Загоняю туды код:

Dim HTAWindow: Set HTAWindow = New clsHTAWindow
Set window = HTAWindow.open("<TITLE>Тест</TITLE><BODY bgcolor='#eeeeee'></BODY>","border=dialog",100,100,300,200)

Do
    if TypeName(window) = "Object" Then
        Exit Do
    Else
        window.document.body.innerHtml = Time
        WScript.Sleep 1000
    End if
Loop



Class clsHTAWindow
    Private document,Application,ShellWindow,ShellWindows,ID,CodeForLinking,WshExec,N,form_id,Window,hWnd
    Function Open(content,features,x,y,width,height)
        On Error Resume Next
        Set document = CreateObject("htmlfile"):document.write content: Application = document.getElementsByTagName("APPLICATION")(0).outerhtml
        Set ShellWindows = CreateObject("Shell.Application").Windows: Randomize: ID = CStr(Clng(Rnd*100000))
        CodeForLinking = "<SCRIPT>moveTo(-1000,-1000);resizeTo(0,0);</SCRIPT><OBJECT id=" & ID & " classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><PARAM name=RegisterAsBrowser value=1></OBJECT>" & _
        "<OBJECT id='MSScriptControl' classid='clsid:0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC'><PARAM name=AllowUI value=1></OBJECT><HTA:APPLICATION " & Replace(left(features,100),"""","'") & " />"
        Set WshExec = CreateObject("WScript.Shell").Exec("mshta javascript:""" & CodeForLinking & """")
        For N=1 to 1000
            For Each ShellWindow in ShellWindows
                form_id = ShellWindow.id
                if form_id = ID Then 
                    N = 1000 
                    Exit For
                end if
            Next
        Next
        if Not IsObject(ShellWindow) Then err.Raise vbObjectError,"Open","Не удалось найти окно"
        Set Document = ShellWindow.parent
        Set Window = Document.parentWindow
        hWnd = Window.MSScriptControl.SitehWnd
        Document.write content
        Window.execScript("document.onkeydown = function(){if(event.keyCode == 116){return false}}")
        Window.execScript("window.hWnd=" & hWnd)
        Window.moveTo x,y : Window.resizeTo width,height
        Set Open = Window
    End Function

    Private Sub Class_Terminate
        On Error Resume Next
        if isObject(WshExec) Then WshExec.Terminate
    End Sub
End Class

Так ?

Потом запускаю в Windows XP - вроде все работает...
Запускаю в Windows 7 -
http://img28.imageshack.us/img28/4025/clipboard01goj.th.jpg
Вот такая ошибка....

Да и, как запускать *.js файлы в семерке ?

Хм, если немного подождать, то вот такая ерунда выскакивает
http://img6.imageshack.us/img6/7545/clipboard02gs.th.jpg

29

Re: JScript: Создание окна, а также трансляция WScript в HTA

Запускать файлы JS можно двойным кликом по ним.

30

Re: JScript: Создание окна, а также трансляция WScript в HTA

В семерке нельзя
Ответьте пожалуйста на мои предыдущие вопросы

31

Re: JScript: Создание окна, а также трансляция WScript в HTA

В System32 присутствует WScript.exe. Попробуйте бросить js-файл на это приложение.

32 (изменено: andreyua, 2010-04-01 22:28:19)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Бросал, то же самое
Как насчет ошибок в семерке ?

33

Re: JScript: Создание окна, а также трансляция WScript в HTA

Картинки относятся к VBScript. Я могу ответить на вопросы, относящиеся к JScript. Я поговорю с коллегой Xameleon, автором реализации на VBS.

34

Re: JScript: Создание окна, а также трансляция WScript в HTA

Было бы неплохо. Я ему на е-майл даже написал

35

Re: JScript: Создание окна, а также трансляция WScript в HTA

2 andreyua:
1) Пока что в семёрке не проверял к сожалению. Видимо там есть какие то ограничения или нестыковки. Так что придётся поизучать эту проблему.
2) OFF:Прошу прощения - с почтой я не в ладах. ) Проверяю её только в случае крайней необходимости, когда знаю, что мне прислать что то должны. 90% времени я доступен в ICQ.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

36

Re: JScript: Создание окна, а также трансляция WScript в HTA

andreyua, Ваш пример у меня в Windows 7 работает без ошибок.

37

Re: JScript: Создание окна, а также трансляция WScript в HTA

У меня тоже ВСЕ работает без ошибок , кроме вышеописанного кода или другого кода с классом clsHTAWindow, примеры которых были приведены в этой теме

А WIN 7 64 или 32 ? У меня 64
А это может быть зависеть от настроек Explorera, mshta.exe и т.д...... ?

38

Re: JScript: Создание окна, а также трансляция WScript в HTA

Ни от чего не зависит. Я Вам говорю, Ваш код у меня на 32-битной Windows 7 работал без проблем.

Есть пара недочетов в моем коде, я их поправлю.

39

Re: JScript: Создание окна, а также трансляция WScript в HTA

JSman пишет:

Ни от чего не зависит. Я Вам говорю, Ваш код у меня на 32-битной Windows 7 работал без проблем.

И ?

Есть пара недочетов в моем коде, я их поправлю.

Ок, но Ваш код - это Java .
Я же использую VBS.

Кстати, у вас, на W7 32 битах , *.js запускается стандартным способом (двойным кликом по файлу)?

Короче, возникновение ошибок  - или это несовместимость кода с W7 x64 или это какой то "странный" глюк у меня.

40 (изменено: Rumata, 2010-04-07 10:32:54)

Re: JScript: Создание окна, а также трансляция WScript в HTA

andreyua пишет:

...Ок, но Ваш код - это Java ...

Простите, я позанудствую.

Java != JavaScript
и
Java != JScript

Это совершенно разные языки.

Java - объектно-ориентированный, компилируемый язык, продукт фирмы SUN.
JScript и JavaScript - разные реализации стандарта языка ECMAScript.

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

41

Re: JScript: Создание окна, а также трансляция WScript в HTA

Я знаю что это разные языки, не нужно было занудствовать
Не надо воспринимать так буквально и неужели не понятно что я имел ввиду

42 (изменено: JSmаn, 2010-04-07 23:51:26)

Re: JScript: Создание окна, а также трансляция WScript в HTA

JS-файлы запускаются двойным кликом.

А я внес в первый пост обновления:
1) Теперь не требуется использование глобальной переменной Host.
2) Контроль исключений при переборе окон.
3) Возможность обращение к WSH Host во время загрузки страницы. Пример:

var code=  "<HTML><TITLE>Заголовок</TITLE><SCRIPT> alert(window.Host.code)</SCRIPT><HTML>",
wnd = CreateWindow(code, 200,200,200,200);
WaitWindow(wnd);

43

Re: JScript: Создание окна, а также трансляция WScript в HTA

Теперь решение вполне зрелое и его можно добавить в Коллекцию

44 (изменено: Xameleon, 2010-04-12 14:40:41)

Re: JScript: Создание окна, а также трансляция WScript в HTA

С помошью JSman-а и я свой код дописал. Избавился от Class модуля. И оставил только функцию.

Function CreateWindow(content,features,x,y,width,height)
    On Error Resume Next
    Dim ShellWindows,ShellWindow,CodeForLinking,form_id,id,i,document,window
    Set CreateWindow = Nothing
    Set ShellWindows = CreateObject("Shell.Application").Windows: Randomize: id = Clng(Rnd*100000)
    CodeForLinking = "<TITLE>&nbsp</TITLE>" & _
    "<SCRIPT>moveTo(-1000,-1000);resizeTo(0,0);</SCRIPT>" &_
    "<HTA:APPLICATION " & features & " />" & _
    "<OBJECT id=" & id & " style='display:none' classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><PARAM name=RegisterAsBrowser value=1></OBJECT>"
    CreateObject("WScript.Shell").Run("mshta about:""" & CodeForLinking & """")
    For i=1 to 1000: For Each ShellWindow in ShellWindows: form_id = Clng(ShellWindow.id)
        if form_id = id Then: Set document = ShellWindow.container:i = 1000: Exit For: End if: Next
    Next
    If document is Nothing Then Exit Function
    Set window = document.parentWindow
    document.open: window.execScript "var Host": Set window.Host = me
    document.write content: document.close
    if x <= 0 Then x = (window.screen.width - width) / 2
    if y <= 0 Then y = (window.screen.height - height) / 2
    window.execScript "document.onkeydown = function(){if(event.keyCode == 116){return false}};" &_
    "setInterval('var e;try{Host.WScript}catch(e){close()}',100);moveTo(" & x & "," & y & ");resizeTo(" & width & "," & height & ")"
    Set CreateWindow = window
End Function

Код примера использования

Option Explicit

Dim Html, window, document, ExitDo

'Формируем тело формы
Html =  "<HTML>" & vbCrlf & _ 
        "<TITLE>Заголовок окна</TITLE><BODY bgcolor='D4D0C8' scroll=no style='border:0;'>" & vbCrlf &_
        "Для проверки подключения события кликните по форме" & vbCrlf &_
        "</BODY>" & vbCrlf &_
        "</HTML>"

Set window = CreateWindow(Html,"showintaskbar=yes",,,250,140)

'Проверяем, создалось ли окно
if window is Nothing Then
    msgbox "Не удалось создать окно !",vbCritical
    WScript.Quit
End if

'Получаем ссылку на документ в окне
set document = window.document

'Подключаем событие клика по форме
document.onclick = GetRef("document_onclick")

'Подключаем событие выгрузки формы
document.body.onunload = getref("window_onunload")

'Событие клика по форме
Sub document_onclick()
    window.alert("Клик !")
End Sub

'Событие закрытия формы
Sub window_onunload()
    ExitDo = True
End Sub

'Запускаем цикл ожидания, чтобы скрипт не завершался, а ждал обработки событий
Do
    WScript.Sleep 100
Loop Until ExitDo

MsgBox "Выполнение скрипта завершено.",vbInformation
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

45 (изменено: badik, 2010-08-18 12:22:12)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Связывание скрипта с НТА использую уже давно. Недавно в одном из скриптов взял функцию CreateWindow. При ее применении обнаружилось не стабильное связывани- потеря окна. Сравнил код функции со своим. Предлагаю изменения в функцию обеспечивающие более стабильную работу.
1.Значение ID определяется  GUID функцию.
2.Поиск ID окна через Enumerator(wss.Windows()) :
3. немного исправил функцию (добавил дополнительный блок обработки ошибок) 18.08.10

function CreateWindow(content, x, y, width, height)
{
var HTASettings = "", e, window, Host = this; 
    width = Number(width) || 400;
    height = Number(height) || 300;
    try {HTASettings = content.match(/<hta[^>]+>/gim)[0].replace(/\r?\n/g, " ").replace(/"/g,"'")}catch(e) {}
    
var tl=WScript.CreateObject('Scriptlet.TypeLib');
var fn=new String(tl.Guid);
var ID=fn.match(/{(.*)}/)[0].replace(/[{}-]+/g,'');

var CodeForLinking = "\"<title> </title><script>moveTo(-300,-300); resizeTo(0,0)</script>"+HTASettings+"<object id="+ID+" classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object>\"";

    (new ActiveXObject("WScript.Shell")).Run("mshta.exe about:"+CodeForLinking);

var wss=new ActiveXObject("Shell.Application")
var i=0
for (i=0 ;i<1000;i++)
{
var ws= new Enumerator(wss.Windows())

for(;!ws.atEnd();ws.moveNext())
{
var oWindow=ws.item()
try
{
if (oWindow.id == ID)
{
window = oWindow.parent.parentWindow
break
}
} catch (e) {}

}
if (window!=null)
break
WScript.Sleep(10)
}

46

Re: JScript: Создание окна, а также трансляция WScript в HTA

badik, благодарю :-)

1.Значение ID определяется  GUID функцией.

var tl=WScript.CreateObject('Scriptlet.TypeLib');
var fn=new String(tl.Guid);
var ID=fn.match(/{(.*)}/)[0].replace(/[{}-]+/g,'');

Предлагаю чуток упростить:

var ID = new ActiveXObject('Scriptlet.TypeLib').Guid.replace(/[^\w]+/g,"");

Что касается

2.Поиск ID окна через Enumerator(wss.Windows()) :

в чем идея?

47

Re: JScript: Создание окна, а также трансляция WScript в HTA

JSman пишет:

badik, благодарю :-)

2.Поиск ID окна через Enumerator(wss.Windows()) :

в чем идея?

1.Похоже если вызывать wss.Windows() до цикла  for ( ... i < 1000) в цикле не всегда возращается полная коллекция окон.
2.У меня wss.Windows() вызывается внутри цикла возвращается действующая коллекция окон

сделал тестовый пример :на 100 открытий/закрый hta окна
проверил на 7 машинах (разной комплектации)
При использовании первого варианта    было 2-8 потерь в зависимости от машины
В моем варианте 1 раз на одной машине

48

Re: JScript: Создание окна, а также трансляция WScript в HTA

Если несложно, покажите пример тестирования. Очень интересно.

49

Re: JScript: Создание окна, а также трансляция WScript в HTA

JSman пишет:

Если несложно, покажите пример тестирования. Очень интересно.

Результаты получал на рабочем примере
Для чистоты эксперемента
Меняем b.js  функции  CreateWindowOld и CreateWindow
Очень сильное влияние оказывает
1.Таймер WaitWindow в b.js и
2.частота загрузки скриптов WScript.Sleep(500) i.js
3.загруженность компа другими процессами

загрузчик тестового файла

var fso = new ActiveXObject("Scripting.FileSystemObject");
var app = new ActiveXObject("Shell.Application")
var shell= new ActiveXObject("WScript.Shell")
var cmd="%comspec% /c cscript    b.js && exit"
for (var i=0; i<100 ;i++)
{
shell.Run(cmd,1)
WScript.Sleep(500)
}
WScript.Quit(0)

Файл с окнами b.js

Sys={}
Sys.window =  CreateWindowOld("<title>"+WScript.ScriptName.split(".")[0]+"</title>\
<div id=LOG_DIV \
style=height:100%;\
overflow:auto;\
font-family: Courier New, Courier;\
border: solid 2px #FFFFFF;\
></div>\
",10,500,550,360)
CloseWindowOnQuit(Sys.window);
WaitWindow(3)



function CreateWindowOld(content, x, y, width, height)
{
var HTASettings = "", e, window, Host = this; 
    width = Number(width) || 400;
    height = Number(height) || 300;
    try {HTASettings = content.match(/<hta[^>]+>/gim)[0].replace(/\r?\n/g, " ").replace(/"/g,"'")}catch(e) {}
    
var 
    ID = (new Date).valueOf(),
    CodeForLinking = "\"<title> </title><script>moveTo(-300,-300); resizeTo(0,0)</script>"+HTASettings+"<object id="+ID+" classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object>\"",
    ShellWindows = (new ActiveXObject("Shell.Application")).Windows(),
    NumberOfWindows = ShellWindows.Count;

    (new ActiveXObject("WScript.Shell")).Run("mshta.exe about:"+CodeForLinking);

    outer: for (var t=0; t<1000; t++)
    inner:  for (var i=ShellWindows.Count; --i>=0;) 
    {try{if(ShellWindows.Item(i).id == ID){window=ShellWindows.Item(i).parent.parentWindow;break outer;}}catch(e) {}
    WScript.Sleep(10);}
    
    try {
        window.document.open(); window.Host = Host; 
        window.document.write([content||"", "<script language='JScript'>eval;resizeTo(",width,",", height,"); moveTo(", Number(x) ||  (window.screen.width - width) / 2,",", Number(y) || (window.screen.height - height) / 2, ");</script>"].join(""));
        window.document.close();
    } catch (e) {return}
    return window;
}









function CreateWindow(content, x, y, width, height)
{
var HTASettings = "", e, window, Host = this; 
    width = Number(width) || 400;
    height = Number(height) || 300;
    try {HTASettings = content.match(/<hta[^>]+>/gim)[0].replace(/\r?\n/g, " ").replace(/"/g,"'")}catch(e) {}
    
var tl=WScript.CreateObject('Scriptlet.TypeLib');
var fn=new String(tl.Guid);
var ID=fn.match(/{(.*)}/)[0].replace(/[{}-]+/g,'');

var CodeForLinking = "\"<title> </title><script>moveTo(-300,-300); resizeTo(0,0)</script>"+HTASettings+"<object id="+ID+" classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object>\"";

    (new ActiveXObject("WScript.Shell")).Run("mshta.exe about:"+CodeForLinking);

var wss=new ActiveXObject("Shell.Application")
var i=0
for (i=0 ;i<1000;i++)
{
var ws= new Enumerator(wss.Windows())

for(;!ws.atEnd();ws.moveNext())
{
var oWindow=ws.item()
if (oWindow.id == ID)
{
window = oWindow.parent.parentWindow
break
}
}
if (window!=null)
break
WScript.Sleep(100)
}

    try {
        window.document.open(); window.Host = Host; 
        window.document.write([content||"", "<script language='JScript'>eval;resizeTo(",width,",", height,"); moveTo(", Number(x) ||  (window.screen.width - width) / 2,",", Number(y) || (window.screen.height - height) / 2, ");</script>"].join(""));
        window.document.close();
    } catch (e) {return}
    return window;
}

function CloseWindowOnQuit(window)
{
    window.eval("setInterval('var e;try{Host.WScript}catch(e){close()}',100)");
}

function WaitWindow(Timer,w)
{
var Stop=(new Date()).getTime()
w=w||Sys.window
Timer=Timer||15
if (Sys.lError)
TitleWindow("есть ошибки")

 while ((typeof w.document)=="object" && (Sys.lError|| ((new Date()).getTime()-Stop)<Timer*1000)) WScript.Sleep(10);
}

50 (изменено: JSmаn, 2010-08-17 22:51:14)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Проверил, но думаю причина различия результатов все-таки кроется в аргументе WScript.Sleep. В моем случае 10 мс, в вашем - 100 мс. Поясню: при запуске 100 программ начинаются «тормоза» (увеличивается время запуска окна), следовательно, при больших нагрузках «события» создания некоторых окон просто не дойдут до родителя.

outer: for (var t=0; t<1000; t++)
    inner:  for (var i=ShellWindows.Count; --i>=0;)
    {try{if(ShellWindows.Item(i).id == ID){window=ShellWindows.Item(i).parent.parentWindow;break outer;}}catch(e) {}
    WScript.Sleep(10);}

Поменял 10 на 100 и результаты стали такие:
35 окон новой версии против 2 старой.

Все дело в Sleep.

51

Re: JScript: Создание окна, а также трансляция WScript в HTA

Истина все-таки  по середине
1. метод Windows() - Creates and returns a new ShellWindows object that is a copy of this ShellWindows object Перевод Google:Создает и возвращает новый объект, который ShellWindows копию этого ShellWindows объекта
2. в моем способе не было  обработки ошибок

var wss=new ActiveXObject("Shell.Application")
var i=0
for (i=0 ;i<1000;i++)
{
var ws= new Enumerator(wss.Windows())

for(;!ws.atEnd();ws.moveNext())
{
var oWindow=ws.item()
try
{
if (oWindow.id == ID)
{
window = oWindow.parent.parentWindow
break
}
} catch (e) {}

}
if (window!=null)
break
WScript.Sleep(10)
}

3. добавил в алгоритм JSman Guid в большой цикл   ShellWindows = wss.Windows(). Начал тестирование
    Появились несвязанные окна. Пытался обработать ошибку исправляя алгоритм и оставляя неизменным поиск окон через Count/Item .  Yt Не получилось.Последний  вариант здесь

var wss=new ActiveXObject("Shell.Application")
    for (var t=0; t<10000; t++)
    {
    try
    {
    ShellWindows = wss.Windows()
    for (var i=0; i < ShellWindows.Count; i++) 
    {
    try
    {
    if(ShellWindows.Item(i).id == ID)
    {window=ShellWindows.Item(i).parent.parentWindow
    break
    }
    }catch(e) {}
    }
    }catch (e) {}
    if (window!=null)
    break
    WScript.Sleep(10)
    }

4. Сегодня у меня касперский занялся полной проверкой диска которая идет часов семь. Было время протестировать
   Мой исправленный пример отработал без ошибок с задержкой в i.js  10 мск
   Ошибки  во втором случаи (Count/Item) с задержкой в i.js  400 мск
   Получается что вероятность появления ошибки при поиске окон через Enumerator и Count/Item различна.

52

Re: JScript: Создание окна, а также трансляция WScript в HTA

Окей Спасибо, badik, вношу изменения.

53

Re: JScript: Создание окна, а также трансляция WScript в HTA

Подскажите пожалуйста, как правильно использовать разработки уважаемого JSman при работе с фреймами. В следующем примере во фреймах отображается не содержимое ресурсов или внешних файлов, а содержимое атрибутов SRC соответствующих тегов FRAME.

//Старт
    // Создание окна с фреймами
    var HTAContent = GetResource(Resources, 0);
    var window = CreateWindow(HTAContent,100,100,600,400);
//Стоп

//===================================================
function GetResource(f, index)
{
    var e; 
    try {return f.toString().split(/\/\*|\*\//)[index*2+1]} catch (e) {}
}
//-----------------------------------------------------------
function Resources() {
/*
<HTML>
<TITLE>Фреймы (проба)</Title>
<frameset rows="40, *, 40">
    <frame src="menu.html" name="menu" frameborder="0" scrolling="no" application = yes>
     <frame src="main.html" name="main" frameborder="1" scrolling="yes" application = yes>
     <frame src="statline.html" name="statline" frameborder="0" scrolling="no" application = yes>
</frameset>
</HTML>
*/
}

//============================================================
function CreateWindow(content, x, y, width, height)
{
var HTASettings = "", e, window, Host = this; 

    try 
    {
        HTASettings = content.match(/<hta[^>]+>/gim)[0].replace(/\r?\n/g, " ").replace(/"/g,"'");
    } 
    catch (e)
    {};
    
var 
    ID = (new Date).valueOf(),
    CodeForLinking = "\"<title> </title><script>moveTo(-300,-300);     resizeTo(0,0)</script>"+HTASettings+"<object id="+ID+
        " classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object>\"",
    ShellWindows=(new ActiveXObject("Shell.Application")).Windows(),
    NumberOfWindows = ShellWindows.Count;

    (new ActiveXObject("WScript.Shell")).Run("mshta.exe javascript:"+CodeForLinking);
    while (NumberOfWindows==ShellWindows.Count) {WScript.Sleep(10);}

    for (var i=ShellWindows.Count; --i>=0;)
    try
    {
       if  (ShellWindows.Item(i).id == ID) 
       window = ShellWindows.Item(i).parent.parentWindow;
    } catch (e) {}
    
    try 
    {
        window.document.open(); 
        window.Host = Host; 
        window.document.write(["<script language='JScript'>eval; moveTo(", Number(x) || 0,",", Number(y) || 0, "); resizeTo(", Number(width) || 400,",", Number(height) || 300,")</script>",content||""].join(""));
    } 
    catch (e) 
        {return}
    return window;
}
//---------------------------------------------------------------
function CreateWindowFromFile(Path, x, y, width, height)
{
    var content = (new ActiveXObject("Scripting.FileSystemObject")).GetFile(Path).OpenAsTextStream(1).ReadAll();
    return CreateWindow(content, x, y, width, height);
}
//===============================================================

Извините, если что-то некорректно написал.

54 (изменено: JSmаn, 2010-12-09 03:22:05)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Вы написали все корректно. А теперь по сути проблемы.
HTA создается динамически. По факту его URL - это about:blank (протокол blank). В этой связи когда вы указываете относительные пути во фреймах, то их  полный адрес станет таким (с протоколом) about:pagename.
Протокол blank получает URL и возвращает его окну. Вот по этой причине мы не видим содержание, а только имя файла страницы. Поэтому следует прямо указывать протокол.

Пока я проверил на http. file:// проверю сегодня.

55

Re: JScript: Создание окна, а также трансляция WScript в HTA

Что касается протокола file, то ситуация довольно интересная. Страницы во фреймах будут отображаться только после вызова window.location.reload() (баги от microsoft). Таким образом, все странички обновятся и отобразятся во фреймсете. Также хочу дополнить, что после применения reload, объект window.Host будет недоступен в HTA. Поэтому укажите вручную window.Host = this;

56

Re: JScript: Создание окна, а также трансляция WScript в HTA

Здравствуйте. Не могу одного понять из первого сообщения. Пожалуйста поясните "суть процесса".
Каким образом при помощи "перебора" всех открытых окон "эксплорера" при помощи объекта ShellWindows (его возвращает метод Windows объекта Shell.Application) находится объект WebBrowser, который "вставлен" в тело динамически созданного окна HTA при помощи тега <object>?

57

Re: JScript: Создание окна, а также трансляция WScript в HTA

1. Принцип динамического создания окна HTA. Для того чтобы отобразить окно HTML-приложения используется программа mshta.exe. В качестве параметра вызова указанного приложения обычно используют имя файла (с необязательным указанием протокола file:\\). Однако mshta поддерживает и иные протоколы, такие как about: и javascript:. Об особенностях этих протоколов я упоминал выше. В качестве примера сделайте вызов mshta "about:<title>123</title>". Окно динамически будет создано с заголовком 123. Однако, из-за ограничения размера строки параметров вызова мы не можем создавать окна с объемным контентом. Поэтому следующей задачей становится каким-то образом подключиться к вновь созданному окну и дополнить его содержание, используя HTML DOM.
2. Принцип механизма поиска окна основывается на переборе элементов коллекции окон WebBrowser, полученной через вызов (new ActiveXObject("Shell.Application")).Windows(). Отбор происходит по атрибуту ID (этот атрибут указан в теге object). Для того, чтобы получить ссылку на искомый объект window сначала получим ссылку на родительский объект Document и воспользуемся свойством parentWindow.
Для того, чтобы постоянно не генерировать коллекцию,  я отслеживаю изменение свойства Count. Как это свойство изменится, значит можно искать нужный элемент.
3.  Далее найденное окно нужно заполнить данными, которые указываются в параметре content при вызове CreateWindow. Для этого мы пользуемся специально предназначенными функциями HTML DOM: document.open и document.write. И после этого возвращаем ссылку на window.

Все ясно?

58 (изменено: Xameleon, 2010-12-11 12:48:12)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Дополню немного. Объект WebBrowser регистрируется в глобальной коллекции ShellWindows при установке его свойства RegisterAsBrowser в True. Благодаря этому можно из внешнего приложения его найти.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

59 (изменено: allycop, 2011-01-28 18:51:56)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Здравствуйте. Возможно ли, у динамически созданного окна HTA, обработать событие закрытия окна по значку (Х) ? В интернете пишут, что у IE это в принципе невозможно. Нужно для корректного выхода из скрипта, создавшего это окно, и завершения работы wscript.exe(cscript.exe).

60 (изменено: JSmаn, 2011-01-30 01:32:44)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Событие до закрытия окна onbeforeunload:

window.document.body.onbeforeunload = callback;

61 (изменено: matiz, 2011-03-03 09:03:48)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Приветствую, моя модификация функции CreateWindow:

function CreateWindow(content, x, y, width, height)
{
var HTASettings = "", e, window, Host = this, ws, shell, w, f=true; 
    try {HTASettings = content.match(/<hta[^>]+>/gim)[0].replace(/\r?\n/g, " ").replace(/"/g,"'")} catch (e){return null;};
var ID = new ActiveXObject('Scriptlet.TypeLib').Guid.replace(/[^\w]+/g,"");
var CodeForLinking = "\"<title> </title><script language='JScript'>for(;;){if(window){window.moveTo(-300,-300);window.resizeTo(0,0);break;}}</script>"+HTASettings+"<object id='"+ID+"' classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name='RegisterAsBrowser' value='1'/></object>\"";
    shell=new ActiveXObject("Shell.Application");
    (new ActiveXObject("WScript.Shell")).Run("mshta.exe javascript:"+CodeForLinking);
    while(f){
        WScript.Sleep(10);
        ws=new Enumerator(shell.Windows()); ws.moveFirst();
        while (ws.atEnd() == false){
            try{
                w=ws.item();
                if(w.id == ID) { window = w.parent.parentWindow; f=false; break; }
                ws.moveNext();
            }catch(e){break;}
        }
    }
    try {
        window.document.open(); 
        window.Host = Host; 
        window.document.write([content||"", "<script language='JScript' id=\"a",ID,"\">eval; window.moveTo(", Number(x) || 0,",", Number(y) || 0, "); window.resizeTo(", Number(width) || 400,",", Number(height) || 300,"); document.getElementById(\"a",ID,"\").removeNode();","</script>"].join(""));
    } catch (e) {return null;}
    return window;
}

62

Re: JScript: Создание окна, а также трансляция WScript в HTA

А в чем ее преимущество?

63

Re: JScript: Создание окна, а также трансляция WScript в HTA

2 matiz:

Что то у меня не получилось Вашим кодом воспользоваться

var NewWindow = CreateWindow("<title>111</title>",100,100,100,100)
WScript.Sleep(5000)

Окно вообще не появляется на экране. Это смысл модификации ?

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

64

Re: JScript: Создание окна, а также трансляция WScript в HTA

Xameleon пишет:

Окно вообще не появляется на экране. Это смысл модификации ?

Попробуй так:

var NewWindow = CreateWindow("<title>111</title><hta:application/>",100,100,100,100);
WScript.Sleep(5000);
Xameleon пишет:

Это смысл модификации ?

Смысл модификации:
1. Изменен алгоритм поиска hta-окна.
2. Перед методами moveTo и resizeTo "добавлено" название объекта window. .

При использовании функции CreateWindow, разработанной JSman (огромное ему спасибо!), и создании одноверменно множества hta-окон возникали проблемы:
1. Некоторые окна не "находились".
2. Вознакала ошибка "Отказано в доступе": было "вылечено" проверкой существования объекта widow и добавлением widow. перед методами moveTo и resizeTo.

65 (изменено: Xameleon, 2011-03-03 12:03:02)

Re: JScript: Создание окна, а также трансляция WScript в HTA

2 matiz:

1) На сколько я помню, я на VBS выкладывал аналог функции CreateWindow.

http://forum.script-coding.com/viewtopi … 583#p34583

Возможно ошибаюсь и открылись новые подробности, но ещё тогда баг с потерей некоторых окон мы с JSman-ом исправляли, убрав из цикла поиска WScript.Sleep. Из-за него скрипт "промахивался". На счёт методов resizeTo и moveTo - они вынесены глобально в код и явно указывать их пренадлежность - смысла не вижу.

2)

("<title>111</title><hta:application/>",

Сэр, ну это как минимум не серьёзно. Прошу простить мою прямоту, но это не модификация, это явная недоработка.

Добавлено позже:

Только что потестил свой старый код. У меня выполняется без сбоев.

Dim i
For i=1 to 10
    set wnd = CreateWindow(i,"",i*50,i*50,100,100)
Next
WScript.Sleep 4000

Function CreateWindow(content,features,x,y,width,height)
    On Error Resume Next
    Dim ShellWindows,ShellWindow,CodeForLinking,form_id,id,i,document,window
    Set CreateWindow = Nothing
    Set ShellWindows = CreateObject("Shell.Application").Windows: Randomize: id = Clng(Rnd*100000)
    CodeForLinking = "<TITLE>&nbsp</TITLE>" & _
    "<SCRIPT>moveTo(-1000,-1000);resizeTo(0,0);</SCRIPT>" &_
    "<HTA:APPLICATION " & features & " />" & _
    "<OBJECT id=" & id & " style='display:none' classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><PARAM name=RegisterAsBrowser value=1></OBJECT>"
    CreateObject("WScript.Shell").Run("mshta about:""" & CodeForLinking & """")
    For i=1 to 1000: For Each ShellWindow in ShellWindows: form_id = Clng(ShellWindow.id)
        if form_id = id Then: Set document = ShellWindow.container:i = 1000: Exit For: End if: Next
    Next
    If document is Nothing Then Exit Function
    Set window = document.parentWindow
    document.open: window.execScript "var Host": Set window.Host = me
    document.write content: document.close
    if x <= 0 Then x = (window.screen.width - width) / 2
    if y <= 0 Then y = (window.screen.height - height) / 2
    window.execScript "document.onkeydown = function(){if(event.keyCode == 116){return false}};" &_
    "setInterval('var e;try{Host.WScript}catch(e){close()}',10);moveTo(" & x & "," & y & ");resizeTo(" & width & "," & height & ")"
    Set CreateWindow = window
End Function
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

66 (изменено: matiz, 2011-03-03 13:14:31)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Xameleon пишет:

Возможно ошибаюсь и открылись новые подробности, но ещё тогда баг с потерей некоторых окон мы с JSman-ом исправляли, убрав из цикла поиска WScript.Sleep. Из-за него скрипт "промахивался". На счёт методов resizeTo и moveTo - они вынесены глобально в код и явно указывать их пренадлежность - смысла не вижу.

Поясню.
Моя программа одновременно запускала от 7 до 14 одинаковых скриптов, например:

Dim WMI, PID
Set WMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2:Win32_Process")
WMI.Create "wscript.exe C:\myscript.js /param:1", Null, Null, PID
WMI.Create "wscript.exe C:\myscript.js /param:2", Null, Null, PID
WMI.Create "wscript.exe C:\myscript.js /param:3", Null, Null, PID
WMI.Create "wscript.exe C:\myscript.js /param:4", Null, Null, PID
'и так далее

Такой запуск скриптов происходит одновременно, т.к. метод Create передает управление сразу обратно в сценарий.

В свою очередь срипт myscript.js в один и тот же момент выполнения создает hta-окно при помощи функции CreateWindow, т.е. hta-окна повляются одновременно (количество появившихся hta-окон равно числу запущенных скриптов). В итоге была "потеря" hta-окон и появление ошибки "Отказано в доступе".
Отладка данной ошибки показывала на метод moveTo при выполнении следующего элемента в функции CreateWindow:

(new ActiveXObject("WScript.Shell")).Run("mshta.exe javascript:"+CodeForLinking);

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

Xameleon пишет:

Сэр, ну это как минимум не серьёзно. Прошу простить мою прямоту, но это не модификация, это явная недоработка.

Согласен, "переборщил" с модификациями. Спасибо.

67

Re: JScript: Создание окна, а также трансляция WScript в HTA

А мой код из примера так же ошибку выбрасывает при множественном запуске или нет ?

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

68

Re: JScript: Создание окна, а также трансляция WScript в HTA

Xameleon пишет:

А мой код из примера так же ошибку выбрасывает при множественном запуске или нет ?

Ваш код при множественном запуске не тестировал, ничего не скажу. Хотя при однократном запуске - работает отлично.

69 (изменено: JSmаn, 2011-03-04 22:46:38)

Re: JScript: Создание окна, а также трансляция WScript в HTA

matiz, проверьте, пожалуйста, новую версию функции:

function CreateWindow(content, x, y, width, height)
{
var HTASettings = "", e, window, Host = this; !content? content="":{};
   content.replace(/<hta[^>]+>/gim, function (m){HTASettings=m.replace(/\r?\n/g, " ").replace(/"/g,"'")});
    
var 
    ID = "a"+Math.floor(Math.random()*10000000);
    CodeForLinking = "<title> </title><script language='jscript'>try{moveTo(-300,-300);resizeTo(0,0);}catch(e){}</script>"+HTASettings+"<object id="+ID+" classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object>",
    ShellWindows=(new ActiveXObject("Shell.Application")).Windows();

    (new ActiveXObject("WScript.Shell")).Run("mshta.exe \"about:"+CodeForLinking+"\"");

    while (!window) 
    {
    WScript.Sleep(10);
    for (var i=ShellWindows.Count; --i>=0;)
    try {    if (ShellWindows.Item(i).id==ID)window=ShellWindows.Item(i).parent.parentWindow;} catch(e){}
    }
        window.document.open(); 
        window.Host = Host; 
        window.document.write([content||"", "<script language='JScript' id=\"a",ID,"\">eval; moveTo(", Number(x) || 0,",", Number(y) || 0, "); resizeTo(", Number(width) || 400,",", Number(height) || 300,"); document.getElementById(\"a",ID,"\").removeNode();","</script>"].join(""));
    return window;
}

70

Re: JScript: Создание окна, а также трансляция WScript в HTA

Потестил.

var i = CreateWindow("ss",100,100,100,100);
var i = CreateWindow("ss",200,200,100,100);
var i = CreateWindow("ss",300,300,100,100);
var i = CreateWindow("ss",400,400,100,100);
var i = CreateWindow("ss",500,500,100,100);
var i = CreateWindow("ss",100,100,100,100);
WScript.Sleep(3000);

Может я чё то не так делаю, но окна не исчезают после выгрузки скрипта.

Пробывал в разные переменные их возвращать - тот же результат.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

71 (изменено: Rumata, 2011-03-04 16:32:41)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Все правильно. Закритие окна - проблема разработчика. Переменная i - ссылается только на объект window, а не на приложение. Для закрытия окна надо вызывать соответствующий метод

var i = CreateWindow(...);
i.close();
( 2 * b ) || ! ( 2 * b )

72

Re: JScript: Создание окна, а также трансляция WScript в HTA

Кхм. Строка 4

   content. ...

Исправить на

   content = (content || ''). ...

Иначе - ошибка при запуске с пустым аргументом content.

Новое окно не имеет объекта document в DOM - надо создавать вручную. Это фича или надо дорабатывать? Я могу ошибаться, но мне помнится, что предыдущая версия функции возвращала более функциональное окно.

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

73 (изменено: JSmаn, 2011-03-04 22:58:46)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Я так понял без комментария тут никак не обойтись.

Начну сначала. В первой версии функции были существенные недостатки, которые проявлялись только при большой нагрузки на процессор: присвоение ID (не стоит привязывать к времени), алгоритм поиска окна.

Чтобы устроить большую нагрузку на проц можно так:

for (i=0;i<20;i++)
(new ActiveXObject("WScript.Shell")).Run("C:\\myscript.js");

где myscript.js можно представить так:

var wnd = CreateWindow();
WScript.Sleep(5000);
wnd.close();

matiz, думаю, что использование Enumerator и TypeLib все-таки излишне.

Xameleon, многократные вызовы CreateWindow рассматриваются только в рамках разных процессов, так как в одном однопоточном процессе функция не проявит свои слабые стороны.

74

Re: JScript: Создание окна, а также трансляция WScript в HTA

Rumata, спасибо, исправил.

!content? content="":{};

75 (изменено: JSmаn, 2011-03-06 11:50:19)

Re: JScript: Создание окна, а также трансляция WScript в HTA

В общем представляю новую версию CreateWindow. Придирайтесь к коду:)

function CreateWindow(content, x, y, width, height)
{
var HTASettings = "", e, window, Host = this; if(!content) content="";
   content.replace(/<hta[^>]+>/gim, function (m){HTASettings=m.replace(/\r?\n/g, " ").replace(/"/g,"'")});
    
var 
    ID = "a"+Math.floor(Math.random()*10000000),
    CodeForLinking = "<title>&nbsp;</title><script language='jscript'>try{moveTo(-300,-300);resizeTo(0,0);}catch(e){}</script>"+HTASettings+"<object id="+ID+" classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object>",
    ShellWindows=(new ActiveXObject("Shell.Application")).Windows();
    (new ActiveXObject("WScript.Shell")).Run("mshta.exe \"about:"+CodeForLinking+"\"");

    while (!window) 
    {
        WScript.Sleep(10);
        for (var i=ShellWindows.Count; --i>=0;)
        try {if (ShellWindows.Item(i).id==ID)window=ShellWindows.Item(i).parent.parentWindow;} catch(e){}
    }
        window.document.open(); 
        window.Host = Host; 
        window.document.write([content,"<script language='JScript' id=\"a",ID,"\">eval; moveTo(",x|| 0,",",y||0,"); resizeTo(",width||400,",",height||300,");document.getElementById(\"a",ID,"\").removeNode();","</script>"].join(""));
    return window;
}

76 (изменено: Rumata, 2011-03-05 02:00:38)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Еще немного придирок по коду:

var 
    ID = "a"+Math.floor(Math.random()*10000000);

должно быть

var 
    ID = "a"+Math.floor(Math.random()*10000000),

или

var 
    ID = "a"+Math.floor(Math.random()*10000000);
var

А вот это я не понимаю.

!content? content="":{};

Зачем таким способом решать отсутствие параметра. Он не лучше предложенного мной и читабельность сильно ухудшается. Я не сразу сообразил - где же исправление. Тернарный оператор красив, но, в данном случае, здесь ему не место. Лучше уж классический условный оператор

if ( ! content ) content = '';
( 2 * b ) || ! ( 2 * b )

77

Re: JScript: Создание окна, а также трансляция WScript в HTA

Rumata пишет:

Все правильно. Закритие окна - проблема разработчика. Переменная i - ссылается только на объект window, а не на приложение. Для закрытия окна надо вызывать соответствующий метод

var i = CreateWindow(...);
i.close();

Не согласен. Любое приложение должно штатно закрывать свои окна в случае падения, так же как это реализовано в Windows. Представьте, если у Вас приложения будут выпадать, а окна оставаться ? Очень красиво ? Проводя аналогии это равноценно некрасивому поведению разработчиков в случаях
1) Приложение устанавливается, но при удалении оставляем мусор в реестре или на диске
2) Приложение во время работы оставляет темповые файлы и не удаляет их по окончании работы
3) Приложение выгружается, но оставляет занятую память. (Memory Leak)

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

78

Re: JScript: Создание окна, а также трансляция WScript в HTA

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

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

79

Re: JScript: Создание окна, а также трансляция WScript в HTA

Rumata пишет:

Приложение, создавшее окно, не знает об этом окне.

А должно знать. Убивая процесс в Windows - Вы же потом не закрываете за ним сотни окон. Они уничтожаются автоматически.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

80

Re: JScript: Создание окна, а также трансляция WScript в HTA

Опять с Вами согласен. Значит надо переписать функцию CreateWindow, так чтобы она возвращала PID процесса, а не ссылку на объект window. Но как при этом сохранить внешний контроль со стороны скрипта? А ведь суть данного предложения именно в том, чтобы создать HTA и сохранить управление его содержимым.

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

81

Re: JScript: Создание окна, а также трансляция WScript в HTA

А что даст PID процесса при аварийном завершении скрипта?
Как вариант можно передавать в HTA ссылку на какой нибудь объект вызывающего скрипта и переодически проверять из HTA доступность этого объекта, при его недоступности закрывать окно.

82

Re: JScript: Создание окна, а также трансляция WScript в HTA

2 wisgest & Rumata: Господа, Вы удивляете меня с каждым постом. Вы примеры в теме смотрели ? Тестировали ?

2 Rumata:

Значит надо переписать функцию CreateWindow, так чтобы она возвращала PID процесса, а не ссылку на объект window

Вот зачем городить грабли, где можно спокойно обойтись без них ??

2 wisgest:

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

    document.open: window.execScript "var Host": Set window.Host = me
    document.write content: document.close
    if x <= 0 Then x = (window.screen.width - width) / 2
    if y <= 0 Then y = (window.screen.height - height) / 2
    window.execScript "document.onkeydown = function(){if(event.keyCode == 116){return false}};" &_
    "setInterval('var e;try{Host.WScript}catch(e){close()}',10);moveTo(" & x & "," & y & ");resizeTo(" & width & "," & height & ")"
    Set CreateWindow = window

Уже давно был решён вопрос автозакрытия. JSman всё придумал и реализовал. И именно таким способом. И не "какой нибудь" объект, а объект хоста (Host)

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

83 (изменено: wisgest, 2011-03-05 23:03:51)

Re: JScript: Создание окна, а также трансляция WScript в HTA

В своё оправдание могу сказать, что вопрос об автозакрытии возник не у меня.
Код уважаемого JSman не пересматривал, т.к. сам принцип его действия у меня сомнения не вызывал ввиду независимого собственного похожего решения.

84

Re: JScript: Создание окна, а также трансляция WScript в HTA

1) Оправдание ? Да я не осуждаю, а всего лишь удивляюсь, что уже созданное начинают придумывать заного.

2) В своём коде я бы поменял только принцип создания окна с Run на Exec, т.к это позволит убить процесс mshta.exe в случае если связь с окном не будет установлена.

Function CreateWindow(content,features,x,y,width,height)
    On Error Resume Next
    Dim ShellWindows,ShellWindow,CodeForLinking,wshExec,form_id,id,i,document,window
    Set CreateWindow = Nothing
    Set ShellWindows = CreateObject("Shell.Application").Windows: Randomize: id = Clng(Rnd*100000)
    CodeForLinking = "<script>moveTo(-1000,-1000);resizeTo(0,0);</script>" &_
    "<hta:application " & features & " />" & _
    "<object id=" & id & " style='display:none' classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2' viewastext><param name=RegisterAsBrowser value=1></object>"
    Set wshExec = CreateObject("WScript.Shell").Exec("mshta about:""" & CodeForLinking & """")
    For i=1 to 1000
        For Each ShellWindow in ShellWindows: form_id = Clng(ShellWindow.id)
            if form_id = id Then
                Set document = ShellWindow.container:
                Set window = document.parentWindow
                document.open: window.execScript "var Host": Set window.Host = me
                document.write content: document.close
                if x <= 0 Then x = (window.screen.width - width) / 2
                if y <= 0 Then y = (window.screen.height - height) / 2
                window.execScript "document.onkeydown = function(){if(event.keyCode == 116){return false}};" &_
                "setInterval('var e;try{Host.WScript}catch(e){close()}',100);moveTo(" & x & "," & y & ");resizeTo(" & width & "," & height & ")"
                Set CreateWindow = window
                Exit Function
            End if
        Next
    Next
    wshExec.Terminate()
End Function
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

85

Re: JScript: Создание окна, а также трансляция WScript в HTA

В первом посте я описывал вот эту функцию:

function CloseWindowOnQuit(window)
{
    return window.eval("setInterval('var e;try{Host.WScript}catch(e){close()}',100)");
}

Конструкция была вынесена в отдельную функцию по разным соображениям: например, имея идентификатор интервала, можно отменить функцию интервала.

Xameleon, во второй строке код стоит явно указать язык скрипта (снижает вероятность возникновения ошибки при парсинге).

86

Re: JScript: Создание окна, а также трансляция WScript в HTA

Xameleon пишет:

2) В своём коде я бы поменял только принцип создания окна с Run на Exec, т.к это позволит убить процесс mshta.exe в случае если связь с окном не будет установлена.

Может быть постараемся найти причины, когда  связь не устанавливается?

87 (изменено: Xameleon, 2011-03-06 12:42:40)

Re: JScript: Создание окна, а также трансляция WScript в HTA

JSman пишет:
Xameleon пишет:

2) В своём коде я бы поменял только принцип создания окна с Run на Exec, т.к это позволит убить процесс mshta.exe в случае если связь с окном не будет установлена.

Может быть постараемся найти причины, когда  связь не устанавливается?

Доброго дня. ) Причины падения я рассматриваю теоретически. Как вариант - запустился HTA, а объект браузера внутри не загрузился из-за запрета на создание в локальной зоне, отсутствия его как такового в системе, ограничение прав на создание и т.п. Всё же может быть. А так - ну не создался и не создался. Процесс mshta.exe выгрузится по концу перебора окон.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

88 (изменено: JSmаn, 2011-03-07 14:03:50)

Re: JScript: Создание окна, а также трансляция WScript в HTA

Окей, значит предлагаю вот такой вот код для тестирования:
Первый файл:

for (i=0;i<20;i++)
(new ActiveXObject("WScript.Shell")).Run("myscript.js");

Второй myscript.js:

function CreateWindow(content, x, y, width, height)
{
var HTASettings = "", e, window, Host = this; !content? content="":{};
   content.replace(/<hta[^>]+>/gim, function (m){HTASettings=m.replace(/\r?\n/g, " ").replace(/"/g,"'")});
    
var 
    ID = "a"+Math.floor(Math.random()*10000000);
    CodeForLinking = "<title>&nbsp;</title><script language='jscript'>try{moveTo(-300,-300);resizeTo(0,0);}catch(e){}</script>"+HTASettings+"<object id="+ID+" classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object>",
    ShellWindows=(new ActiveXObject("Shell.Application")).Windows();
    (new ActiveXObject("WScript.Shell")).Run("mshta.exe \"about:"+CodeForLinking+"\"");

    while (!window) 
    {
        WScript.Sleep(10);
        for (var i=ShellWindows.Count; --i>=0;)
        try {if(ShellWindows.Item(i).id==ID)window=ShellWindows.Item(i).parent.parentWindow;} catch(e){}
    }
        window.document.open(); 
        window.Host = Host; 
        window.document.write([content,"<script language='JScript' id=\"a",ID,"\">eval; moveTo(",x|| 0,",",y||0,"); resizeTo(",width||400,",",height||300,");document.getElementById(\"a",ID,"\").removeNode();","</script>"].join(""));
    return window;
}

var wnd = CreateWindow("<title>123123</title><hta:application caption=no><body>123123</body>");
WScript.Sleep(5000);
wnd.close();

Создаются окна и через 5 секунд закрываются. Если остаются окошки незакрытыми или ошибки возникают, то сообщите:)

89

Re: JScript: Создание окна, а также трансляция WScript в HTA

JSman, коллега. Я конечно же тестировал Ваш код и могу сказать он в свете найденных багов превосходен. Я сторонник того, чтобы из скрипта иметь доступ к содержимому окна и его DOM нежели процессу.

Значит надо переписать функцию CreateWindow...

Это всего лишь моя дружеская перепалка с коллегой Xameleon.

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

90

Re: JScript: Создание окна, а также трансляция WScript в HTA

JSman пишет:

Может быть постараемся найти причины, когда  связь не устанавливается?

Нужна помощь по данному вопросу. Есть скрипт с функцией CreateWindow от JSman. При запуске от имени пользователя, все работает отлично. Если же скрипт запускается с правами администратора (для работы при включенном UAC на Windows 7), то при переборе ShellWindows.Item(i).id не удается найти объект по указанному ID. Значение ShellWindows.Count при этом на 1 меньше, чем при аналогичном запуске без повышения прав. Само окно HTA формируется (видно значок на панели задач).
Подскажите, пожалуйста, чем это может быть вызвано и есть ли какие-либо идеи, как можно решить указанную проблему?

91

Re: JScript: Создание окна, а также трансляция WScript в HTA

Вот пример скрипта.

var WshShell = new ActiveXObject("WScript.Shell");
var Elevate = true;

function main(){
    var oXMLHTTP = new ActiveXObject("MSXML2.XMLHTTP");    
    innerhtml =
        "<html> " +
        "<head> " +
        "<title>Test HTA window</title> " +
        "<HTA:APPLICATION " +
        "APPLICATIONNAME='test' " +
        "VERSION='1.0' " +
        "BORDER='none' " +
        "CAPTION='yes' " +
        "INNERBORDER='no' " +
        "CONTEXTMENU='no' " +
        "SCROLL='no' " +
        "MAXIMIZEBUTTON='no' " +
        "MINIMIZEBUTTON='no' " +
        "SELECTION='no' " +
        "/> " +
        "<STYLE> " +
        "body{ " +
        "font-family:Verdana; " +
        "font-size:11px; " +
        "} " +
        "</STYLE> " +
        "</head> " +
        "<script language='javascript'> " +
        "function window.onload(){ " +
        "self.focus(); " +
        "self.resizeTo(300,80); " +
        "} " +
        "</script> " +
        "<body scroll=no bgcolor='D4D0C8' style='border:0;'> " +
        "<center> Test HTA window " +
        "<br><br> " +
        " It will be closed in 10 sec " +
        "</center> " +
        "</body> " +
        "</html> ";
    width = 300; height = 80;
    var window = createHTAWindow(innerhtml,0,0,width,height);
    window.moveTo((window.screen.width-width)/2,(window.screen.height-height)/2);
    WScript.Sleep(10000);
    window.close();
}

function createHTAWindow(content, x, y, width, height)
{
var HTASettings = "", e, window, Host = this; 
    width = Number(width) || 400;
    height = Number(height) || 300;
    try {
        HTASettings = content.match(/<hta[^>]+>/gim)[0].replace(/\r?\n/g, " ").replace(/"/g,"'");
    } catch(e) {
    }
    
    //var ID = "1"+(new Date).valueOf();
    var ID = "u"+Math.floor(Math.random()*10000000)
    var CodeForLinking = "\"<title> </title><script>moveTo(-300,-300); resizeTo(0,0)</script>" + 
        HTASettings + 
        "<object id=" + ID + 
        " classid='clsid:8856F961-340A-11D0-A96B-00C04FD705A2'><param name=RegisterAsBrowser value=1></object>\"";
    var ShellWindows = ( new ActiveXObject("Shell.Application") ).Windows();
    var NumberOfWindows = ShellWindows.Count;

    WshShell.Run("mshta.exe about:"+CodeForLinking);

WScript.Sleep(1000);
var s="ID: " + ID + "\n";
for (var i=ShellWindows.Count; --i>=0;){
    s = s + i + ": " + ShellWindows.Item(i).id + "\n";
}
WScript.Echo(s);

    outer: for (var t=0; t<500; t++)    
    inner:  for (var i=ShellWindows.Count; --i>=0;){
        try{
            if( ShellWindows.Item(i).id == ID ){
                window = ShellWindows.Item(i).parent.parentWindow;
                break outer;
            }
        } catch(e) {
            WScript.Echo(e.message);
            return false;
        }
        WScript.Sleep(10);
    }
    
    if (!window) {
        WshShell.Popup("Error", 0, "Error", 0+48);
    WScript.Quit();
        return false;
    }
    
    try {
        window.document.open(); window.Host = Host; 
        window.document.write([content||"", "<script language='JScript'>eval;resizeTo(",width,",", height,"); moveTo(", Number(x) ||  (window.screen.width - width) / 2,",", Number(y) || (window.screen.height - height) / 2, ");</script>"].join(""));
        window.document.close();
    } catch (e) {
    }
    return window;
}

if ( Elevate && WScript.Arguments.Count() == 0 ) {
    var oShell = new ActiveXObject("Shell.Application");
    oShell.ShellExecute("wscript.exe", "\"" + WScript.ScriptFullName + "\"" + " /isElevated", WScript.ScriptFullName.slice(0,-WScript.ScriptName.length-1), "runas", 1);
    WScript.Quit();
}

main();

При запуске с выключенным UAC или с UAC, но без повышения прав (во второй строке надо установить ключ Elevate = false), скрипт отрабатывает как надо. Если же скрипт повышает себе права при включенном UAC, то в списке ShellWindows не видно окна HTA.

92

Re: JScript: Создание окна, а также трансляция WScript в HTA

Если не запущен Проводник (в полном объёме, с Рабочим столом и прочим), то попытка обращения к колекции ShellWindows вызывает ошибку. Если Проводник и окно обозревателя запущены от имени разных уч.записей, то очевидно, окно не попадёт в коллекцию ShellWindows. Если процесс Проводника запущен после того, как окно уже существовало — его не будет в ShellWindows. Делайте выводы.

93

Re: JScript: Создание окна, а также трансляция WScript в HTA

wisgest, спасибо. Не подскажите, как тогда можно решить данную задачу под UAC?

94

Re: JScript: Создание окна, а также трансляция WScript в HTA

Возможное решение, требующее проработки:

HTA=WshShell.Exec('mshta.exe "javascript:var FSO=new ActiveXObject("Scripting.FileSystemObject"),StdIn=FSO.GetStandardStream(0);eval(StdIn.ReadLine());"');

(вместо eval() может быть document.write()) и взаимодействовать через стандартные потоки ввода-вывода.

95 (изменено: Aaroniero, 2012-12-29 01:09:20)

Re: JScript: Создание окна, а также трансляция WScript в HTA

wisgest, спасибо. Идея общения через файл мне не очень нравится, но если не удастся по другому, действительно, возможный вариант.
А можно как-то из HTA приложения получить доступ к родительскому объекту WebBrowser? Если да, то, как я понимаю, проблему можно будет решить при помощи метода IShellWindows::Register