1 (изменено: JSmаn, 2010-03-20 13:18:09)

Тема: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Наконец-то форум заработал, теперь могу показать, что я недавно написал. :-)

Пример оконного приложения с графическими ресурсами в одном JS-файле. Использует WinSock.

var VB = new ActiveXObject("htmlfile").parentWindow;    
VB.document.write("<script language='VBScript'>Function GetData(Obj, data, num, bytTotal)\nObj.GetData data, num, bytTotal\nGetData = data\nEnd Function</script>");
var 
    Port = parseInt(Math.random()*100000)% 20000 +9000,
    MainSocket = WScript.CreateObject("MSWinsock.Winsock.1","MainSocket_"),
    Sockets = {};
    MainSocket.LocalPort = Port;
    MainSocket.Listen();
    
Function.prototype.GetResource = function (ResourceName)
{
    if (!this.Resources) 
    {
        var UnNamedResourceIndex = 0, _this = this;
        this.Resources = {};
        function f(match, resType, Content){
            _this.Resources[(resType=="[[")?UnNamedResourceIndex++:resType.slice(1,-1)] = Content;}
        this.toString().replace(/\/\*(\[(?:[^\[]+)?\[)((?:[\r\n]|.)*?)\]\]\*\//gi, f);
    }
    return this.Resources[ResourceName];
}

function GetResource(ResourceName) {
    return arguments.callee.caller.GetResource(ResourceName)}
    
function DecodeBase64(textBase64)
{
var Element = new ActiveXObject("MSXml2.DOMDocument").createElement("tmp");
    Element.dataType = "bin.base64";
    Element.text = textBase64;
    return Element.nodeTypedValue;
}

function HTTPGetFileName(Data)
{
    var match = Data.match(/^(\w+)\s+\/([^\s]*)\s+([^\s]+)/);
    return (match && match[2])? match[2] : null;
}

var Host = this;

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

    try {HTASettings = content.match(/<hta[^>]+>/gim)[0].replace(/\r?\n/g, " ").replace(/"/g,"'")} catch (e){};
    
var 
    ID = (new Date).valueOf(),
    CodeForLinking = "\"<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;)
       if  (ShellWindows.Item(i).id == ID) 
       window = ShellWindows.Item(i).parent.parentWindow;
    
    try
    {
        window.document.open();
        window.document.write("<base href='http://localhost:"+Port+"/' >"+(content || "") + "<script language='JScript'>eval</script>");
        window.document.close();
        window.Host = Host;
        window.moveTo(Number(x) || 0, Number(y) || 0); 
        window.resizeTo(Number(width) || 400, Number(height) || 300); 
    }
    catch (e) {return}
    return window;
}

function MainSocket_ConnectionRequest(requestID)
{
    var NewSocket = WScript.CreateObject("MSWinsock.Winsock","Socket_");
    NewSocket.Accept(requestID);
    Sockets[NewSocket.SocketHandle]=NewSocket;
}

function Socket_SendComplete()
{
    delete Sockets[this.SocketHandle];
    this.Close();
    WScript.DisconnectObject(this);
}

function Socket_DataArrival(bytTotal)
{
  var Data = VB.GetData (this, Data, 8, bytTotal);
  var FileName = HTTPGetFileName(Data);

  if (Resources.GetResource(FileName))
  {
    this.SendData("HTTP/1.1 200 OK\nContent-Type: application/octet\nContent-Transfer-Encoding: binary\nContent-Disposition: inline\n\n");
    this.SendData(DecodeBase64(Resources.GetResource(FileName)));
  }
  else this.SendData("HTTP/1.1 404 Not Found");
}
//——————————————————————————————————————————
function Resources()
{
/*[pic[iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAMAAAAMCGV4AAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADYUExURWJiYv7xQ0ZGRioqKiQaAP/te//gAPeiAP7uZP7lAP/YAPz8Ef/UAP31Kv+zAP7qADcuFf+6APOgAP3yAP/dAP33AP/MAP/VZemdAP3yAf+sAP/eQsaHAP7sEf30Ef/gY//DIP/VVtaeLkM9If7MYv31Jv/jVv/AEf7tKt6jMeCpAOXNJ/GfAP/BAPz5AOfQOf7jGfikAP/dAf/he/33Af7kEf/FKv/aEf/IRv/FPv7lAv7xYv/WCv/jDvixKuSkGfW5Rf7qAuOgDvmqEf/cKuKbAAAAAP///7GsR/gAAABIdFJOU///////////////////////////////////////////////////////////////////////////////////////////////AJzs8mAAAACwSURBVHjaVM9FFsMwDARQBxpmhqbMzMytlfvfqHbSTedpob/SCOU0QFNsiKqd9urNowWlYS5VSNbhEKhhLJ0RkhAKOy0gthiGYVky6eFh5QgWA13nODKf3e0OCK5ZTVXVWrbd998vYsHs+jPfNQWtIWJiT4aN65qyd4EJtSLIEMfP0wqSiDjnFU8o+hkO5un9UaApWjA1RFyFoh+2bdtIHMqyP78UnQjzv/5//30FGACrUSaRymhFqgAAAABJRU5ErkJggg==]]*/

/*[HTML[
<html><title>Гипертекстовое приложение</title><body>Привет от JSman! <img src='pic' /></body></html>
]]*/
}

var window = CreateWindow(Resources.GetResource("HTML"), 200, 200, 350, 100);

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

Полное описание работы частей скрипта можно найти в темах:
JScript: Создание окна, а также трансляция WScript в HTA
JS: Хранение ресурсов в файле JS.
VBScript: Обмен данными между процессами через сокеты.

Все, что написано выше разделителя в коде,

//——————————————————————————————————————————

является «модулем», то есть подлежит copy-paste.

Остальная часть (которая ниже разделителя) — это основной код.

function Resources()
{
/*[pic[base64рисунка]]*/

/*[HTML[
HTML код окна
]]*/
}

var window = CreateWindow(Resources.GetResource("HTML"), 200, 200, 350, 100);

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

Ресурсы лежат в контейнере Resources.

2

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Пробовал запускать, выходит ошибка в 5й строке 5й символ:
' Не удается создать объект с именем "MSWinsock.Winsock.1" '

Стремление - залог успеха

3

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Было бы неплохо указать какие дополнительные компоненты и в какой последовательности необходимо устанавливать для полноценной работы.

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

4

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Если

' Не удается создать объект с именем "MSWinsock.Winsock.1" '

, то нужно установить MsWinsock.ocx.

Принцип работы скрипта:
1. Описываем в файле ресурсы. Абсолютно не важен способ хранения. Нужно просто иметь механизм получения как текстового так и бинарного контента.
2. Создаем и запускаем мультисокетный веб-сервер со случайным портом, который сможет обращаться к этим ресурсам (читать их и отправлять клиенту, например прямо в тег img).
3. Создаем окно. К коду автоматически присоединяется строка <base href=…>? которая указывает на то, что окно должно обращаться к нашему серверу для получения требуемого контента.

Допустим, что наш сервер слушает 127.0.0.1:8888. HTA включает в себя элемент base href. Теперь все вызовы по относительным ссылкам, указанных в коде страницы, будут обращаться к серверу. Например, img src="123.jpg" обратится к адресу 127.0.0.1:8888/123.jpg. После того как клиент получит ответ от сервера, картинка отобразится в нужном месте.

Rumata пишет:

Было бы неплохо указать какие дополнительные компоненты и в какой последовательности необходимо устанавливать для полноценной работы.

Последовательность подключения компонентов не имеет значения.

Итак, первый компонент — Хранение ресурсов.

Function.prototype.GetResource = function (ResourceName)
{
    if (!this.Resources) 
    {
        var UnNamedResourceIndex = 0, _this = this;
        this.Resources = {};
        function f(match, resType, Content){
            _this.Resources[(resType=="[[")?UnNamedResourceIndex++:resType.slice(1,-1)] = Content;}
        this.toString().replace(/\/\*(\[(?:[^\[]+)?\[)((?:[\r\n]|.)*?)\]\]\*\//gi, f);
    }
    return this.Resources[ResourceName];
}

function GetResource(ResourceName) {
    return arguments.callee.caller.GetResource(ResourceName)}

Второй компонент — функция создания окон HTA

var Host = this;

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

    try {HTASettings = content.match(/<hta[^>]+>/gim)[0].replace(/\r?\n/g, " ").replace(/"/g,"'")} catch (e){};
    
var 
    ID = (new Date).valueOf(),
    CodeForLinking = "\"<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;)
       if  (ShellWindows.Item(i).id == ID) 
       window = ShellWindows.Item(i).parent.parentWindow;
    
    try
    {
        window.document.open();
        window.document.write("<base href='http://localhost:"+Port+"/' >"+(content || "") + "<script language='JScript'>eval</script>");
        window.document.close();
        window.Host = Host;
        window.moveTo(Number(x) || 0, Number(y) || 0); 
        window.resizeTo(Number(width) || 400, Number(height) || 300); 
    }
    catch (e) {return}
    return window;
}

Третий компонент — это веб-сервер, который обеспечит нам доступ к ресурсам при необходимости:

function DecodeBase64(textBase64)
{
var Element = new ActiveXObject("MSXml2.DOMDocument").createElement("tmp");
    Element.dataType = "bin.base64";
    Element.text = textBase64;
    return Element.nodeTypedValue;
}

function HTTPGetFileName(Data)
{
    var match = Data.match(/^(\w+)\s+\/([^\s]*)\s+([^\s]+)/);
    return (match && match[2])? match[2] : null;
}

var VB = new ActiveXObject("htmlfile").parentWindow;    
VB.document.write("<script language='VBScript'>Function GetData(Obj, data, num, bytTotal)\nObj.GetData data, num, bytTotal\nGetData = data\nEnd Function</script>");
var 
    Port = parseInt(Math.random()*100000)% 20000 +9000,
    MainSocket = WScript.CreateObject("MSWinsock.Winsock.1","MainSocket_"),
    Sockets = {};
    MainSocket.LocalPort = Port;
    MainSocket.Listen();

function MainSocket_ConnectionRequest(requestID)
{
    var NewSocket = WScript.CreateObject("MSWinsock.Winsock","Socket_");
    NewSocket.Accept(requestID);
    Sockets[NewSocket.SocketHandle]=NewSocket;
}

function Socket_SendComplete()
{
    delete Sockets[this.SocketHandle];
    this.Close();
    WScript.DisconnectObject(this);
}

function Socket_DataArrival(bytTotal)
{
  var Data = VB.GetData (this, Data, 8, bytTotal);
  var FileName = HTTPGetFileName(Data);

  if (Resources.GetResource(FileName))
  {
    this.SendData("HTTP/1.1 200 OK\nContent-Type: application/octet\nContent-Transfer-Encoding: binary\nContent-Disposition: inline\n\n");
    this.SendData(DecodeBase64(Resources.GetResource(FileName)));
  }
  else this.SendData("HTTP/1.1 404 Not Found");
}

Стоит обратить внимание на function Socket_DataArrival. Она отвечает за то, как веб-сервер будет обрабатывать запрос клиента ( HTTPGetFileName(Data) ). Данная реализация требует наличия контейнера ресурсов Resources. Таким образом, если вы будете использовать другой способ хранения ресурсов (например, WSF-использовать), то имейте это в виду.

5

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Lucky пишет:

Пробовал запускать, выходит ошибка в 5й строке 5й символ:
' Не удается создать объект с именем "MSWinsock.Winsock.1" '

У меня вот что выдает:

---------------------------
Windows Script Host
---------------------------
Сценарий: c:\tmp\test.js
Строка: 5
Символ: 5
Ошибка: Не удается найти класс программируемых объектов с именем "MSWinsock.Winsock.1".
Код: 80020009
Источник: WScript.CreateObject

---------------------------
ОК   
---------------------------

6

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Так и должно быть, если WinSock не стоит.

7

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

JSman пишет:

Так и должно быть, если WinSock не стоит.

Расскажите пожалуйста, что это за WinSock загадочный такой и где его взять?

8 (изменено: JSmаn, 2010-03-26 14:10:16)

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

mswinsck.ocx — это winsock control module, преимущественно используемый в приложениях написанных на VB, предоставляет возможности программирования сокетов. Обычно входит в поставку VB6.

Взять его можно тут, например. Должен быть зарегистрирован в системе через resvr32. Указанный элемент требует наличие лицензии на использование его в своих разработках.

Если приложение не работает из-за отсутствия лицензии, то вам поможет запрос в гугле.

Если все получилось, то дайте знать

9 (изменено: -red-, 2010-03-24 10:43:30)

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Т.к. mswinsck.ocx уже был скачан и зарегистрирован то я сразу попробовал это

JSman пишет:

http://www.sql.ru/forum/actualfile.aspx?id=2559830

(полный URL т.к. хотлинкинг запрещен на sql.ru)
Заработало! Спасибо!

10

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

JSman пишет:

<удалено>

Господа, это варез. Прошу автора подкорректировать пост.

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

11

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

The gray Cardinal пишет:

Господа, это варез. Прошу автора подкорректировать пост.

Не варез. Прошу обратить внимание на Method 2: Add the licensing keys to the registry

12

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

JSman пишет:
The gray Cardinal пишет:

Господа, это варез. Прошу автора подкорректировать пост.

Не варез. Прошу обратить внимание на Method 2: Add the licensing keys to the registry

Бегло просмотрел, но не понял до конца. Эта штука регистрируется с помощью инсталляционного диска Visual Studio .NET, который бесплатен?

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

13

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Да. VB6Controls.reg свободно распространяется.

14

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

JSman пишет:

VB6Controls.reg свободно распространяется.

С чего Вы это решили?

15

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Этот файл является частью из нескольких бесплатных версий Visual Studio. Перечень всех версий (где имеется этот файл) приведен в странице по указанной ссылке. Часть из них бесплатно распространяются (например, релизы для студентов). У меня нет возможности провести полный анализ американского законодательства в области авторского права и лицензионных соглашений относительно небольшого файлика и дать развернутую юридическую оценку по его использованию. Если считаете, что это нарушает авторские права Микрософта, то удалите то, что по Вашему мнению вредно.

16

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

JSman, бесплатно доступны версии «Express», которые отсутствуют в перечислении на указанной странице. Иногда, действительно, бывают промо-акции, по которым можно некоторым категориям граждан, соблюдая лицензионное соглашение, загрузить и пользоваться некоторым набором профессиональных продуктов (например, Microsoft DreamSpark - бесплатное программное обеспечение для студентов и аспирантов). Однако, в рамках лицензионного соглашения (как Express, так и разных версий Professional) содержится прямой запрет на распространение как в целом, так и отдельных частей продукта. Допустимые части продукта для повторного распространения перечислены в файле «redist.txt» Visual Studio; «VB6Controls.reg» там не указан. Так что, мы можем поступить двояко: указать, где можно получить этот файл (если, допустим, этот файл есть и в Express-версиях — я не проверял по причине отсутствия), либо сделать такой финт ушами (см. в постскриптум). Что скажете?

17

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

alexii пишет:

Так что, мы можем поступить двояко: указать, где можно получить этот файл (если, допустим, этот файл есть и в Express-версиях — я не проверял по причине отсутствия), либо сделать такой финт ушами (см. в постскриптум). Что скажете?

Имхо, подходят оба варианта (можно одновременно).

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

18

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Кстати, если в поисковике введете "mlrljgrlhltlngjlthrligklpkrhllglqlrk", то увидите, что этот ключ выставлен на всеобщее обозрение в инете и даже на сайте MS. Вот одна их ссылок: http://social.msdn.microsoft.com/forums … fc0e9a9b5e.

19

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

JSman, дык, я не спорю с этим. Но… неважно, где и у кого выставлено на всеобщее обозрение. Главное — чтобы здесь было чисто. Понимаете, о чём я?

20

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

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

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

21 (изменено: JSmаn, 2010-03-26 13:58:45)

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Лучше, конечно, перестраховаться. Сейчас поправлю посты. Только что прочитал новость Защитники авторских прав требуют с ветеранов деньги за исполнение военных песен. После такого — «ну их на фиг».

22

Re: JScript: Оконное приложение с графическими ресурсами в одном JS-файле.

Хорошая статья для этой темы: OFF: Как вы относитесь к "лицензионному" и "пиратскому" ПО?