Главная
Форумы
Новые сообщения
Поиск сообщений
Что нового?
Новые сообщения
Новые ресурсы
Последняя активность
Ресурсы
Последние отзывы
Поиск ресурсов
Помощь форуму
ЧатTG
Вход
Регистрация
Что нового?
Поиск
Поиск
Искать только в заголовках
От:
Новые сообщения
Поиск сообщений
Меню
Вход
Регистрация
Приложение
Установить
Форумы
Форум программистов
Visual Basic 6 / Сценарии VBScript, JScript
Банк полезных кодов
Вызов API-функций из VBScript / JScript (DynamicWrapperX)
JavaScript отключён. Чтобы полноценно использовать наш сайт, включите JavaScript в своём браузере.
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно.
Вам необходимо обновить браузер или попробовать использовать
другой
.
Ответить в теме
Сообщение
[QUOTE="Dragokas, post: 181324, member: 6966"] [CENTER][B][B][COLOR=rgb(0, 0, 255)]Подробности с сайта автора[/COLOR][/B][/B][/CENTER] [accordion=bcenter|80%] {slide=О библиотеке DynamicWrapperX|left} Автор: Юрий Попов (YMP на script-coding.com форуме). Условия распространения библиотеки: freeware. [URL='http://yuripopov.ucoz.net/index/dynwrapx/0-11']DynamicWrapperX[/URL] - это компонент ActiveX, который вы можете использовать в скриптах (JScript, VBScript и т.п.) для вызова: [LIST] [*]функций из библиотек DLL (в частности функций Windows API); [*]вообще любых функций, адрес которых в памяти вам известен; [*]функций, чей машинный код (в виде хекс-строки) у вас имеется. [/LIST] Компонент написан с нуля на языке ассемблера GoAsm как попытка более полной реализации идеи [URL='http://www.script-coding.com/dynwrap.html']DynamicWrapper[/URL]. [B]Другие возможности:[/B] [LIST] [*]обратный вызов (callback) скриптовой функции из вызванной вами внешней функции; [*]прямой доступ к памяти (чтение и запись числа по адресу); [*]выделение и освобождение памяти; [*]чтение и запись строк в произвольной кодировке; [*]получение указателя на строку, объект, массив, переменную; [*]получение объекта по указателю на него; [*]определение битности (32 или 64) процесса, в котором выполняется скрипт. [/LIST] {/slide} {slide=Регистрация в системе (установка)|left} Есть два способа регистрации: [code] regsvr32.exe <путь-к-компоненту>\dynwrapx.dll — для всех пользователей. regsvr32.exe /i <путь-к-компоненту>\dynwrapx.dll — для текущего пользователя.[/code] Регистрация для текущего пользователя не требует прав администратора, но имеет ограничения: [LIST] [*]в Windows 98 не работает; [*]в Windows Vista, 7 и 8 при включенном UAC объект будет недоступен приложениям, запущенным с правами администратора. [/LIST] В 64-битной ОС нужно регистрировать оба варианта DLL: x86 и x64, чтобы объект был доступен как 64-, так и 32-битным приложениям. [U]Примечание[/U] для пользователей 1-й версии. Если в системе уже установлена 1-я версия DWX, 2-я зарегистрируется параллельно с ней. В этом случае она будет доступна в скриптах только по имени DynamicWrapperX.2. Чтобы заменить старую версию новой, нужно сначала разрегистрировать старую. В этом случае новая версия будет доступна также и под общим именем DynamicWrapperX. Разрегистрация компонента: [code] regsvr32.exe /u <путь-к-компоненту>\dynwrapx.dll — для всех пользователей. regsvr32.exe /u /i <путь-к-компоненту>\dynwrapx.dll — для текущего пользователя.[/code] Если 2-я версия была установлена параллельно с 1-й, её разрегистрация никак не затронет регистрацию 1-й (и наоборот). {/slide} {slide=Метод Register - регистрация API перед ее вызовом|left} Этот метод регистрирует функцию из DLL в качестве метода объекта. Функция задаётся именем или ординалом. Значение аргументов "i=", "r=" и "f=" см. в примечаниях. [B]Регистрация по имени[/B] [code] DWX = new ActiveXObject("DynamicWrapperX"); DWX.Register("user32.dll", "MessageBoxW", "i=hwwu", "r=l"); res = DWX.MessageBoxW(0, "Hello, world!", "Test", 4); // Вызов.[/code] [B]Регистрация по имени с заменой его на другое[/B] [code] DWX.Register("user32:BadName", "GoodName", "r=n", "f=t"); // BadName — имя функции, например, содержащее символы, // недопустимые в именах методов, или просто очень длинное.[/code] [B]Регистрация по ординалу[/B] [code] DWX.Register("user32:110", "MethodName", "i=p", "r=l"); DWX.Register("user32:0x6E", "MethodName", "i=p", "r=l");[/code] Примечания [LIST] [*]Если файл библиотеки имеет расширение dll, его можно не указывать. Если файл не имеет расширения, имя должно быть указано с точкой на конце: "mylib." [*]Для системных DLL путь указывать не нужно. Для сторонних зависит от того, где они находятся. [*]Функции Windows API, принимающие или возвращающие строки, часто имеют два варианта: например, MessageBoxW для строк в Юникоде и MessageBoxA для строк в ANSI-кодировке. Букву "А" на конце можно не добавлять, DWX сделает это сам, если не найдёт функцию MessageBox, но имена юникодных функций должны указываться точно, c "W" на конце. [*]Ординал можно задавать десятичным или шестнадцатеричным числом. Учтите, что ординал функции может быть разным в разных версиях библиотеки и в x86 и x64 вариантах одной и той же версии. [*]Наличие аргументов "i=", "r=" и "f=" зависит от функции. Порядок их произвольный, т.к. они опознаются по префиксам. [*]"i=" задаёт тип каждого из параметров функции (целое число, дробное, строка и т.п.). Может опускаться только, если функция не имеет параметров. Расшифровка буквенных обозначений [URL='http://yuripopov.ucoz.net/index/dwx_types/0-14']здесь[/URL]. [*]"r=" — тип возвращаемого значения. Можно не указывать, если возвращаемое значение не нужно, даже если функция что-то возвращает. [*]"f=" — флаги, влияющие на то, как будет вызываться функция. На данный момент имеет одно возможное значение "t" (соглашение вызова thiscall). Имеет смысл только для 32-битного DWX и только со 2-й версии. 64-битным и 1-й версией игнорируется. [/LIST] {/slide} {slide=Метод RegisterAddr - регистрирует функцию по её адресу в памяти|left} Этот метод регистрирует функцию по её адресу в памяти. Остальные параметры те же, что у метода [URL='http://yuripopov.ucoz.net/index/dwx_register/0-12']Register[/URL]. [code]DWX.RegisterAddr(Address, "FuncName", "i=hwwu", "r=l");[/code] {/slide} {slide=Метод RegisterCode - ассемблерная вставка|left} Метод принимает в первом аргументе машинный код функции, представленный в виде хекс-строки. Остальные параметры те же, что у метода [URL='http://yuripopov.ucoz.net/index/dwx_register/0-12']Register[/URL]. [code=JavaScript]DWX = new ActiveXObject("DynamicWrapperX"); if (DWX.Bitness == 32) { // Функция, возвращающая произведение своих аргументов. Code = "8B442404F76C2408C3" } else { Code = "4889C8 48F7EA C3" // mov rax,rcx; imul rdx; ret } CodeAddr = DWX.RegisterCode(Code, "Multiply", "i=ll", "r=l"); WScript.Echo(DWX.Multiply(5, 4));[/code] Примечания [LIST] [*]Под код выделяется память, и он записывается туда уже в бинарном виде. После чего его можно вызывать по присвоенному ему во втором аргументе имени. Возвращаемое значение содержит адрес кода в памяти. Машинный код для 32 и 64 бит различен, отсюда необходимость проверки битности процесса (через проверку битности объекта DWX), чтобы определить, какой код использовать. В качестве возможного применения для такого кода можно привести обработку больших объёмов данных. Машинный код может работать в десятки или даже сотни раз быстрее скриптового. [*]Если вы хотите использовать код по его адресу, без создания метода, можно опустить все аргументы кроме первого. Но имейте в виду, что выделенная под код память всё же связана с объектом и будет освобождена в случае его уничтожения. [*]Хекс-строка может быть сплошной или содержать пробелы, табуляции и переводы строки. [*]Комментарии можно поместить прямо в хекс-строку, обрамив их скобками. Code = "4889C8 (mov rax,rcx) 48F7EA (imul rdx) C3 (ret)" [*]Если хекс-строка является многострочным текстом, комментарии можно обозначать точкой с запятой. Code = "4889C8 ; mov rax,rcx \n" + "48F7EA ; imul rdx \n" + "C3 ; ret" Но учтите, что в этом случае каждая строка, кроме последней, должна иметь на конце перевод строки, т.к. он используется как признак конца комментария. [/LIST] {/slide} {slide=Метод RegisterCallback|left} Этот метод нужен для получения указателя на скриптовую функцию, пригодного для передачи какой-либо функции API. Которая потом, используя этот указатель, могла бы данную скриптовую функцию вызывать. Пример такой API-функции — EnumWindows (см. код ниже). Она перебирает существующие окна и хэндл каждого окна передаёт callback-функции в качестве параметра. После этого она ждёт, что вернёт callback-функция. Если 1, то перебор идёт дальше, если 0 — прекращается. В JScript и VBScript функция является объектом, и ссылка на неё для таких целей не годится. Поэтому ссылка на скриптовую функцию сначала передаётся методу RegisterCallback, а API-функция получает возвращённый им указатель на одну из вспомогательных процедур внутри dynwrapx.dll, вызовы которой будут транслироваться в вызовы скриптовой функции, а возвращаемые значения — в обратном направлении. В JScript ссылка на функцию — это её имя без скобок, а в VBScript сначала нужно использовать GetRef. Кроме ссылки на функцию задаются также типы её параметров и возвращаемого значения — аналогично методу [URL='http://yuripopov.ucoz.net/index/dwx_register/0-12']Register[/URL] (но используются только маленькие буквы). Пример на [B]JScript[/B] (VBScript см. ниже): [code=JavaScript]DWX = new ActiveXObject("DynamicWrapperX"); DWX.Register("user32", "EnumWindows", "i=ph"); DWX.Register("user32", "GetWindowTextW", "i=hpl"); // Unicode //DWX.Register("user32", "GetWindowText", "i=hpl"); // ANSI // Регистрация CbkEnumWin как функции обратного вызова // и получение указателя. pCbkFunc = DWX.RegisterCallback(CbkEnumWin, "i=hh", "r=l"); n=0, m=0, WinList=""; Buf = DWX.MemAlloc(256); // Буфер под заголовок окна (выходная строка). // Вызов EnumWindows с передачей ей указателя на callback-функцию. DWX.EnumWindows(pCbkFunc, 0); DWX.MemFree(Buf); WScript.Echo("Всего окон: " + m + "\nС заголовками: " + n + "\n\n" + WinList); // ............... Собственно callback-функция .................... function CbkEnumWin(hwnd, lparam) { var Title; DWX.GetWindowTextW(hwnd, Buf, 128); // Unicode Title = DWX.StrGet(Buf, "w"); //DWX.GetWindowText(hwnd, Buf, 256); // ANSI //Title = DWX.StrGet(Buf, "s"); if(Title.length > 0) { WinList += hwnd + "\t" + Title + "\n"; ++n; } ++m; return 1; // Если вернуть 0, вызовы прекратятся. }[/code] Пример на [B]VBScript[/B]: [code=VB]Set DWX = CreateObject("DynamicWrapperX") DWX.Register "user32", "EnumWindows", "i=ph" DWX.Register "user32", "GetWindowTextW", "i=hpl" ' Unicode 'DWX.Register "user32", "GetWindowText", "i=hpl" ' ANSI Set Ref = GetRef("CbkEnumWin") ' Получение ссылки на функцию. ' Регистрация CbkEnumWin как функции обратного вызова ' и получение указателя. pCbkFunc = DWX.RegisterCallback(Ref, "i=hh", "r=l") n = 0 : m = 0 : WinList = "" Buf = DWX.MemAlloc(256) ' Буфер под заголовок окна (выходная строка). ' Вызов EnumWindows с передачей ей указателя на callback-функцию. DWX.EnumWindows pCbkFunc, 0 DWX.MemFree Buf WScript.Echo "Всего окон: " & m & vbCrLf & "С заголовками: " & n & _ vbCrLf & vbCrLf & WinList ' ................ Собственно callback-функция ....................... Function CbkEnumWin(hwnd, lparam) DWX.GetWindowTextW hwnd, Buf, 128 ' Unicode Title = DWX.StrGet(Buf, "w") 'DWX.GetWindowText hwnd, Buf, 256 ' ANSI 'Title = DWX.StrGet(Buf, "s") If Len(Title) > 0 Then WinList = WinList & hwnd & vbTab & Title & vbCrLf n = n+1 End If m = m+1 CbkEnumWin = 1 ' Если вернуть 0, вызовы прекратятся. End Function[/code] {/slide} {slide=Прочие методы|left} Параметры в квадратных скобках необязательны, но нельзя опускать такой параметр, если следующий за ним вы указываете. [B]NumGet( Address [, Offset] [, Type] ) [/B]— чтение числа из памяти. Address — базовый адрес. Offset — смещение от него (в байтах), положительное или отрицательное; по умолчанию 0. Type — тип числа: те же буквенные обозначения, что и для метода Register (см. список [URL='http://yuripopov.ucoz.net/index/dwx_types/0-14']здесь[/URL]), но используются только маленькие буквы; по умолчанию — [B]l[/B]. Считанное число помещается в возвращаемое методом значение. [B]NumPut( Var, Address [, Offset] [, Type] )[/B] — запись числа в память. Var — либо литеральное числовое значение, либо переменная, содержащая значение, которое нужно записать. Остальное — как в NumGet. Возвращаемое методом значение содержит адрес сразу за последним записанным байтом. В обоих методах выше Address может быть как числом, так и строкой, в последнем случае в качестве базового адреса используется указатель на эту строку. Это позволяет использовать строки в качестве буфера для данных, размещать там массивы, структуры и т.п. (о связанном с этим риске см. примечание к методу Space ниже). [B]StrPtr( Var [, Type/Codepage] ) [/B]— возвращает указатель на строку (на оригинал). Var — строковая переменная или константа. Type/Codepage — тип/кодировка. Возможные значения: [B]w[/B] (по умолчанию), [B]s[/B], [B]z[/B], либо явное указание кодировки — например, "cp1251". При значениях [B]s[/B], [B]z[/B] либо кодировке строка предварительно конвертируется на месте. Поддерживается кодировка "cp1201", т.е. UTF-16 Big Endian. Если результирующая строка длиннее исходной, она будет обрезана. Поскольку исходная строка в Юникоде, где каждый символ занимает два байта, места должно быть более чем достаточно в большинстве случаев. Возможно, какой-нибудь восточно-азиатский текст может быть длиннее в ANSI-кодировке или в UTF-8, чем он есть в UTF-16, но это только мои догадки. [B]StrGet( Address [, Type/Codepage] ) [/B]— чтение строки с указанного адреса. Возвращает копию строки. Address может быть как указателем в виде числа, так и строковой переменной. Type/Codepage — то же, что у StrPtr. Значения [B]s[/B] и [B]z[/B] нужны для чтения строки в ANSI— или OEM—кодировке по умолчанию. Строка при чтении конвертируется в Юникод. [B]StrPut( String, Address [, Type/Codepage] )[/B] — запись строки по указанному адресу. Type/Codepage — то же, что у двух методов выше. Строка при записи конвертируется в заданную кодировку. Возвращается адрес после нулевого терминатора строки. Если Address указан как 0, метод вернёт размер буфера в памяти, необходимый для записи строки в указанной кодировке, включая нулевой терминатор на конце строки. [B]Space( Count [, Char] ) [/B]— создание строки (BSTR) заданной длины. Возвращает строковую переменную. Count — число символов (двухбайтных). Char — символ, которым будет заполнена строка. По умолчанию строка заполняется пробелами — так же, как это делает функция Space в VBScript. Чтобы заполнить строку двоичными нулями, задайте Char как пустую строку (""). [U]NB[/U]: Метод Space был задуман для создания строк, используемых как буферы памяти — для чисел, структур, выходных строк. Но, как выяснилось на практике, такое использование строк в общем случае ненадёжно. Контроль над памятью, выделенной под строку, отдаётся скриптовому движку, и если он в процессе своей работы произведёт с ней какие-то манипуляции, помещённые в неё данные могут быть потеряны или испорчены. Поэтому я рекомендую для выделения памяти под буфер использовать метод MemAlloc (см. ниже). [B]ObjPtr( Object )[/B] — получение указателя на объект. [B]ObjGet( ObjPtr )[/B] — получение объекта по указателю на него. Если объект поддерживает интерфейс IDispatch, возвращается переменная типа VT_DISPATCH; если нет — VT_UNKNOWN. Счётчик ссылок объекта увеличивается на 1. [B]ArrPtr( Array ) [/B]— получение указателя на структуру SAFEARRAY массива. Не работает для массивов в JScript, т.к. это объекты. [B]VarPtr( Variable )[/B] — в языках, где переменные передаются в методы по ссылке, как в VBScript, можно получить указатель на структуру VARIANT переменной. [B]MemAlloc( Bytes [, ZeroMem] ) [/B]— выделение памяти. Если вторым аргументом указать 1, память будет обнулена. Возвращается указатель на выделенную память. [B]MemFree( MemPtr ) [/B]— освобождение ранее выделенной памяти. [B]Bitness() [/B]— определение битности объекта DynamicWrapperX (и, тем самым, битности процесса, его использующего). Возвращает число 32 или 64. [B]Version( [Field] )[/B] — возвращает указанное поле/поля из полного номера версии DynamicWrapperX. Задайте параметру Field значение согласно приведённой ниже таблице. Если Field опущен, это равносильно 0. Пример для версии 2.5.7.10. 0 — полная версия как строка: "2.5.7.10" 1 — старший номер версии: 2 2 — младший номер версии: 5 3 — номер сборки: 7 4 — номер ревизии: 10 (0xA) 5 — старший + младший номер версии: 0x20005 6 — номер сборки + ревизии: 0x7000A 7 — полный номер версии: 0x200050007000A Как вы можете видеть, каждое поле является 16-битным целым и занимает 2 байта. {/slide} {slide=Типы параметров и возвращаемых значений|left} [SIZE=4][B]Типы входных параметров и возвращаемых значений[/B][/SIZE] [B]m[/B] — знаковое целое 64 бита — INT64, LONGLONG, ... [B]q[/B] — беззнаковое целое 64 бита — UINT64, ULONGLONG, ... [B]l[/B] — знаковое целое 32 бита — LONG, INT, LRESULT, BOOL, ... [B]u[/B] — беззнаковое целое 32 бита — ULONG, UINT, DWORD, ... [B]h[/B] — хэндл, дескриптор — HANDLE, HWND, HMODULE, HINSTANCE, HICON, ... — 32 бита (x86) или 64 бита (x64) [B]p[/B] — указатель, для чисел то же, что u (x86) или q (x64), но также можно использовать для передачи объекта (IDispatch *) и строки. [B]n[/B] — знаковое целое 16 бит — SHORT [B]t[/B] — беззнаковое целое 16 бит — USHORT, WORD, WCHAR, OLECHAR, ... [B]c[/B] — знаковое целое 8 бит — CHAR [B]b[/B] — беззнаковое целое 8 бит — UCHAR, BYTE, ... [B]f[/B] — дробное число одинарной точности (32 бита) — FLOAT [B]d[/B] — дробное число двойной точности (64 бита) — DOUBLE [B]w[/B] — строка в Юникоде — BSTR, LPWSTR, LPOLESTR, OLECHAR *, WCHAR *, ... [B]s[/B] — строка в кодировке ANSI/Windows по умолчанию — LPSTR, LPCSTR, CHAR *, ... [B]z[/B] — строка в кодировке OEM/DOS по умолчанию — LPSTR, LPCSTR, CHAR *, ... [B]v[/B] — указатель на структуру VARIANT Примечания [LIST] [*]Подробнее о строковых типах см. [URL='http://yuripopov.ucoz.net/index/dwx_strings/0-18']здесь[/URL]. [*]Кроме хэндлов и указателей, есть и другие типы, меняющие свою битность с битностью процесса. Например, LPARAM, WPARAM, SIZE_T. Для них также лучше использовать тип h или p, чтобы код скрипта корректно работал при его выполнении как 32-, так и 64-битным интерпретатором. [*]Типам [B]m[/B] и [B]q[/B] (а также [B]h[/B] и [B]p[/B] в x64) в скриптах соответствовали бы типы VT_I8 и VT_UI8. Движками JScript и VBScript эти типы не поддерживаются, что ограничивает возможности работы с 64-битными целыми. Пока значение возвращаемого функцией числа это позволяет, DWX преобразует его к типам VT_I4 (знаковое целое 32 бита) либо VT_R8 (дробное число двойной точности). Поскольку мантисса VT_R8 имеет только 53 бита, этот тип не может отобразить все числа в диапазоне 64-битного целого. В таком случае возвращается тип VT_I8 или VT_UI8. Всё, что можно с ними сделать в скрипте, — передать как аргумент в какой-то другой метод или вывести значение числа в WScript.Echo либо MsgBox. Никакие расчёты с ними невозможны. [*]Когда большое целое возвращается как VT_R8 и вы хотите посмотреть его значение в диалоговом окне, оно может отображаться неточно из-за ограничения на число знаков после запятой в строковом представлении дробного числа. Поэтому, например, число 9223372036854775808 может отобразиться как 9,22337203685478E+18 вместо 9,223372036854775808E+18. Однако само число в переменной не округляется и остаётся точным. [*]Если значение 64-битного целого не укладывается ни в один из доступных числовых типов, можно указать его в виде строки, десятичной или шестнадцатеричной (с префиксом 0x). [/LIST] [code] DWX.Register("lib.dll", "func", "i=m") DWX.func("0xFFFFFFFFFFFFFFFF") DWX.func("-0x7FFFFFFFFFFFFFFF") DWX.func("18446744073709551615") DWX.func("-9223372036854775807")[/code] [SIZE=4][B]Выходные параметры[/B][/SIZE] [B]M[/B] — указатель на число (его адрес в памяти) — LONGLONG *, PLONGLONG и т.п. [B]Q[/B] — то же — ULONGLONG *, PULONGLONG, ... [B]L[/B] — то же — LONG *, LPLONG, ... [B]H[/B] — то же — HANDLE *, PHANDLE, LPHANDLE, ... [B]U[/B] — то же — ULONG *, LPDWORD, ... [B]P[/B] — то же [B]N[/B] — то же — SHORT * [B]T[/B] — то же — USHORT *, LPWORD, WCHAR *, OLECHAR *, ... [B]C[/B] — то же — CHAR *, ... [B]B[/B] — то же — UCHAR *, LPBYTE, ... [B]F[/B] — то же — FLOAT *, PFLOAT [B]D[/B] — то же — DOUBLE *, PDOUBLE [B]W[/B] — выходная строка в Юникоде [B]S[/B] — выходная строка в ANSI [B]Z[/B] — выходная строка в OEM Примечания [LIST] [*]Использование выходных типов для чисел имеет смысл для скриптовых движков, которые передают переменные в метод по ссылке, как это делает VBScript. В этом случае DWX может передать функции указатель на значение переменной, которое функция может изменить. В движках, где аргументы передаются по значению, как в JScript, методу передаётся копия числа, поэтому изменить оригинал нет возможности. В этом случае решением будет выделение нужного количества памяти, например, методом MemAlloc, передача функции указателя на эту память (используя тип [B]p[/B]) и затем, после вызова функции, считывание помещённого ею туда числа методом NumGet. [*]Некоторые движки копируют строки при передаче их в метод; в этом случае использование выходных типов для строк также теряет смысл. Решение аналогично: выделение памяти, передача указателя на неё типом [B]p[/B] и затем считывание оттуда строки методом StrGet. [/LIST] {/slide} {slide=Подробнее о строках|left} [CENTER][SIZE=4][B]Строки[/B][/SIZE][/CENTER] В JScript и VBScript используются строки типа BSTR. Это строка в Юникоде, т.е. код каждого символа занимает 2 байта. За последним символом расположен ограничитель - 2 нулевых байта. Кроме того, перед первым символом находится 4-байтное число, содержащее длину строки в байтах (без учёта нулевых на конце). Указатель, содержащийся в скриптовых строковых переменных, является адресом первого символа такой строки (т.е. байты, содержащие длину строки, как бы остаются за кадром). Передать строку можно тремя способами: [LIST] [*]Входная строка: [B]w[/B], [B]s[/B], [B]z[/B]. Для типов [B]s[/B] и [B]z[/B] строка копируется с конвертацией в соответствующую кодировку, и API-функция получает указатель на эту копию. После завершения работы функции память, запрошенная под копию строки, освобождается, т.е. эта копия перестаёт существовать. В случае [B]w[/B] функции передаётся указатель на оригинал строки. [*]Выходная строка: [B]W[/B], [B]S[/B], [B]Z[/B]. Передаётся указатель на оригинал строки, но [B]S[/B] и [B]Z[/B] предварительно конвертируются (на месте). После завершения функции строки [B]S[/B] и [B]Z[/B]конвертируются обратно в Юникод, у них измеряется длина, а у строки [B]W[/B] только измеряется длина. Длина (в байтах) записывается перед строкой. Без этой последней операции потом в скрипте будут глюки, например, при конкатенации этой строки с другими. [*]Указатель: [B]p[/B]. Это самый простой способ. Передаётся указатель на оригинал строки, без конвертации. После завершения функции нет ни конвертации, ни корректировки длины. Так что если функция туда что-то запишет, оно там будет в нетронутом виде. Здесь строка фактически является просто буфером в памяти для хранения любых данных. Может показаться, что это то же самое, что [B]w[/B], но это не так. Разница в том, что параметр, объявленный как [B]p[/B], принимает не только строковые переменные, но и числовые. [/LIST] Вернуть строку можно также по-разному: [LIST] [*][B]p[/B] — получаем числовую переменную, содержащую указатель на строку, которую вернула функция. [*][B]w[/B], [B]s[/B] или [B]z[/B] — получаем строковую переменную, содержащую указатель на копию этой строки. Строки [B]s[/B] и [B]z[/B] копируются с конвертацией в Юникод. Оригинал строки не освобождается, т.к. DWX не может знать, каким способом была выделена под неё память. Если для вас это имеет значение, то возвращайте строку типом [B]p[/B], копируйте её в переменную методом StrGet и затем освобождайте исходную строку тем способом, какой рекомендован в описании вызываемой функции. [/LIST] Вызовы API, принимающие строковые аргументы, как правило, представлены в двух вариантах - например, MessageBoxA и MessageBoxW. Использование в скриптах юникодовских вариантов, с окончанием W, представляется более логичным, т.к. при этом нет дополнительных перекодировок строк туда и обратно. Выходная строка, как и прочие выходные параметры, предназначена для того, чтобы функция API в неё что-нибудь записала, так что её длина должна быть соответствующей. Использование строк как буферов памяти может работать или нет в зависимости от того, как внутри скриптового движка реализована работа со строками. Предпочтительнее выделять память методом MemAlloc, т.к. она будет под вашим полным контролем. {/slide} [/accordion] [CENTER][B][COLOR=blue]Краткое описание[/COLOR][/B][/CENTER] Ранее у VBS / JS не было возможностей для вызова API-функций. Так было до тех пор, пока [B]Юрий Попов[/B] не написал замечательную библиотеку [B]DynamicWrapperX[/B]. Библиотеку [COLOR=#0000ff]нужно зарегистрировать[/COLOR]: 1) в системе (нужны права администратора) [code]regsvr32 "<путь-к-компоненту>\dynwrapx.dll"[/code] 2) или в контексте текущего пользователя [code]regsvr32 /i "<путь-к-компоненту>\dynwrapx.dll"[/code] Затем можно воспользоваться всеми прелестями вызова API из .VBS / .JS. [COLOR=#0000ff]Пример вызова.[/COLOR] [B]API из JS:[/B] [code=JavaScript]DWX = new ActiveXObject("DynamicWrapperX"); DWX.Register("user32.dll", "MessageBoxW", "i=hwwu", "r=l"); res = DWX.MessageBoxW(0, "Hello, world!", "Test", 4); // Вызов.[/code] [B]API из VBS[/B] [code=VB]set DWX = CreateObject("DynamicWrapperX") DWX.Register "user32.dll", "MessageBoxW", "i=hwwu", "r=l" res = DWX.MessageBoxW(0, "Hello, world!", "Test", 4) ' Вызов.[/code] [COLOR=#0000ff] [B]Библиотеку можно скачать:[/B] [/COLOR] 1) [URL='http://yuripopov.ucoz.net/index/dynwrapx/0-11']на сайте автора[/URL] 2) или [B]под этим постом[/B] вместе с батником [B]авторегистрации[/B] и примером сворачивания / разворачивания "Калькулятора Windows" [spoiler=О батнике подробнее...] [B]Батник для регистрации DynamicWrapperX 2.0 (x32, x64) и вызова функций из 32/64-битных библиотек.[/B] В комплект уже включена [URL='http://yuripopov.ucoz.net/index/dynwrapx/0-11']DynamicWrapperX[/URL] ver.2.0.0.1, а также демо-VBS, показывающий как свернуть и развернуть "Калькулятор Windows" с помощью API-функций. [B]FindWindow.vbs[/B] - демо-проект (если библиотека не будет зарегистрирована, то сам вызовет regdynwrapx.bat и перезапустится) [B]regdynwrapx.bat[/B] - чтобы зарегистрировать [B]unregdynwrapx.bat[/B] - чтобы снять регистрацию. Скрипт сам запрашивает права Администратора, если понадобится. Если Вы хотите вызывать функции из своей [B]32-битной[/B] библиотеки (независимо от битности ОС), раскомментируйте участок кода FindWindow.vbs в строках №№ 16-24. Если появится новая версия библиотеки DynamicWrapperX, ее папки "32" и "64" нужно скопировать в папку "dynwrapx", заменив оригинал. [/spoiler] _____________________________ Об основах API здесь я вести речь не буду. Тот, кто ни разу ними не пользовался, с нуля вникать будет тяжело. Но можно будет воспользоваться чужими примерами реализаций простых задач. На функциях API основана работа самой ОС. Используя их, Вы получаете практически неограниченные возможности. [B][COLOR=#ff0000]Тема закрыта и дополняется. Просьба вопросы задавать в новых темах.[/COLOR][/B] [/QUOTE]
Вставить цитаты...
Проверка
Ответить
Форумы
Форум программистов
Visual Basic 6 / Сценарии VBScript, JScript
Банк полезных кодов
Вызов API-функций из VBScript / JScript (DynamicWrapperX)
Сверху
Снизу