101

Re: WSH: обсуждаем DynamicWrapperX от YMP

А так, без скобок?

Option Explicit

Dim objMyServer
Dim CardCount

Set objMyServer = CreateObject("wmCOM.Automate")

CardCount = 123
objMyServer.GetScanCardCount CardCount

WScript.Echo "[" & CardCount & "]"

Set objMyServer = Nothing

WScript.Quit 0

102

Re: WSH: обсуждаем DynamicWrapperX от YMP

cadavr, попробуйте несколько модифицированный №6.

103

Re: WSH: обсуждаем DynamicWrapperX от YMP

alexii пишет:

А так, без скобок?

Option Explicit

Dim objMyServer
Dim CardCount

Set objMyServer = CreateObject("wmCOM.Automate")

CardCount = 123
objMyServer.GetScanCardCount CardCount

WScript.Echo "[" & CardCount & "]"

Set objMyServer = Nothing

WScript.Quit 0

Ошибка:
---------------------------
Windows Script Host
---------------------------
Script: D:\Work\Lawhinie\Projects\vbServers\test2.vbs
Line: 9
Char: 1
Error: Type mismatch: 'GetScanCardCount'
Code: 800A000D
Source: Microsoft VBScript runtime error

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

104

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP пишет:

cadavr, попробуйте несколько модифицированный №6.

---------------------------
MethodCall
---------------------------
VT_I4: ошибка: 0, число до: 123, число после: 123

VT_BYREF | VT_I4 (value): ошибка: 0, число до: 123, число после: 0      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

VT_BYREF | VT_I4 (variant): ошибка: 0, число до: 123, число после: 123

VT_INT: ошибка: 0, число до: 123, число после: 123

VT_BYREF | VT_INT (value): ошибка: 80020005, число до: 123, число после: 123

VT_BYREF | VT_INT (variant): ошибка: 80020005, число до: 123, число после: 123

VT_PTR: ошибка: 80020008, число до: 123, число после: 123

VT_BYREF | VT_PTR (value): ошибка: 80020008, число до: 123, число после: 123

VT_BYREF | VT_PTR (variant): ошибка: 80020008, число до: 123, число после: 123

VT_INT_PTR: ошибка: 80020008, число до: 123, число после: 123

VT_BYREF | VT_INT_PTR (value): ошибка: 80020005, число до: 123, число после: 123

VT_BYREF | VT_INT_PTR (variant): ошибка: 80020005, число до: 123, число после: 123

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

Вот ОН!!!!
- Похоже что этот вариант верен - VT_BYREF | VT_I4 (value): ошибка: 0, число до: 123, число после: 0
Он выдает 0 так и должен, (раньне должен выдавать был 1, сейчас 0, потому что я отключил карту управления), а то очень долго идет запуск и гонять лишний раз лазерную установку непозволительно...  Если есть возможность реализовать MethodCall с передачей параметра таким образом, то может что-то и получится
Проверил на процедуре вызова количества объектов в файле - 100% работает!!! - именно этим способом передавать значение надо:
Выдало 21 - количество объектов
Осталось реализовать сам MethodCall, и можно пробовать.
Только остается открытым вопрос, а как в том случае если несколько параметров???
И еще - пока 1С аварийно вылетает, после каждого MethodCall... надеюсь это устранится?

105

Re: WSH: обсуждаем DynamicWrapperX от YMP

cadavr пишет:

Только остается открытым вопрос, а как в том случае если несколько параметров???

Да, меня это тоже занимает. Хотелось бы сделать что-то более универсальное, а не для одного конкретного параметра одного конкретного метода. Т.е. чтобы пользователь мог как-то указывать, каким типом передавать каждый из параметров. Вроде того, как это сделано для функций из DLL. Но тут дело посложнее с типами.

И еще - пока 1С аварийно вылетает, после каждого MethodCall... надеюсь это устранится?

Возможно, из-за возвращаемого значения, там просто мусор возвращался.

Пока мысль такая, что возвращать MethodCall должен то, что возвращает транслируемый метод. А изменённые параметры получать потом по запросу. Что-то вроде:

Ret = DX.MethodCall(object, "method", prm1, prm2, prm3)

prm1 = DX.MethodCall(1)
prm2 = DX.MethodCall(2)

Но как типы указывать, пока не ясно. И откуда их узнавать, тоже непонятно.

Пока что я исправил возвращаемое значение - через него возвращается изменённое число. Проверьте, не будет ли теперь вылетов - №7.

106

Re: WSH: обсуждаем DynamicWrapperX от YMP

Пока что я исправил возвращаемое значение - через него возвращается изменённое число. Проверьте, не будет ли теперь вылетов - №7.

№7 работает ОТЛИЧНО !!! и так как надо - пока вылетов нет - возвращаемые значения правильные!

Вот что я хочу предложить насчет параметров и их типов, чтоб было удобно:
Сделать так чтоб для передачи в метод СОМ-сервера передавался указатель на структуру (строку), поскольку типы мы уже знаем и определились с ними, какие типы нужны то сделать еще и указатель на структуру (строку) типов и тоже передавать туда. А возвращать уже известным методом поскольку StrPtr() работет.
Схематично это так: для примера когда есть 4 параметра:

ParamNum = 4;
Params = "123;456;Строчечка;555";
ParamsTypes = "VT_I4;VT_I4;VT_BSTR;VT_I4";
AdrParams = StrPtr(Params);
MethodCall (object, "method", ParamNum, Params, ParamsTypes);
ReturnString = StrGet(AdrParams);

Внутри MethodCall происходит преобразование к нужному типу. Числа к типу VT_BYREF | VT_I4 (value), который теперь работает.
Внутри после выполнения метода СОМ-сервера преобразовывать полученные данные обратно в строку лепить вместе, разделяя точкой с запятой, и ложить на то же место.
После вызова метода все данные будут находиться в той же самой строке.
И все... Передаем строку параметров и строку-описание передаваемых параметров, и соответственно после вызова оттуда же их и забираем по адресам, которые мы запомнили с помощью StrGet().

Это просто предложение - но оно реально должно работать.

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

ParamNum = 4;
Params = "123;456;Строчечка;555";
ParamsTypes = "VT_I4;VT_I4;VT_BSTR;VT_I4";
ReturnString = MethodCall (object, "method", ParamNum, Params, ParamsTypes);

Так проще... остается реализовать внутри MethodCall нужные преобразования.

107

Re: WSH: обсуждаем DynamicWrapperX от YMP

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

Я всё-таки склоняюсь к своему варианту. Типы можно в виде строки передавать, но для параметров, по-моему, это явно лишнее.

Для типов можно те же буквы использовать. Например "l" = "VT_I4", целое передаётся по значению, входной параметр, а "L" = "VT_BYREF | VT_I4", целое передаётся по ссылке, выходной параметр. Тогда получится, например, так:

DX.MethodCall(object, "method", 55, 123, "Hello", 1000, "i=lLwl", "r=l");
// Второе число - выходной параметр, поэтому передаётся по ссылке.

Res = DX.MethodCall(2); // Получаем изменённое число.

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

108

Re: WSH: обсуждаем DynamicWrapperX от YMP

Для типов можно те же буквы использовать. Например "l" = "VT_I4", целое передаётся по значению, входной параметр, а "L" = "VT_BYREF | VT_I4", целое передаётся по ссылке, выходной параметр.

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

DX.MethodCall(object, "method", 55, 123, "Hello", 1000, "i=lLwl", "r=l");
// Второе число - выходной параметр, поэтому передаётся по ссылке.

а что тогда означает "r=l"?

Res = DX.MethodCall(2); // Получаем изменённое число.

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

Мне остается дождаться релиза №8 - теперь я надеюсь результат уже верный будет. Спасибо за старания.

109

Re: WSH: обсуждаем DynamicWrapperX от YMP

"r=l" - это тип возвращаемого значения. В общем, быстро не обещаю, возни тут явно не на пару дней, но сделаю.

110

Re: WSH: обсуждаем DynamicWrapperX от YMP

Я полазил в нете нашел каким образом просто подключать СОМ-сервер в делфи (на примере MS Word) с помощью этого принципа подключил мой СОМ-сервер и все это обернул в делфовский DLL, который тоже по выкачаному примеру сделал ОЛЕ - сервером - и внутри могу делать свои действия. Сделал там процедурку MethodCall, b GetResult - по анологии с тем что мы обсуждали - так работает... Раньше я не знал как подключить этот СОМ - сервер без использования форм в приложении - а теперь все вроде решилось... и работает, осталось немного оформить - перечислить все функции и процедуры СОМ-сервера в делфийском сервере, чтоб не заморачиваться в 1С с количеством параметров и их типом.
Вызывать в 1С буду так:

vk = СоздатьОбъект("AddIn.wmCOMOle");
vk.MethodCall ("method", Parameter1, Parameter2 ... );
ReturnString = vk.GetResult(1);
ReturnInteger = vk.GetResult(2);

111

Re: WSH: обсуждаем DynamicWrapperX от YMP

Если реализуете DynwrapX то буду использовать его, а пока мне нужно отчитаться хотя бы по тому, что я уже сделал... просто ждут результатов. Пока буду использовать свой сервер.

112

Re: WSH: обсуждаем DynamicWrapperX от YMP

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

113 (изменено: blindvic, 2009-10-02 23:05:50)

Re: WSH: обсуждаем DynamicWrapperX от YMP

Пример из документации:

DX = new ActiveXObject("DynamicWrapperX");
str = "Hello, world! Это я.";

// Чтение из памяти. Читаются коды символов строки.

codes = "";

for(i=0; i < str.length; ++i)
  codes += DX.NumGet(str, i*2, "t") + " "; // i умножается на 2, т.к. смещение должно
                                           // быть в байтах, а тип "t" - двухбайтный.

Не могу понять:

code = DX.NumGet(str, i*2, "t");     // Читаем слева направо (смещение растёт).

первым параметром передается переменная str, a

str = "Hello, world! Это я.";

но документация говорит

NumGet( Address [, Offset] [, Type] ) - чтение числа из памяти. Address - базовый адрес. Offset - смещение от него (в байтах), положительное или отрицательное...

по идее первым параметром надо передавать не строковую переменную, а указатель на нее. Или, наверное, JavaScript в случае строковой пременной передает указатель на нее?

Как бы то ни было - у меня какие-то глюки:
http://www.1cpp.ru/forum/YaBB.pl?num=1247208308/0
1С вылетает регулярно

114 (изменено: blindvic, 2009-10-02 23:01:48)

Re: WSH: обсуждаем DynamicWrapperX от YMP

DX.MethodCall(object, "method", 55, 123, "Hello", 1000, "i=lLwl", "r=l");
// Второе число - выходной параметр, поэтому передаётся по ссылке.

Res = DX.MethodCall(2); // Получаем изменённое число.

Вы тут что-то внедряли новое, но в документации этого нет (http://www.script-coding.com/dynwrapx.html). Да и не понял я до конца.

115

Re: WSH: обсуждаем DynamicWrapperX от YMP

Значением строковой переменной является указатель на строку, он и передаётся. Почему падает 1С, мне трудно судить, сам я дела с ней не имел. Но судя по разъяснениям cadavr'a выше в этой теме, она как-то прикольно работает с переменными. Я dynwrapx тестил только под JScript и VBScript.

А где она конкретно падает, в какой момент, при какой операции?

blindvic пишет:

Вы тут что-то внедряли новое, но в документации этого нет (http://www.script-coding.com/dynwrapx.html). Да и не понял я до конца.

Это пока осталось нереализованным.

116

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP пишет:

А где она конкретно падает, в какой момент, при какой операции?

Функция Запросить ( WTSInfoClass )

     lRet = DX.WTSQuerySessionInformationA ( 0, -1, WTSInfoClass, ppBuffer, pBytesReturned );
     Если lRet = 1 Тогда
           pBuffer = DX.NumGet ( ppBuffer, 0, "u" );
           BytesReturned = DX.NumGet ( pBytesReturned, 0, "u" );

     КонецЕсли;
     Возврат lRet;

КонецФункции

Функция ПолучитьСостояниеСессии () // текущей сессии терминального сервера
     lRet = Запросить ( 8 ); // WTSConnectState
     Если lRet <> 0 Тогда
           Session_Connection_State = DX.NumGet ( pBuffer, 0, "l" ); // Pointer to an INT variable that contains a value from the WTS_CONNECTSTATE_CLASS enumeration type to indicate the session's current connection state.
           DX.WTSFreeMemory ( ppBuffer );
     Иначе
           Session_Connection_State = -1;
     КонецЕсли;
     Возврат Session_Connection_State;
КонецФункции

           DX = СоздатьОбъект ( "DynamicWrapperX" ); // regsvr32 -i /s dynwrapx.dll // http://www.script-coding.com/dynwrapx.html
           // Регистрация функции из dll
           DX.Register ( "wtsapi32.dll", "WTSQuerySessionInformationA", "i=lllll", "r=l" ); // http://msdn.microsoft.com/en-us/library/aa383838(VS.85).aspx
           DX.Register ( "wtsapi32.dll", "WTSFreeMemory", "i=u" ); // http://msdn.microsoft.com/en-us/library/aa383834(VS.85).aspx

           ppBuffer = DX.StrPtr ( DX.Space ( 16) ); // Pointer to a variable that receives a pointer to the requested information. The format and contents of the data depend on the information class specified in the WTSInfoClass parameter. To free the returned buffer, call the WTSFreeMemory function.
           pBytesReturned = DX.StrPtr ( DX.Space ( 4) ); // Pointer to a variable that receives the size, in bytes, of the data returned in ppBuffer.

ПолучитьСостояниеСессии ()

Методом тыка выяснил, что проблема в строках, выделенных жирным шрифтом.

И еще, по ходу дела, один вопрос:

Функция ПолучитьСостояниеСессии () // текущей сессии терминального сервера
     lRet = Запросить ( 8 ); // WTSConnectState
     Если lRet <> 0 Тогда
           Session_Connection_State = DX.NumGet ( pBuffer, 0, "l" ); // Pointer to an INT variable that contains a value from the WTS_CONNECTSTATE_CLASS enumeration type to indicate the session's current connection state.
           DX.WTSFreeMemory ( ppBuffer );
     Иначе
           Session_Connection_State = -1;
     КонецЕсли;
     Возврат Session_Connection_State;
КонецФункции

Во всех примерах, что я нашел в интернете, так и делается: DX.WTSFreeMemory ( ppBuffer )
Но мне кажется, что должно быть: DX.WTSFreeMemory ( pBuffer )
Документация MSDN говорит:

void WTSFreeMemory(
  __in  PVOID pMemory
);

pMemory [in]

    Pointer to the memory to free.

Но ppBuffer - указатель на область памяти, в которую функция WTSQuerySessionInformationA возвращает указатель на выделенную функцией память (т.е. указатель на указатель), в к-й находится результат запроса (http://msdn.microsoft.com/en-us/library/aa383838%28VS.85%29.aspx):

ppBuffer [out]
    A pointer to a variable that receives a pointer to the requested information. The format and contents of the data depend on the information class specified in the WTSInfoClass parameter. To free the returned buffer, call the WTSFreeMemory function.

Все вроде бы работает, но почему так?

117

Re: WSH: обсуждаем DynamicWrapperX от YMP

blindvic пишет:

Методом тыка выяснил, что проблема в строках, выделенных жирным шрифтом.

В обеих? Если падает на первой, то до второй дело не доходит и она ни при чём. Если падает на второй, то первая ни при чём, раз на ней не падает.

ppBuffer = DX.StrPtr ( DX.Space ( 16) );

Поскольку результат DX.Space не помещается в переменную, то возникает вопрос, не освобождает ли 1С эту память сразу же после вызова DX.StrPtr? Если да, то последующее обращение к этой памяти, наверное, может вызвать проблемы. А если через GlobalAlloc выделить память, тоже падает?

blindvic пишет:

Но мне кажется, что должно быть: DX.WTSFreeMemory ( pBuffer )

Я тоже думаю, что должно быть так.

118

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP пишет:

А если через GlobalAlloc выделить память, тоже падает?

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

119

Re: WSH: обсуждаем DynamicWrapperX от YMP

День добрый!
А реально ли сделать так - заменить процедуру главного окна скриптовой (это можно), а после обработки некоторого сообщения вернуть управление в главную процедуру?

120

Re: WSH: обсуждаем DynamicWrapperX от YMP

Доброго времени суток. Обращаюсь за помощью к YMP.

Мне очень понравился DynamicWrapperX, большое вам спасибо за реализацию.
Я хочу использовать его для вызова методов/функций SQLite.

Основной вопрос который меня интересует - передача аргументов и возвращаемое методом/функцией значение. Полагаю, что со строками (в юникодовой версии конечно) никаких проблем быть не должно. Но вот с числами получается следующая загвоздка. Если я правильно понял, SQLite хранит знаковые 64-битные числа. Поле ROWID (если я ничего не напутал) беззнаковое 64-битное целое. Конечно возможно читать/писать 32-битные, но это всё же ограничение.

И суть вопроса: добавьте, пожалуйста, в DynamicWrapperX возможность передавать/принимать 64-битные числа. (это вообще возможно?)
Позвольте, я ещё губу раскатаю и попрошу добавить конвертацию uft8 <-> 2-byte unicode (аналогично s и z).

P.S.: По большому счёту это "спортивый" интерес. Потому что, например, тот же LiteX успешно работает с числами длиной более 32-бита и в utf8-версии конвертирует строки. (Мой рекорд 49 бит, но это похоже ограничение jscript на котором я пищу, либо я чего-то глубоко в этой жизни не понимаю :-)



"Переходи на темную сторону юный падаван - у нас есть ПЕЧЕНЬКИ!" (с) Дядька с Ведром ;-)

121

Re: WSH: обсуждаем DynamicWrapperX от YMP

max7
Я уже думал о 64 битах, но вопрос в том, в каком виде их подавать из скрипта на вход DynWrapX и в какой тип возвращать на выходе. Дробное число двойной точности (тип Double) покрывает большой диапазон, но у него не хватит точности для передачи всех возможных значений 64-битного целого. Большой диапазон оно охватывает за счёт экспоненты, а мантисса имеет только 53 бита. Можно, конечно, сделать передачу числа в виде строки, а внутри DynWrapX преобразовывать, но как-то это мне показалось слегка коряво. Тот же вопрос и относительно возврата 64 бит из функции — в какой скриптовый тип его поместить? Тоже в строковый вид? Если есть идеи, давайте.

В принципе и сейчас можно передавать 64-битное целое — в виде двух 32-битных. Т.е. разбить один 64-битный параметр на два 32-битных. Дело в том, что все аргументы перед вызовом функции кладутся в стек в виде 32-битных кусков, так что 64-битное целое всё равно так и передаётся — в виде двух 32-битных порций.

Т.е. если имеем функцию наподобие такой:

int64 SomeFunction( int64 Value );

то её можно зарегистрировать так:

DX.Register("SomeDll", "SomeFunction", "i=ul", "r=l");

и потом вызывать так:

ret = DX.SomeFunction(ValueLow, ValueHigh);

Здесь сначала передаются младшие 4 байта 64-битного целого, а потом старшие. К примеру, 0x1234567890ABCDEF делится на ValueLow = 0x90ABCDEF и ValueHigh = 0x12345678. Для беззнакового целого уже не одну, а обе половины регистрировать как беззнаковые: "i=uu".

Что касается возврата, то в примере выше в ret окажется младшая половина возвращаемого функцией 64-битного числа. Так что если значение числа заведомо не выходит за пределы 32-битного, то сойдёт. Ну а если может выходить, то увы...

Преобразование из/в UTF-8 сделать не проблема, но сначала мне надо бы разобраться с одним косяком, который обнаружился при работе со строками под Win7. Например, код из справки, перечисляющий окна, корректно не отрабатывает, причём как раз вариант на JScript. Какой-то сбой при работе с выходной строкой. Нужно выяснить, в чём там дело и какие могут быть от сего последствия.

122

Re: WSH: обсуждаем DynamicWrapperX от YMP

ret = DX.SomeFunction(ValueLow, ValueHigh);

Поддерживаю. Сам вчера этот вариант хотел предложить.

123

Re: WSH: обсуждаем DynamicWrapperX от YMP

Т.е. можно надеяться?!

Тот же вопрос и относительно возврата 64 бит из функции — в какой скриптовый тип его поместить

Ну я ничего кроме этого http://msdn.microsoft.com/en-us/library/ms221627.aspx и этого http://msdn.microsoft.com/en-us/library/ms221061.aspx не знаю.

Вот подсмотрел в исходниках LiteX'а. Там идёт так:

...

  typedef long long int sqlite_int64;
  typedef unsigned long long int sqlite_uint64;

...

  sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);

...

  STDMETHODIMP CLiteConnection::get_LastInsertRowid( VARIANT *pVal )  // видно в скрипте как свойство LastInsertRowid
  {
    if ( m_db == NULL )
    {
        return litex_error( E_DB_IS_NOT_OPEN );
    }

    CComVariant v;

    HRESULT hr = make_integer_or_decimal( v, sqlite3_last_insert_rowid( m_db ) ); // получили 64-битное значение

    if ( FAILED(hr) )
    {
        return litex_error( hr );
    }

    return v.Detach( pVal );  // "копируем" из v в pVal; pVal - указатель на внутренний VARIANT, в моем случае, движка jscript
  }

...

HRESULT make_integer_or_decimal( CComVariant& v, LONGLONG n )
{
    if (( n >= -2147483648i64 ) && ( n <= 2147483647i64 ))
    {
        v = (LONG)n;
    }
        #if _MSC_VER > 1300    
    else if ( (n >= 0i64) && (n <= 0xffffffffi64) )
    {
        v = (ULONG)n;
    }
        #endif    
    else
    {
        v = 0;
        v.ChangeType( VT_DECIMAL );
        DECIMAL& dm = v.decVal;
        
        if ( n >= 0 ) // пишем в структуру VARIANT в структуру DECIMAL 64-битное значение
        {
            dm.sign = 0;
            dm.Lo64 = (ULONGLONG)n;
        }
        else
        {
            dm.sign = DECIMAL_NEG;
            dm.Lo64 = (ULONGLONG)(-n);
        }
        //v.ChangeType( VT_DECIMAL );
    }
    
    return S_OK;
}
...

124

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP пишет:

Например, код из справки, перечисляющий окна, корректно не отрабатывает, причём как раз вариант на JScript. Какой-то сбой при работе с выходной строкой. Нужно выяснить, в чём там дело и какие могут быть от сего последствия.

Вот этот?

DX = new ActiveXObject("DynamicWrapperX");

DX.Register("user32", "EnumWindows",    "i=pl");
DX.Register("user32", "GetWindowTextW", "i=hWl");          // Вариант Unicode.
// DX.Register("user32", "GetWindowText", "i=hSl");        // Вариант ANSI.

pCbkFunc = DX.RegisterCallback(CbkEnumWin, "i=hl", "r=l"); // Регистрация CbkEnumWin
                                                           // как функции обратного
                                                           // вызова и получение
                                                           // указателя.
n=0, m=0, WinList="";

Title = DX.Space(256);              // Буфер под заголовок окна (выходная строка).

DX.EnumWindows(pCbkFunc, 0);        // Вызов EnumWindows с передачей ей указателя на
                                    // callback-функцию.

WScript.Echo("Всего окон: " + m + "\nС заголовками: " + n + "\n\n" + WinList);


// ............... Собственно callback-функция ....................

function CbkEnumWin(hwnd, lparam)
{
  DX.GetWindowTextW(hwnd, Title, 256);
  // DX.GetWindowText(hwnd, Title, 256);  // Вариант ANSI.
  if(Title.length > 0) {  // Если длина заголовка больше 0, заносим в список.
    WinList += hwnd + "\t" + Title + "\n";
    ++n;
  }
  ++m;
  return 1;              // Если вернуть 0, вызовы прекратятся.
}

А такой вариант работает, проверьте, пожалуйста.

var DX = new ActiveXObject("DynamicWrapperX");

DX.Register("user32", "EnumWindows",    "i=pl");
DX.Register("user32", "GetWindowTextW", "i=hWl");          // Вариант Unicode.
DX.Register("user32.dll", "GetWindowTextLength", "i=h", "r=l");

var pCbkFunc = DX.RegisterCallback(CbkEnumWin, "i=hl", "r=l"); // Регистрация CbkEnumWin
                                                           // как функции обратного
                                                           // вызова и получение
                                                           // указателя.
var n=0, m=0, WinList="";

//### Title = DX.Space(256);              // Буфер под заголовок окна (выходная строка).

function getTitle(hWnd)
{
   var chars_count = DX.GetWindowTextLength(hWnd);
   if(chars_count > 0)
   {
      var buffer = DX.Space(chars_count+1,"_"); // ###  
      chars_count = DX.GetWindowTextW(hWnd,buffer,chars_count+1);
      return ""+buffer.substr(0,chars_count);
   }
   return "";
};

DX.EnumWindows(pCbkFunc, 0);        // Вызов EnumWindows с передачей ей указателя на
                                    // callback-функцию.

WScript.Echo("Всего окон: " + m + "\nС заголовками: " + n + "\n\n" + WinList);


// ............... Собственно callback-функция ....................

function CbkEnumWin(hwnd, lparam)
{
  //### DX.GetWindowTextW(hwnd, Title, 256);
  var Title = getTitle(hwnd);
  if(Title.length > 0) {  // Если длина заголовка больше 0, заносим в список.
    WinList += hwnd + "\t" + Title + "\n";
    ++n;
  }
  ++m;
  return 1;              // Если вернуть 0, вызовы прекратятся.
}

125

Re: WSH: обсуждаем DynamicWrapperX от YMP

max7
Спасибо за наводку на DECIMAL. Я попробовал его возвращать из объекта, JScript не ругается. Но ведь этот формат для него хотя и знакомый, но неродной, он его преобразует опять же в Double, с потерей точности. Результат получается как в этом примере:

num64 = 0x1234567890ABCDEF;

WSH.echo(num64.toString(16).toUpperCase());

Даже если ничего с числом не делать, а сразу передать в другой метод, оно уже передаётся как Double.

Попробовал возвращать тип LONGLONG, т.е. собственно int64. JScript его не узнаёт, хотя и не ругается, если с числом ничего не делать. Если передать в другой метод, передаётся в нетронутом виде.

Универсальным решением, наверно, был бы возврат в типе Object. Он может в себе содержать что угодно, лишь бы предоставлял методы для операций над содержимым.

max7 пишет:

А такой вариант работает, проверьте, пожалуйста.

Да, так работает. Что-то пока не улавливаю, в чём тут подвох, попробую разобраться.

126 (изменено: max7, 2010-02-04 03:05:02)

Re: WSH: обсуждаем DynamicWrapperX от YMP

Протестируйте, пожалуйста, такой вариант (он незначительно отличается от исходного)

DX = new ActiveXObject("DynamicWrapperX");

DX.Register("user32", "EnumWindows",    "i=pl");
DX.Register("user32", "GetWindowTextW", "i=hWl");          // Вариант Unicode.
// DX.Register("user32", "GetWindowText", "i=hSl");        // Вариант ANSI.

pCbkFunc = DX.RegisterCallback(CbkEnumWin, "i=hl", "r=l"); // Регистрация CbkEnumWin
                                                           // как функции обратного
                                                           // вызова и получение
                                                           // указателя.
n=0, m=0, WinList="";

Title = DX.Space(256);              // Буфер под заголовок окна (выходная строка).

DX.EnumWindows(pCbkFunc, 0);        // Вызов EnumWindows с передачей ей указателя на
                                    // callback-функцию.

WScript.Echo("Всего окон: " + m + "\nС заголовками: " + n + "\n\n" + WinList);


// ............... Собственно callback-функция ....................

function CbkEnumWin(hwnd, lparam)
{
  DX.GetWindowTextW(hwnd, Title, 256);
  // DX.GetWindowText(hwnd, Title, 256);  // Вариант ANSI.
  if(Title.length > 0) {  // Если длина заголовка больше 0, заносим в список.
     // WinList += hwnd + "\t" + Title + "\n"; // оригинал
    WinList += hwnd + "\t" + (Title.substr(0)) + "\n"; // !!!!!!!!!
    ++n;
  }
  ++m;
  return 1;              // Если вернуть 0, вызовы прекратятся.
}

Кстати, пару раз была ошибка

Ошибка приложения wscript.exe, версия 5.7.0.18066, модуль dynwrapx.dll, версия 1.0.0.0, адрес 0x00001c89.

при комбинациях

Title = DX.Space(256);
...
Title = DX.Space(256,"");
...
Title.substring(0,Title.length)
...
Title.substr(0)

127

Re: WSH: обсуждаем DynamicWrapperX от YMP

Да, работает и так. Я вчера пришёл практически к тому же варианту:

WinList += hwnd + "\t" + Title.slice(0) + "\n";

Ещё можно сделать Title локальной переменной, или оставить глобальной, но инициализировать внутри функции. Также помогают и манипуляции с WinList, даже такая вроде бы бесполезная строчка:

WinList.length;

В общем, чего-то подобного можно было ожидать, т.к. callback — самопальная фича, не предусмотренная разработчиками движка, и при его изменении их не волнует её работоспособность.

Ошибки по адресу 0x00001c89 у меня пока не было, и кстати, глядя в дебагере, адрес приходится между двух инструкций, что для меня непонятно.

128

Re: WSH: обсуждаем DynamicWrapperX от YMP

А мне кажется, что дело скорее не в callback, а в каких-то оптимизациях движки jscript при работе со строками.

129

Re: WSH: обсуждаем DynamicWrapperX от YMP

Кстати, к вопросу почему срабатывает ".substr(0)", вот такой вот удивительный код

var dx = new ActiveXObject("DynamicWrapperX");

var a = "this is string";

var b = a + "";

var c = a + "!";

var d = a.substr(0);

var e = ((function(x) { return ""+x;})(a));
 
WScript.Echo( 
   "a: (\"this is string\") \t\t\t" + a + " \t" + dx.StrPtr(a,"w") + "\n" + 
   "b: (a + \"\") \t\t\t" + b + " \t" + dx.StrPtr(b,"w") + "\n" +
   "c: (a + \"!\") \t\t\t" + c + " \t" + dx.StrPtr(c,"w") + "\n" +
   "d: (a.substr(0)) \t\t\t" + d + " \t" + dx.StrPtr(d,"w") + "\n" +
   "e: (((function(x) { return \"\"+x;})(a))) \t" + e + " \t" + dx.StrPtr(e,"w") + "\n"
);

130

Re: WSH: обсуждаем DynamicWrapperX от YMP

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

На всякий случай, у меня выдало вот что:

---------------------------
Windows Script Host
---------------------------
a: ("this is string")                   this is string  37495100
b: (a + "")                             this is string  37495100
c: (a + "!")                            this is string! 3634964
d: (a.substr(0))                        this is string  3634908
e: (((function(x) { return ""+x;})(a))) this is string  37495100

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

Исключение прямого доступа к данным — это, кажись, одна из идей ООП. Доступ идёт только через функции. Поэтому внутренний формат данных не имеет значения и может меняться, никак не затрагивая использующий их код. Поскольку функция типа GetName() может спокойно продолжать существовать. Интересная идея, кстати. DynamicWrapperX — это, в общем, монолитное приложение, что вышло боком, когда я попытался кое-что кардинально в нём изменить. Сейчас подумываю над второй версией, которая будет устроена уже иначе.

131

Re: WSH: обсуждаем DynamicWrapperX от YMP

Да, а ещё есть строки-объекты ("обёртка" над данными) и строки-значения (непосредственно данные). И где в скрипте что и как оформлено определить сложно, а во "вне" всегда передаётся указатель на данные. Вот так данные изменились, а объект (и дополнительные данные) нет. Но я могу и ошибаться.

132

Re: WSH: обсуждаем DynamicWrapperX от YMP

Подскажите , а можно с помощью данной компоненты получить описание типа к примеру "TDCB" , который используется в API  функции получения данных COM порта ? Реализация кода на DELPHI выглядет :

function SetupCOMPort: Boolean;
var DCB: TDCB;
begin
  Result := True;
  if not GetCommState(ComFile, DCB) then  Result := False;
end;

Мне это нужно для получения настроек COM порта в 1С Предприятии 8.1.
Код в 1С выглядит так :

        Wrap = Новый COMОбъект("DynamicWrapperX");
    Wrap.Register("KERNEL32.DLL", "GetCommState", "i=ll", "r=l");

        if not Wrap.GetCommState(ComFile, DCB) then  Result = False; EndIf;

С переменной ComFile все ясно это указатель (я это уже преодолел с помощью компоненты), переменная DCB:=TDCB  а та в свою очередь имеет тип :

type
  _DCB = packed record
    DCBlength: DWORD;
    BaudRate: DWORD;
    Flags: Longint;
    wReserved: Word;
    XonLim: Word;
    XoffLim: Word;
    ByteSize: Byte;
    Parity: Byte;
    StopBits: Byte;
    XonChar: CHAR;
    XoffChar: CHAR;
    ErrorChar: CHAR;
    EofChar: CHAR;
    EvtChar: CHAR;
    wReserved1: Word;
  end;

как мне получить описание данного типа в 1С-ке и передать указатель на него в функцию GetCommState?
Прошу спасите меня от мук поисков . Уже мозги кипят..

133

Re: WSH: обсуждаем DynamicWrapperX от YMP

Маленький пример как можно работать с типами. Вызываю функцию GetLocalTime

'Private Declare Sub GetLocalTime Lib "kernel32.dll" (ByRef lpSystemTime As SYSTEMTIME)
'Private Type SYSTEMTIME
'    wYear As Integer
'    wMonth As Integer
'    wDayOfWeek As Integer
'    wDay As Integer
'    wHour As Integer
'    wMinute As Integer
'    wSecond As Integer
'    wMilliseconds As Integer
'End Type

Dim DX, St, pSt
Set DX = CreateObject("DynamicWrapperX") 'Создаём объект

St = DX.Space(8, "") 'Данный String - будет 16 байтовым буфером структуры
pSt = DX.StrPtr(St)

DX.Register "kernel32", "GetLocalTime", "i=l"
DX.GetLocalTime pSt 'Заполняем структуру вызовом API

'Читаем по 2 байта из указателя
MsgBox "Год: " & DX.NumGet(pSt, 0, "n") & vbCrLf & _
       "Месяц: " & DX.NumGet(pSt, 2, "n") & vbCrLf & _
       "День: " & DX.NumGet(pSt, 6, "n") & vbCrLf & _
       "Часы: " & DX.NumGet(pSt, 8, "n") & vbCrLf & _
       "Минуты: " & DX.NumGet(pSt, 10, "n") & vbCrLf & _
       "Секунды: " & DX.NumGet(pSt, 12, "n"), vbInformation

134

Re: WSH: обсуждаем DynamicWrapperX от YMP

Да, выделить память нужного размера и передать указатель на неё. Потом считывать члены структуры через NumGet. Размер, если я не обсчитался, 28 байт. Поскольку в 1С какие-то, помнится, проблемы при использовании строк в качестве буферов, можно просто зарегить функции GlobalAlloc и GlobalFree и запрашивать/освобождать память через них.

Как-нибудь так, наверно:

Wrap = Новый COMОбъект("DynamicWrapperX");
Wrap.Register("kernel32.dll", "GlobalAlloc", "i=uu", "r=p");
Wrap.Register("kernel32.dll", "GlobalFree", "i=p");
Wrap.Register("KERNEL32.DLL", "GetCommState", "i=lp", "r=l");

GPTR = 64;      // GPTR = GMEM_FIXED | GMEM_ZEROINIT, обнулённая память.
pDCB = Wrap.GlobalAlloc(GPTR, 28);
Wrap.NumPut(28, pDCB, 0, "u");  // Пишем размер структуры в её начало,
                                // как требует MSDN.
if not Wrap.GetCommState(ComFile, pDCB) then  Result = False; EndIf;

BaudRate  = Wrap.NumGet(pDCB, 4,  "u");
Flags     = Wrap.NumGet(pDCB, 8,  "u"); 
XonLim    = Wrap.NumGet(pDCB, 14, "t");
XoffLim   = Wrap.NumGet(pDCB, 16, "t");
ByteSize  = Wrap.NumGet(pDCB, 18, "b");
Parity    = Wrap.NumGet(pDCB, 19, "b");
StopBits  = Wrap.NumGet(pDCB, 20, "b");
XonChar   = Wrap.NumGet(pDCB, 21, "c");
XoffChar  = Wrap.NumGet(pDCB, 22, "c");
ErrorChar = Wrap.NumGet(pDCB, 23, "c");
EofChar   = Wrap.NumGet(pDCB, 24, "c");
EvtChar   = Wrap.NumGet(pDCB, 25, "c");

// Ну и когда структура больше не нужна:
Wrap.GlobalFree(pDCB);

135

Re: WSH: обсуждаем DynamicWrapperX от YMP

Огромное спасибо YMP !!! Я очень вам признателен за быстрый ответ и за подсказку !!! В коде все понятно . Буду пробовать. Листинг для работы с COM портом в 1С Предприятии 8.1 с помощью компоненты DynamicWrapperX обещаю выложить как закончу.

136

Re: WSH: обсуждаем DynamicWrapperX от YMP

VSVLAD пишет:

Маленький пример как можно работать с типами. Вызываю функцию GetLocalTime

'Private Declare Sub GetLocalTime Lib "kernel32.dll" (ByRef lpSystemTime As SYSTEMTIME)
'Private Type SYSTEMTIME
'    wYear As Integer
'    wMonth As Integer
'    wDayOfWeek As Integer
'    wDay As Integer
'    wHour As Integer
'    wMinute As Integer
'    wSecond As Integer
'    wMilliseconds As Integer
'End Type

Dim DX, St, pSt
Set DX = CreateObject("DynamicWrapperX") 'Создаём объект

St = DX.Space(8, "") 'Данный String - будет 16 байтовым буфером структуры
pSt = DX.StrPtr(St)

DX.Register "kernel32", "GetLocalTime", "i=l"
DX.GetLocalTime pSt 'Заполняем структуру вызовом API

'Читаем по 2 байта из указателя
MsgBox "Год: " & DX.NumGet(pSt, 0, "n") & vbCrLf & _
       "Месяц: " & DX.NumGet(pSt, 2, "n") & vbCrLf & _
       "День: " & DX.NumGet(pSt, 6, "n") & vbCrLf & _
       "Часы: " & DX.NumGet(pSt, 8, "n") & vbCrLf & _
       "Минуты: " & DX.NumGet(pSt, 10, "n") & vbCrLf & _
       "Секунды: " & DX.NumGet(pSt, 12, "n"), vbInformation

VSVLAD Спасибо за код. Маленько не то что я просил , но я думаю пригодиться в дальнейшем. Код читаем все ясно.

137 (изменено: boss_kuz, 2010-07-30 18:01:44)

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP (ответ на предыдущее сообщение) не подскажите, а такая реализация  создания структуры может работать ?

 Wrap.Register("KERNEL32.DLL", "GetCommState", "i=lp", "r=l");

pDCB =Wrap.Space(28);
Wrap.NumPut(28,pDCB ,0,"u");

if not Wrap.GetCommState(ComFile, pDCB) then  Result = False; EndIf;

BaudRate  = Wrap.NumGet(pDCB, 4,  "u");
Flags     = Wrap.NumGet(pDCB, 8,  "u"); 
XonLim    = Wrap.NumGet(pDCB, 14, "t");
XoffLim   = Wrap.NumGet(pDCB, 16, "t");
ByteSize  = Wrap.NumGet(pDCB, 18, "b");
Parity    = Wrap.NumGet(pDCB, 19, "b");
StopBits  = Wrap.NumGet(pDCB, 20, "b");
XonChar   = Wrap.NumGet(pDCB, 21, "c");
XoffChar  = Wrap.NumGet(pDCB, 22, "c");
ErrorChar = Wrap.NumGet(pDCB, 23, "c");
EofChar   = Wrap.NumGet(pDCB, 24, "c");
EvtChar   = Wrap.NumGet(pDCB, 25, "c");

и еще вопрос - переменные созданные функцие Wrap.Space(n) в памяти уничтожаются сами при выходе или необходимы какие нибудь действия? если да то какие ? Спасибо .

138

Re: WSH: обсуждаем DynamicWrapperX от YMP

Уничтожаются, для того я и придумал такой способ создания буфера — в виде строки. Но я ж говорю, в 1С какие-то заморочки со строками, которые мешают их так использовать. В этой ли теме или в другой, кто-то об этом писал. А буфер через GlobalAlloc никуда не денется и 1С в его содержимое никогда не полезет.

Но если у Вас всё работает, то дело хозяйское. Только нужно учесть, что методу Space указывается количество юникодных символов, а не байтов. А каждый такой символ — 2 байта, так что достаточно будет:

pDCB = Wrap.Space(14);

139

Re: WSH: обсуждаем DynamicWrapperX от YMP

Понятно. Использование Space()  в 1С Передприятии не рекомендуется т.е. работаем только с памятью напрямую , а через переменные передаем указатели и прежде чем 1с уничтожит переменную мы должны сами освободить память на которую указывает указатель. Тода будем изучать функции Win API поподробнее.

140

Re: WSH: обсуждаем DynamicWrapperX от YMP

На всякий случай: не забудьте про Microsoft Script Control, иногда помогает обойти проблемы 1С.

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

141 (изменено: boss_kuz, 2010-08-01 12:49:56)

Re: WSH: обсуждаем DynamicWrapperX от YMP

Подскажите почему функция Register() не находит API функцию OpenComm (LPCSTR lpszDevControl,UINT cbInQueue, UINT cbOutQueue);

Wrap.Register("KERNEL32.DLL", "OpenComm" ,"i=pll","r=l");

или к примеру

Wrap.Register("KERNEL32.DLL", "GetWinFlags" ,"r=l");

142

Re: WSH: обсуждаем DynamicWrapperX от YMP

Их там нет. Насколько понял, это 16-битные функции, которые Win32 не предоставляет. Вместо OpenComm нужно использовать CreateFile. Вместо GetWinFlags — GetSystemInfo.

143

Re: WSH: обсуждаем DynamicWrapperX от YMP

Спасибо

144 (изменено: boss_kuz, 2010-08-03 10:17:20)

Re: WSH: обсуждаем DynamicWrapperX от YMP

Вопрос к специалистам.Извините что задаю этот вопрос в данной ветке. Изучаю DynamicWrapperX.
Объясните неопытному почему команда на паскале в Delphi типа

var b:String;
      b:=#97#0;

при трассировке дельфи пишет типа : b = 'a'#0, указатель ^b=00453460 , содержимое памяти : 61 00 00 ???
Но ведь код символа "a" это 97, а в памяти 61 как это может быть?
http://s04.radikal.ru/i177/1008/de/22ab6b46c696.jpg

145

Re: WSH: обсуждаем DynamicWrapperX от YMP

97 десятичное — то же, что 61 шестнадцатеричное.

146

Re: WSH: обсуждаем DynamicWrapperX от YMP

я бот .... похоже надо отдохнуть. Спасибо.

147 (изменено: boss_kuz, 2010-08-03 13:24:09)

Re: WSH: обсуждаем DynamicWrapperX от YMP

1С Предприятие 8.1

        GPTR = 64;      // GPTR = GMEM_FIXED | GMEM_ZEROINIT, обнулённая память.
        pConfig = Wrap.GlobalAlloc(GPTR, СтрДлина(Config)+1);// +1 создаем буфер строки которая оканчивается нулем
                Config="baund=.. parity=.... data... stop..."; // строка для передачи в порт для настройки 
        Для i=1 По СтрДлина(Config) Цикл
            Wrap.NumPut(КодСимвола(Сред(Config,i,1)),pConfig,i-1,"b");
        КонецЦикла;         
        if not Wrap.BuildCommDCB(pConfig, pDCB) then Result = False; функция заполняет настройки порта

в данном коде буфер pConfig содержит представления символов в десятичном или шестнадцатеричном формате ?
примечание : КодСимвола() возвращает код символа в десятичном представлении.
Получается фрагмент кода не нужен и можно просто передать переменную Config в функцию BuildCommDCB  вместо указателя pConfig.
Если NumPut записывает десятичное представление символа в ячейку памяти тогда становится интересно почему все работает я проверял . К примеру скорость передачи порта изменяется.

148

Re: WSH: обсуждаем DynamicWrapperX от YMP

Коды символов строки хранятся в памяти в двоичном виде. Десятичный/шестнадцатеричный — это способы отображения числа, число в памяти при этом то же самое.

Поскольку pConfig — это строка, то да, можно просто передавать строковую переменную. При регистрации BuildCommDCB указать этот параметр как s. Если использовать юникодную версию функции — BuildCommDCBW, тогда тип строки указать как w.

149 (изменено: boss_kuz, 2010-09-10 08:44:24)

Re: WSH: обсуждаем DynamicWrapperX от YMP

Пример обработки работы с COM портом из 1С Предприятия 8.1 с помощью DynamicWrapperX

http://s59.radikal.ru/i165/1008/fb/44cb20bfda06.jpg     http://s41.radikal.ru/i092/1008/31/6ae23b791108.jpg
Для запуска нужно просто открыть в 1С данную обработку. При первом запуске она автоматически зарегистрирует компоненту DynamicWrapperX в вашей системе. Далее выбираем порт к которому подключено устройство , устанавливаем настройки порта и можем тестить. В коде я описал все структуры и функции WinAPI для работы с портом , методы DynamicWrapperX и работу с ними можно почитать здесь http://rapidshare.com/files/411259195/Help.html , скачать компоненту здесь http://rapidshare.com/files/411259421/dynwrapx.dll
Большое спасибо "YMP" и "The gray Cardinal" за подсказки . Любые пожелания для доработки, выявленные ошибки шлите на мыло.
Скачать обработку :  http://rapidshare.com/files/418180199/HTerminal.epf ............... Исправлена ошибка работы с COM портом выше 9-го.

150

Re: WSH: обсуждаем DynamicWrapperX от YMP

Юрий, а правильно я понимаю, что когда мы вызываем RegisterCallback и передаем указатель на функцию, то в DXW приезжает IDispatch MSScriptControl'а?

151

Re: WSH: обсуждаем DynamicWrapperX от YMP

chessman пишет:

Юрий, а правильно я понимаю, что когда мы вызываем RegisterCallback и передаем указатель на функцию, то в DXW приезжает IDispatch MSScriptControl'а?

А почему MSScriptControl'а? Функция — это объект в JScript и VBScript. Вот указатель на IDispatch этого объекта и передаётся из скрипта методу RegisterCallback. В 1С, очевидно, так же, если там работает RegisterCallback. В общем-то, функция этот объект или что другое, никак не проверяется, потому что неясно, как вообще это можно проверить.

При вызовах функции у объекта запрашивается метод "call" — в JScript объект функции имеет такой метод. Если его нет, то вызывается метод с идентификатором 0 — в VBScript он безымянный, как я понял. Какой из этих вариантов срабатывает для 1С, я не знаю.

152

Re: WSH: обсуждаем DynamicWrapperX от YMP

Ок, понял.
Я сейчас код изучаю под Идой, хочу разобраться как это вообще функционирует. Проблему тут вроде озвучивали, но я повторюсь-почему-то после уничтожения MSScriptControl'а, видно, что указатели на внутренние таблицы функций не инициализируются, т.е. как будто объект и не уничтожался. Сейчас я проблему решил просто ручным обновлением указателей (off_10003030, off_10003038), благо у меня это используется в одной единственной обработке и путаницы не возникает, при "удалении" ссылки. Не знаю, понятно ли я выразился.

153

Re: WSH: обсуждаем DynamicWrapperX от YMP

Честно говоря, непонятно. О какой проблеме речь? И как MSScriptControl связан с RegisterCallback? И что за внутренние таблицы функций?

154

Re: WSH: обсуждаем DynamicWrapperX от YMP

Я имел ввиду, что объект DWX не уничтожается после его использования в скрипте. Может конечно сам MSScriptControl не уничтожается, а соответственно и DWX. Как это видно? - RegisterCallback возвращает возрастающие адреса внутренних функций, даже если закрыть обработку и заново ее запустить.
Про указатели на внутренние таблицы...есть 2 указателя, один на внутренние функции RegisterCallback, другой, видимо на 4 параметра для них (один из параметров IDispatch).

Зы:пользуясь случаем, хочу поблагодарить за DXW, очень полезная разработка!!!

155

Re: WSH: обсуждаем DynamicWrapperX от YMP

Ну, трудность ещё в том, что смутно представляю, что конкретно происходит при "закрытии обработки". Вообще, каждый экземпляр объекта содержит счётчик ссылок на него. И когда счётчик обнуляется, экземпляр уничтожается. Но Callback'и не принадлежат конкретному экземпляру. Они будут сброшены только при перезагрузке библиотеки (dynwrapx.dll). Сама себя она не выгружает, даже если все объекты уничтожены, а только отвечает "можно" на запрос операционной системы (через экспортируемую функцию DllCanUnloadNow). Если запроса нет, то и выгрузки нет. Выгрузку библиотеки может также заблокировать клиент — через метод LockServer интерфейса IClassFactory. Для этого тоже есть счётчик. Если он не на нуле, то даже если все объекты уничтожены и придёт запрос от системы, библиотека не выгрузится, т.к. DllCanUnloadNow вернёт отказ.

Просто не все возможные ситуации я предусмотрел.

156

Re: WSH: обсуждаем DynamicWrapperX от YMP

Спасибо, Юрий! Теперь ясно куда копать.

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

157

Re: WSH: обсуждаем DynamicWrapperX от YMP

А какова конечная цель? Для чего это нужно?

158

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP пишет:

А какова конечная цель? Для чего это нужно?

Как вариант - возможность обращения к внутренним функциям движка 1С, ну и просто "академический" интерес.

159

Re: WSH: обсуждаем DynamicWrapperX от YMP

Пока сделал таким образом - после загрузки dynwrapx, добавляю в связанный список встроенных функций еще одну RegisterAddr, с ID = 9. Она работатет точно так же как и Register, только ее первый параметр Адрес памяти. Таким образом можно именовать участки кода в памяти и вызывать виртуальные функции объектов.

160

Re: WSH: обсуждаем DynamicWrapperX от YMP

Интересная идея, надо будет реализовать её в будущем. Я тоже думал о возможности выполнять код по адресу, правда только в применении к коду, записанному из скрипта в память. В AutoHotkey, например, это есть и позволяет иногда ускорить скрипт в десятки раз. То, что можно адресу присвоить имя — да, интересная мысль. Так получится стандартнее. Можно ещё сделать вариант Register, который принимал бы первым аргументом HEX-строку с кодом.

161

Re: WSH: обсуждаем DynamicWrapperX от YMP

Отлично! Будем ждать!
Кстати, это решит параллельно еще одну проблему - вызов функций с "кривыми" именами (типа, ?wndNoTopMost@CWnd@@2V1@B).

162

Re: WSH: обсуждаем DynamicWrapperX от YMP

Только, боюсь, не скоро. Исходник первой версии Dynwrapx утрачен, сгорел вместе с компьютером при пожаре. Вторая же версия пока на начальной стадии. Не совсем пока мне ясно, как она будет устроена внутри. Надо ещё пробовать и смотреть. Если у Вас есть мысли, какие фичи желательно добавить к функционалу первой версии, пишите.

163

Re: WSH: обсуждаем DynamicWrapperX от YMP

Ясно. ((
Ну, может это и к лучшему, обычно при переписи, код получается еще более лаконичным.

Пока буду тестировать этот функционал. На данный момент, есть желание загружать регистр ecx, для thiscall-вызовов.

164

Re: WSH: обсуждаем DynamicWrapperX от YMP

Да, нужно будет добавить к Register параметр для указания соглашения вызова регистрируемой функции.

165 (изменено: chessman, 2010-11-09 17:56:51)

Re: WSH: обсуждаем DynamicWrapperX от YMP

Юрий, вы не будете против, если я пока начну обсуждение "нового" функционала, на нашем 1С-форуме? Я тут уже накропал небольшую обработку, которая как раз использует обращения к виртуальным функциям объектов?

В случае согласия, мне придется выложить на 1С-м форуме "исправленный" dynwrapx.dll. Собственно я там изменил только один байт в PE-заголовке, чтобы сделать секцию .const writeable.

166

Re: WSH: обсуждаем DynamicWrapperX от YMP

Нет, я не против. Только просьба — в ресурсе VERSIONINFO в dll отразить этот факт. Например, изменить последнюю цифру в версии файла (вроде там обычно разные билды одной версии нумеруются) и добавить строковый параметр PrivateBuild, в котором описать изменения и указать, кто их сделал. В общем, тут можно посмотреть, что там для чего: VERSIONINFO Resource.

Поскольку я тут уже как-то выкладывал тестовые билды, штук 6-7, то для верности можно задать версию файла 1.0.0.10. Всё это чтобы исключить возможную путаницу.

167

Re: WSH: обсуждаем DynamicWrapperX от YMP

Все сделал.

168

Re: WSH: обсуждаем DynamicWrapperX от YMP

Сделал пару примеров - все пашет!!! Я в шоке!
Остается изучить тему передачи объектов из 1С и обратно.

169

Re: WSH: обсуждаем DynamicWrapperX от YMP

Сегодня обнаружил, что есть такая замечательная функция, как VirtualProtect. Получается, что и файл менять не нужно.

170

Re: WSH: обсуждаем DynamicWrapperX от YMP

chessman пишет:

Сегодня обнаружил, что есть такая замечательная функция, как VirtualProtect. Получается, что и файл менять не нужно.

Что она делает?

171 (изменено: chessman, 2010-12-01 11:06:31)

Re: WSH: обсуждаем DynamicWrapperX от YMP

jite пишет:
chessman пишет:

Сегодня обнаружил, что есть такая замечательная функция, как VirtualProtect. Получается, что и файл менять не нужно.

Что она делает?

http://msdn.microsoft.com/en-us/library … S.85).aspx

172

Re: WSH: обсуждаем DynamicWrapperX от YMP

Юрий, из хотелок, так сказать на будущее....я думаю, что будет на сложно снять ограничение для RegisterCallBack, организовав связанный список функций (как это сделано для Register) вместо массива, как сейчас.
Спасибо.

173

Re: WSH: обсуждаем DynamicWrapperX от YMP

Да, согласен, надо это сделать. Я ещё в начале об этом думал, но не знал, как реализовать, и отложил разбирательство на потом.

174

Re: WSH: обсуждаем DynamicWrapperX от YMP

Юрий, а правильно ли я понимаю, что при уничтожении объекта dwx, память, выделенная методом "Register" (под 'описание функции', переменные) не освобождается? Или этого делать не надо?

175

Re: WSH: обсуждаем DynamicWrapperX от YMP

Честно говоря, уже трудно вспомнить. Вполне возможно, что так. Кажется, впоследствии я это исправлял в том варианте, который был в разработке. Или это было не то? Я там разные вещи пробовал и менял, теперь всё в памяти перемешалось.

176

Re: WSH: обсуждаем DynamicWrapperX от YMP

Ок. Я ведь правильно понимаю, что это нужно делать в реализации IDispatch_Release?

177

Re: WSH: обсуждаем DynamicWrapperX от YMP

Да. Уменьшается счётчик ссылок, и если он при этом обнуляется, надо освобождать всю память, запрошенную для объекта.

178

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP пишет:

Да. Уменьшается счётчик ссылок, и если он при этом обнуляется, надо освобождать всю память, запрошенную для объекта.

Сделал.

Теперь нужно побороться с RegisterCallBack. Нужно будет расширить объект еще на один указатель на список функций, зарегистрированных этим методом.

179

Re: WSH: обсуждаем DynamicWrapperX от YMP

chessman пишет:

Теперь нужно побороться с RegisterCallBack. Нужно будет расширить объект еще на один указатель на список функций, зарегистрированных этим методом.

Все сделал, теперь ограничение на кол-во вызовов RCB снято

180

Re: WSH: обсуждаем DynamicWrapperX от YMP

Это Вы всё через отладчик? Снимаю шляпу. Если будет работать стабильно, то можно, наверно, выложить в этой теме в Коллекции. Думаю, администрация не будет против дать Вам на форуме статус разработчика, чтобы Вы могли это сделать.

181

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP, готово. chessman, добро пожаловать! Ознакомьтесь с 6. Разделы форума и права посетителей.

182

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP пишет:

Это Вы всё через отладчик? Снимаю шляпу. Если будет работать стабильно, то можно, наверно, выложить в этой теме в Коллекции. Думаю, администрация не будет против дать Вам на форуме статус разработчика, чтобы Вы могли это сделать.

IDA сделала бОльшую часть работы.  
С другой стороны, было очень интересно посмотреть, как это всё устроено изнутри.
Я довольно давно использую DWX в 1C. Радует то, что на одной маааааленькой dll-ке можно организовать кучу нового функционала, к тому же с открытым кодом.


ЗЫ:скрипт выложил, но в отдельную ветку, т.к. не знаю, как в вышеприведенной теме прикрепить файлик.

183

Re: WSH: обсуждаем DynamicWrapperX от YMP

alexii пишет:

YMP, готово. chessman, добро пожаловать! Ознакомьтесь с 6. Разделы форума и права посетителей.

Спасибо за доверие

184

Re: WSH: обсуждаем DynamicWrapperX от YMP

chessman пишет:

IDA сделала бОльшую часть работы.

Никогда ею не пользовался. Только эпизодически — OllyDbg. Так что и его возможности знаю слабо. Видимо, чукча не читатель, чукча писатель.  Обычно кажется, что проще самому с нуля написать, чем разбирать чужой код.


chessman пишет:

ЗЫ:скрипт выложил, но в отдельную ветку, т.к. не знаю, как в вышеприведенной теме прикрепить файлик.

Просто ответить на первый пост, то бишь нажать "Ответить" и на странице ответа будет кнопка Обзор.

185

Re: WSH: обсуждаем DynamicWrapperX от YMP

chessman, я изменил заголовок темы, включил ссылку на оригинальный DynamicWrapperX, поправил оформление и пару орфографических и грамматических ошибок.

Проверьте, пожалуйста, не внёс ли я туда каких-либо ошибок.

186

Re: WSH: обсуждаем DynamicWrapperX от YMP

alexii пишет:

chessman, я изменил заголовок темы, включил ссылку на оригинальный DynamicWrapperX, поправил оформление и пару орфографических и грамматических ошибок.

Проверьте, пожалуйста, не внёс ли я туда каких-либо ошибок.

Все верно.

187

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP пишет:
chessman пишет:

IDA сделала бОльшую часть работы.

Никогда ею не пользовался.

Кстати, IDA, сильно помогла с отладкой.

188

Re: WSH: обсуждаем DynamicWrapperX от YMP

Добавил еще 2 встроенных метода GetIDispatch и GetObject.

189

Re: WSH: обсуждаем DynamicWrapperX от YMP

помогите плиз, как получить имя компьютера с помощью функции GetComputerName
если не сложно, то на JScript
только начинаю разбираться с DynamicWrapper, так что не пинайте сильно ))

190

Re: WSH: обсуждаем DynamicWrapperX от YMP

Вот так, например:

DX = new ActiveXObject("DynamicWrapperX");
DX.Register("kernel32", "GetComputerNameW", "i=Wp", "r=l");

MAX_COMPUTERNAME_LENGTH = 15;   // Взято из WinBase.h.

name = DX.Space(MAX_COMPUTERNAME_LENGTH + 1);   // Буфер под имя.
bufsize = DX.Space(2);                          // Буфер под размер буфера.
DX.NumPut(name.length, bufsize);                // Пишем туда размер.

if (DX.GetComputerNameW(name, bufsize))
    WSH.Echo("Имя компьютера: " + name);
else
    WSH.Echo("Ошибка GetComputerName.");

191

Re: WSH: обсуждаем DynamicWrapperX от YMP

YMP, спасибо большое!
а то совсем запутался с буферами ))

192

Re: WSH: обсуждаем DynamicWrapperX от YMP

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

193

Re: WSH: обсуждаем DynamicWrapperX от YMP

Тут на форуме есть раздел Community, создайте там тему с этим вопросом. А здесь действительно это обсуждать ни к чему.

194 (изменено: Аскет, 2011-03-17 03:30:51)

Re: WSH: обсуждаем DynamicWrapperX от YMP

В DynamicWrapperX отсутствует логический тип данных BOOL (Boolean). Какой тип выгоднее всего использовать в данном случае?
[c]?

p.s. Это не критично, но всё же было бы удобнее подгонять код под прототипы функций
(на случай если будете модернизировать компонент)

195

Re: WSH: обсуждаем DynamicWrapperX от YMP

Вроде, так:

WinDef.h

typedef int                 BOOL;

WinNT.h

typedef BYTE  BOOLEAN;           
typedef BOOLEAN *PBOOLEAN;

196

Re: WSH: обсуждаем DynamicWrapperX от YMP

Ну, раз BOOL в конечном итоге int, то логично использовать тип "l". Насчёт какой выгоднее, не знаю.

197

Re: WSH: обсуждаем DynamicWrapperX от YMP

Я тоже Long использовал, но вот задумался...

...выделять 4 байта под 1-битовую по сути переменную - это же верх расточительства и бескультурщины!

Остаются [c](-128..127) и [b](0..255) как самые близкие по значению. А так как (где-то я такое видел, по моему что-то из разряда variant) ложное значение может быть отрицательным (-1,-2), то остаётся c.


И всё таки, если надумаете пересобирать, то прошу добавить этот полезнейший тип данных.

198

Re: WSH: обсуждаем DynamicWrapperX от YMP

Наоборот, насколько знаю, истинное может быть отрицательным (-1), ложное всегда 0. А буквы подходящей всё равно нету, b ведь уже задействована. Какую предлагаете?

Аскет пишет:

...выделять 4 байта под 1-битовую по сути переменную - это же верх расточительства и бескультурщины!

Раз в хедерах Майкрософта BOOL определён как int, то деваться уже некуда, потому что именно int и ожидают функции API на самом деле, и его же реально и возвращают. BOOL — всего лишь псевдоним. BOOLEAN я что-то не помню в описаниях апишек.

Когда вызывается функция, параметры ей передаются через специальную область памяти — стек, а стек нельзя при этом сдвигать на произвольное количество байт. Шаг должен быть кратен 4 байтам у 32-разрядных функций и 8 у 64-разрядных. Так что однобайтовый параметр всё равно займёт 4 байта. Если функции нужен только один байт, то его она и использует, игнорируя остальные.

199

Re: WSH: обсуждаем DynamicWrapperX от YMP

От оно чё. Спасибо за пояснение.

YMP пишет:

BOOLEAN я что-то не помню в описаниях апишек.

Это логический тип в Pascal/Delphi. Да и чисто по англицки "BOOLEAN" - "логический".

200 (изменено: mikser, 2011-03-21 23:02:15)

Re: WSH: обсуждаем DynamicWrapperX от YMP

Помогите правильно указать указатель и\или обратиться по указателю.
Не могу понять что не так делаю.
Есть такая библиотека curl ,  скачиваем http://www.gknw.net/mirror/curl/win32/c … ingw32.zip .
Находим в архиве dll-ки и распаковываем их в %SystemRoot%\System32 , потом запускаем мой пример и смотрим где я накосячил.

<html>
 <head>
  <title> Curl Test</title>
 </head>

<body>
  <script type="text/javascript">

  CURLOPT_URL                     = 10002
  CURLINFO_RESPONSE_CODE           = 2097154
  CURLOPT_HEADER                  = 42


  var DX=new ActiveXObject("DynamicWrapperX");
  var libcurldll="libcurl.dll";

  //function  curl_easy_init:pCURL; cdecl; external LIB_CURL;
  DX.Register(libcurldll, "curl_easy_init",      "r=p");
  //function  curl_easy_setopt(curl:pCURL; option:CURLoption):CURLcode; varargs; cdecl; external LIB_CURL;
  DX.Register(libcurldll, "curl_easy_setopt",    "i=plp","r=l")
  //function  curl_easy_perform(curl:pCURL):CURLcode; cdecl; external LIB_CURL;  
  DX.Register(libcurldll, "curl_easy_perform",   "i=p","r=l")

  //procedure curl_easy_cleanup(curl:pCURL); cdecl; external LIB_CURL;
  DX.Register(libcurldll, "curl_easy_cleanup",   "i=p")

  //function  curl_easy_getinfo(curl:pCURL; info:CURLINFO; out value):CURLcode; cdecl; external LIB_CURL;
  DX.Register(libcurldll, "curl_easy_getinfo",   "i=plL","r=l")
  //function  curl_easy_duphandle(curl:pCURL):pCURL; cdecl; external LIB_CURL;
  DX.Register(libcurldll, "curl_easy_duphandle", "i=p","r=p")
  //procedure curl_easy_reset(curl:pCURL); cdecl; external LIB_CURL;
  DX.Register(libcurldll, "curl_easy_reset",     "i=p")

 
  with (DX)
  {
  //выполняем инициализацю
  var curl = curl_easy_init();

  if(curl) 
  { 
    //проверяем
    //задаем опцию - получить страницу по адресу http://google.com
    curl_easy_setopt(curl, CURLOPT_URL, "http://google.com/");
    //указываем прокси сервер
 //   curl_easy_setopt(curl, CURLOPT_PROXY, "proxy:8080");
    //задаем опцию отображение заголовка страницы
    curl_easy_setopt(curl, CURLOPT_HEADER, 1);
    //вызываем функцию, выполняющюю все операции, заданные в опциях (получение страницы, передача данных и т.д.), результат - объект типа CURLcode
    res = curl_easy_perform(curl);
    //декларирую буфер с типом лонг :)
    var buf = new Number(0);
    // пробуем получить ответ сервера   
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, buf)

    document.writeln("res="+res+"<br>")
    document.writeln("buf="+NumGet(buf)+"<br>")

  //выполняем обязательное завершение сессии  
    curl_easy_cleanup(curl);
    }
  }
  </script>
 </body>
</html>

Проблема с curl_easy_getinfo  - не могу ее корректно за декларировать
curl_easy_getinfo

вот как ее вызывают на Си:

curl_code = curl_easy_perform (session);
long http_code = 0;
curl_easy_getinfo (session, CURLINFO_RESPONSE_CODE, &http_code);
if (http_code == 200 && curl_code != CURLE_ABORTED_BY_CALLBACK)
{
         //Succeeded
}
else
{
         //Failed
}

То есть в качестве третьего параметра должен быть указатель на число типа Long.
Но я и декларирую ее как L .
В ответ получаю жалобу на несовместимость типов.
и как потом получить результат тоже не знаю в сях есть оператор &, в паскале @, А в JScript как передать указатель?