Вызов API-функций из VBScript / JScript (DynamicWrapperX)

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,133
Реакции
5,908
Баллы
648
Подробности с сайта автора

[accordion=bcenter|80%]
{slide=О библиотеке DynamicWrapperX|left}
Автор: Юрий Попов (YMP на script-coding.com форуме).
Условия распространения библиотеки: freeware.

DynamicWrapperX - это компонент ActiveX, который вы можете использовать в скриптах (JScript, VBScript и т.п.) для вызова:
  • функций из библиотек DLL (в частности функций Windows API);
  • вообще любых функций, адрес которых в памяти вам известен;
  • функций, чей машинный код (в виде хекс-строки) у вас имеется.
Компонент написан с нуля на языке ассемблера GoAsm как попытка более полной реализации идеи DynamicWrapper.

Другие возможности:
  • обратный вызов (callback) скриптовой функции из вызванной вами внешней функции;
  • прямой доступ к памяти (чтение и запись числа по адресу);
  • выделение и освобождение памяти;
  • чтение и запись строк в произвольной кодировке;
  • получение указателя на строку, объект, массив, переменную;
  • получение объекта по указателю на него;
  • определение битности (32 или 64) процесса, в котором выполняется скрипт.
{/slide}

{slide=Регистрация в системе (установка)|left}
Есть два способа регистрации:
Код:
  regsvr32.exe <путь-к-компоненту>\dynwrapx.dll — для всех пользователей.
  regsvr32.exe /i <путь-к-компоненту>\dynwrapx.dll — для текущего пользователя.
Регистрация для текущего пользователя не требует прав администратора, но имеет ограничения:
  • в Windows 98 не работает;
  • в Windows Vista, 7 и 8 при включенном UAC объект будет недоступен приложениям, запущенным с правами администратора.
В 64-битной ОС нужно регистрировать оба варианта DLL: x86 и x64, чтобы объект был доступен как 64-, так и 32-битным приложениям.

Примечание для пользователей 1-й версии. Если в системе уже установлена 1-я версия DWX, 2-я зарегистрируется параллельно с ней. В этом случае она будет доступна в скриптах только по имени DynamicWrapperX.2. Чтобы заменить старую версию новой, нужно сначала разрегистрировать старую. В этом случае новая версия будет доступна также и под общим именем DynamicWrapperX.

Разрегистрация компонента:
Код:
  regsvr32.exe /u <путь-к-компоненту>\dynwrapx.dll — для всех пользователей.
  regsvr32.exe /u /i <путь-к-компоненту>\dynwrapx.dll — для текущего пользователя.
Если 2-я версия была установлена параллельно с 1-й, её разрегистрация никак не затронет регистрацию 1-й (и наоборот).
{/slide}

{slide=Метод Register - регистрация API перед ее вызовом|left}
Этот метод регистрирует функцию из DLL в качестве метода объекта. Функция задаётся именем или ординалом. Значение аргументов "i=", "r=" и "f=" см. в примечаниях.

Регистрация по имени
Код:
  DWX = new ActiveXObject("DynamicWrapperX");
  DWX.Register("user32.dll", "MessageBoxW", "i=hwwu", "r=l");
  res = DWX.MessageBoxW(0, "Hello, world!", "Test", 4); // Вызов.
Регистрация по имени с заменой его на другое
Код:
  DWX.Register("user32:BadName", "GoodName", "r=n", "f=t");
  // BadName — имя функции, например, содержащее символы,
  // недопустимые в именах методов, или просто очень длинное.
Регистрация по ординалу
Код:
  DWX.Register("user32:110", "MethodName", "i=p", "r=l");
  DWX.Register("user32:0x6E", "MethodName", "i=p", "r=l");
Примечания
  • Если файл библиотеки имеет расширение dll, его можно не указывать. Если файл не имеет расширения, имя должно быть указано с точкой на конце: "mylib."
  • Для системных DLL путь указывать не нужно. Для сторонних зависит от того, где они находятся.
  • Функции Windows API, принимающие или возвращающие строки, часто имеют два варианта: например, MessageBoxW для строк в Юникоде и MessageBoxA для строк в ANSI-кодировке. Букву "А" на конце можно не добавлять, DWX сделает это сам, если не найдёт функцию MessageBox, но имена юникодных функций должны указываться точно, c "W" на конце.
  • Ординал можно задавать десятичным или шестнадцатеричным числом. Учтите, что ординал функции может быть разным в разных версиях библиотеки и в x86 и x64 вариантах одной и той же версии.
  • Наличие аргументов "i=", "r=" и "f=" зависит от функции. Порядок их произвольный, т.к. они опознаются по префиксам.
  • "i=" задаёт тип каждого из параметров функции (целое число, дробное, строка и т.п.). Может опускаться только, если функция не имеет параметров. Расшифровка буквенных обозначений здесь.
  • "r=" — тип возвращаемого значения. Можно не указывать, если возвращаемое значение не нужно, даже если функция что-то возвращает.
  • "f=" — флаги, влияющие на то, как будет вызываться функция. На данный момент имеет одно возможное значение "t" (соглашение вызова thiscall). Имеет смысл только для 32-битного DWX и только со 2-й версии. 64-битным и 1-й версией игнорируется.
{/slide}

{slide=Метод RegisterAddr - регистрирует функцию по её адресу в памяти|left}
Этот метод регистрирует функцию по её адресу в памяти. Остальные параметры те же, что у метода Register.
Код:
DWX.RegisterAddr(Address, "FuncName", "i=hwwu", "r=l");
{/slide}

{slide=Метод RegisterCode - ассемблерная вставка|left}
Метод принимает в первом аргументе машинный код функции, представленный в виде хекс-строки. Остальные параметры те же, что у метода Register.
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));
Примечания
  • Под код выделяется память, и он записывается туда уже в бинарном виде. После чего его можно вызывать по присвоенному ему во втором аргументе имени. Возвращаемое значение содержит адрес кода в памяти. Машинный код для 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"

    Но учтите, что в этом случае каждая строка, кроме последней, должна иметь на конце перевод строки, т.к. он используется как признак конца комментария.
{/slide}


{slide=Метод RegisterCallback|left}
Этот метод нужен для получения указателя на скриптовую функцию, пригодного для передачи какой-либо функции API. Которая потом, используя этот указатель, могла бы данную скриптовую функцию вызывать. Пример такой API-функции — EnumWindows (см. код ниже). Она перебирает существующие окна и хэндл каждого окна передаёт callback-функции в качестве параметра. После этого она ждёт, что вернёт callback-функция. Если 1, то перебор идёт дальше, если 0 — прекращается.

В JScript и VBScript функция является объектом, и ссылка на неё для таких целей не годится. Поэтому ссылка на скриптовую функцию сначала передаётся методу RegisterCallback, а API-функция получает возвращённый им указатель на одну из вспомогательных процедур внутри dynwrapx.dll, вызовы которой будут транслироваться в вызовы скриптовой функции, а возвращаемые значения — в обратном направлении.

В JScript ссылка на функцию — это её имя без скобок, а в VBScript сначала нужно использовать GetRef. Кроме ссылки на функцию задаются также типы её параметров и возвращаемого значения — аналогично методу Register (но используются только маленькие буквы).

Пример на JScript (VBScript см. ниже):
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, вызовы прекратятся.
}

Пример на VBScript:
Код:
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
{/slide}
{slide=Прочие методы|left}
Параметры в квадратных скобках необязательны, но нельзя опускать такой параметр, если следующий за ним вы указываете.

NumGet( Address [, Offset] [, Type] ) — чтение числа из памяти. Address — базовый адрес. Offset — смещение от него (в байтах), положительное или отрицательное; по умолчанию 0. Type — тип числа: те же буквенные обозначения, что и для метода Register (см. список здесь), но используются только маленькие буквы; по умолчанию — l. Считанное число помещается в возвращаемое методом значение.

NumPut( Var, Address [, Offset] [, Type] ) — запись числа в память. Var — либо литеральное числовое значение, либо переменная, содержащая значение, которое нужно записать. Остальное — как в NumGet. Возвращаемое методом значение содержит адрес сразу за последним записанным байтом.

В обоих методах выше Address может быть как числом, так и строкой, в последнем случае в качестве базового адреса используется указатель на эту строку. Это позволяет использовать строки в качестве буфера для данных, размещать там массивы, структуры и т.п. (о связанном с этим риске см. примечание к методу Space ниже).

StrPtr( Var [, Type/Codepage] ) — возвращает указатель на строку (на оригинал). Var — строковая переменная или константа. Type/Codepage — тип/кодировка. Возможные значения: w (по умолчанию), s, z, либо явное указание кодировки — например, "cp1251". При значениях s, z либо кодировке строка предварительно конвертируется на месте. Поддерживается кодировка "cp1201", т.е. UTF-16 Big Endian.

Если результирующая строка длиннее исходной, она будет обрезана. Поскольку исходная строка в Юникоде, где каждый символ занимает два байта, места должно быть более чем достаточно в большинстве случаев. Возможно, какой-нибудь восточно-азиатский текст может быть длиннее в ANSI-кодировке или в UTF-8, чем он есть в UTF-16, но это только мои догадки.

StrGet( Address [, Type/Codepage] ) — чтение строки с указанного адреса. Возвращает копию строки. Address может быть как указателем в виде числа, так и строковой переменной. Type/Codepage — то же, что у StrPtr. Значения s и z нужны для чтения строки в ANSI— или OEM—кодировке по умолчанию. Строка при чтении конвертируется в Юникод.

StrPut( String, Address [, Type/Codepage] ) — запись строки по указанному адресу. Type/Codepage — то же, что у двух методов выше. Строка при записи конвертируется в заданную кодировку. Возвращается адрес после нулевого терминатора строки. Если Address указан как 0, метод вернёт размер буфера в памяти, необходимый для записи строки в указанной кодировке, включая нулевой терминатор на конце строки.

Space( Count [, Char] ) — создание строки (BSTR) заданной длины. Возвращает строковую переменную. Count — число символов (двухбайтных). Char — символ, которым будет заполнена строка. По умолчанию строка заполняется пробелами — так же, как это делает функция Space в VBScript. Чтобы заполнить строку двоичными нулями, задайте Char как пустую строку ("").

NB: Метод Space был задуман для создания строк, используемых как буферы памяти — для чисел, структур, выходных строк. Но, как выяснилось на практике, такое использование строк в общем случае ненадёжно. Контроль над памятью, выделенной под строку, отдаётся скриптовому движку, и если он в процессе своей работы произведёт с ней какие-то манипуляции, помещённые в неё данные могут быть потеряны или испорчены. Поэтому я рекомендую для выделения памяти под буфер использовать метод MemAlloc (см. ниже).

ObjPtr( Object ) — получение указателя на объект.

ObjGet( ObjPtr ) — получение объекта по указателю на него. Если объект поддерживает интерфейс IDispatch, возвращается переменная типа VT_DISPATCH; если нет — VT_UNKNOWN. Счётчик ссылок объекта увеличивается на 1.

ArrPtr( Array ) — получение указателя на структуру SAFEARRAY массива. Не работает для массивов в JScript, т.к. это объекты.

VarPtr( Variable ) — в языках, где переменные передаются в методы по ссылке, как в VBScript, можно получить указатель на структуру VARIANT переменной.

MemAlloc( Bytes [, ZeroMem] ) — выделение памяти. Если вторым аргументом указать 1, память будет обнулена. Возвращается указатель на выделенную память.

MemFree( MemPtr ) — освобождение ранее выделенной памяти.

Bitness() — определение битности объекта DynamicWrapperX (и, тем самым, битности процесса, его использующего). Возвращает число 32 или 64.

Version( [Field] ) — возвращает указанное поле/поля из полного номера версии 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}
Типы входных параметров и возвращаемых значений
m — знаковое целое 64 бита — INT64, LONGLONG, ...
q — беззнаковое целое 64 бита — UINT64, ULONGLONG, ...
l — знаковое целое 32 бита — LONG, INT, LRESULT, BOOL, ...
u — беззнаковое целое 32 бита — ULONG, UINT, DWORD, ...
h — хэндл, дескриптор — HANDLE, HWND, HMODULE, HINSTANCE, HICON, ... — 32 бита (x86) или 64 бита (x64)
p — указатель, для чисел то же, что u (x86) или q (x64), но также можно использовать для передачи объекта (IDispatch *) и строки.
n — знаковое целое 16 бит — SHORT
t — беззнаковое целое 16 бит — USHORT, WORD, WCHAR, OLECHAR, ...
c — знаковое целое 8 бит — CHAR
b — беззнаковое целое 8 бит — UCHAR, BYTE, ...
f — дробное число одинарной точности (32 бита) — FLOAT
d — дробное число двойной точности (64 бита) — DOUBLE
w — строка в Юникоде — BSTR, LPWSTR, LPOLESTR, OLECHAR *, WCHAR *, ...
s — строка в кодировке ANSI/Windows по умолчанию — LPSTR, LPCSTR, CHAR *, ...
z — строка в кодировке OEM/DOS по умолчанию — LPSTR, LPCSTR, CHAR *, ...
v — указатель на структуру VARIANT

Примечания
  • Подробнее о строковых типах см. здесь.
  • Кроме хэндлов и указателей, есть и другие типы, меняющие свою битность с битностью процесса. Например, LPARAM, WPARAM, SIZE_T. Для них также лучше использовать тип h или p, чтобы код скрипта корректно работал при его выполнении как 32-, так и 64-битным интерпретатором.
  • Типам m и q (а также h и p в 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).
Код:
  DWX.Register("lib.dll", "func", "i=m")
  DWX.func("0xFFFFFFFFFFFFFFFF")
  DWX.func("-0x7FFFFFFFFFFFFFFF")
  DWX.func("18446744073709551615")
  DWX.func("-9223372036854775807")
Выходные параметры
M — указатель на число (его адрес в памяти) — LONGLONG *, PLONGLONG и т.п.
Q — то же — ULONGLONG *, PULONGLONG, ...
L — то же — LONG *, LPLONG, ...
H — то же — HANDLE *, PHANDLE, LPHANDLE, ...
U — то же — ULONG *, LPDWORD, ...
P — то же
N — то же — SHORT *
T — то же — USHORT *, LPWORD, WCHAR *, OLECHAR *, ...
C — то же — CHAR *, ...
B — то же — UCHAR *, LPBYTE, ...
F — то же — FLOAT *, PFLOAT
D — то же — DOUBLE *, PDOUBLE
W — выходная строка в Юникоде
S — выходная строка в ANSI
Z — выходная строка в OEM

Примечания
  • Использование выходных типов для чисел имеет смысл для скриптовых движков, которые передают переменные в метод по ссылке, как это делает VBScript. В этом случае DWX может передать функции указатель на значение переменной, которое функция может изменить. В движках, где аргументы передаются по значению, как в JScript, методу передаётся копия числа, поэтому изменить оригинал нет возможности. В этом случае решением будет выделение нужного количества памяти, например, методом MemAlloc, передача функции указателя на эту память (используя тип p) и затем, после вызова функции, считывание помещённого ею туда числа методом NumGet.
  • Некоторые движки копируют строки при передаче их в метод; в этом случае использование выходных типов для строк также теряет смысл. Решение аналогично: выделение памяти, передача указателя на неё типом p и затем считывание оттуда строки методом StrGet.
{/slide}
{slide=Подробнее о строках|left}
Строки

В JScript и VBScript используются строки типа BSTR. Это строка в Юникоде, т.е. код каждого символа занимает 2 байта. За последним символом расположен ограничитель - 2 нулевых байта. Кроме того, перед первым символом находится 4-байтное число, содержащее длину строки в байтах (без учёта нулевых на конце). Указатель, содержащийся в скриптовых строковых переменных, является адресом первого символа такой строки (т.е. байты, содержащие длину строки, как бы остаются за кадром).

Передать строку можно тремя способами:
  • Входная строка: w, s, z. Для типов s и z строка копируется с конвертацией в соответствующую кодировку, и API-функция получает указатель на эту копию. После завершения работы функции память, запрошенная под копию строки, освобождается, т.е. эта копия перестаёт существовать. В случае w функции передаётся указатель на оригинал строки.
  • Выходная строка: W, S, Z. Передаётся указатель на оригинал строки, но S и Z предварительно конвертируются (на месте). После завершения функции строки S и Zконвертируются обратно в Юникод, у них измеряется длина, а у строки W только измеряется длина. Длина (в байтах) записывается перед строкой. Без этой последней операции потом в скрипте будут глюки, например, при конкатенации этой строки с другими.
  • Указатель: p. Это самый простой способ. Передаётся указатель на оригинал строки, без конвертации. После завершения функции нет ни конвертации, ни корректировки длины. Так что если функция туда что-то запишет, оно там будет в нетронутом виде. Здесь строка фактически является просто буфером в памяти для хранения любых данных.

    Может показаться, что это то же самое, что w, но это не так. Разница в том, что параметр, объявленный как p, принимает не только строковые переменные, но и числовые.

Вернуть строку можно также по-разному:
  • p — получаем числовую переменную, содержащую указатель на строку, которую вернула функция.
  • w, s или z — получаем строковую переменную, содержащую указатель на копию этой строки. Строки s и z копируются с конвертацией в Юникод.

    Оригинал строки не освобождается, т.к. DWX не может знать, каким способом была выделена под неё память. Если для вас это имеет значение, то возвращайте строку типом p, копируйте её в переменную методом StrGet и затем освобождайте исходную строку тем способом, какой рекомендован в описании вызываемой функции.

Вызовы API, принимающие строковые аргументы, как правило, представлены в двух вариантах - например, MessageBoxA и MessageBoxW. Использование в скриптах юникодовских вариантов, с окончанием W, представляется более логичным, т.к. при этом нет дополнительных перекодировок строк туда и обратно.

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

Использование строк как буферов памяти может работать или нет в зависимости от того, как внутри скриптового движка реализована работа со строками. Предпочтительнее выделять память методом MemAlloc, т.к. она будет под вашим полным контролем.
{/slide}
[/accordion]
Краткое описание

Ранее у VBS / JS не было возможностей для вызова API-функций.
Так было до тех пор, пока Юрий Попов не написал замечательную библиотеку DynamicWrapperX.

Библиотеку нужно зарегистрировать:
1) в системе (нужны права администратора)
Код:
regsvr32 "<путь-к-компоненту>\dynwrapx.dll"
2) или в контексте текущего пользователя
Код:
regsvr32 /i "<путь-к-компоненту>\dynwrapx.dll"
Затем можно воспользоваться всеми прелестями вызова API из .VBS / .JS.

Пример вызова.

API из JS:
JavaScript:
DWX = new ActiveXObject("DynamicWrapperX");
DWX.Register("user32.dll", "MessageBoxW", "i=hwwu", "r=l");
res = DWX.MessageBoxW(0, "Hello, world!", "Test", 4); // Вызов.
API из VBS
Код:
set DWX = CreateObject("DynamicWrapperX")
DWX.Register "user32.dll", "MessageBoxW", "i=hwwu", "r=l"
res = DWX.MessageBoxW(0, "Hello, world!", "Test", 4) ' Вызов.

Библиотеку можно скачать:

1) на сайте автора
2) или под этим постом вместе с батником авторегистрации и примером сворачивания / разворачивания "Калькулятора Windows"
Батник для регистрации DynamicWrapperX 2.0 (x32, x64) и вызова функций из 32/64-битных библиотек.

В комплект уже включена DynamicWrapperX ver.2.0.0.1,
а также демо-VBS, показывающий как свернуть и развернуть "Калькулятор Windows" с помощью API-функций.

FindWindow.vbs - демо-проект (если библиотека не будет зарегистрирована, то сам вызовет regdynwrapx.bat и перезапустится)
regdynwrapx.bat - чтобы зарегистрировать
unregdynwrapx.bat - чтобы снять регистрацию.

Скрипт сам запрашивает права Администратора, если понадобится.
Если Вы хотите вызывать функции из своей 32-битной библиотеки (независимо от битности ОС), раскомментируйте участок кода FindWindow.vbs в строках №№ 16-24.

Если появится новая версия библиотеки DynamicWrapperX, ее папки "32" и "64" нужно скопировать в папку "dynwrapx", заменив оригинал.
_____________________________

Об основах API здесь я вести речь не буду.
Тот, кто ни разу ними не пользовался, с нуля вникать будет тяжело.
Но можно будет воспользоваться чужими примерами реализаций простых задач.

На функциях API основана работа самой ОС.
Используя их, Вы получаете практически неограниченные возможности.

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

Вложения

Последнее редактирование:
Сверху Снизу