1

Тема: VBScript: Вызов API в VBScript

Подскажите пожалуйста, как можно вызвать API функции в VB скриптах? гугль мне выдал такой вариант


Dim User32
Set User32 = XNHost.LoadDll( "user32.dll" )

Dim hWnd
hWnd = User32.GetForegroundWindow

Dim Caption
Set Caption = XNHost.Struct
Caption.Add "buffer" , "t", 1024

User32.GetWindowText hWnd, Caption, 1023

MsgBox Caption.buffer,0, "Foreground Window Caption"

Но при запуске выдаёт ошибку что нужно сначало создать объект XNHost, но у меня такого ActiveX нету, можно ещё как нибудь вызвать? если нет то где взять XNHost?

2

Re: VBScript: Вызов API в VBScript

Библиотека dynwrapx.dll и вызов функций Win 32 API
JScript/VBScript & Win32 API: DynamicWrapperX
JScript/VBScript & Win32: расширение возможностей DynamicWrapperX

3

Re: VBScript: Вызов API в VBScript

Спасибо, а других вариантов больше нет?

4 (изменено: SergeyA, 2012-02-12 23:30:03)

Re: VBScript: Вызов API в VBScript

Я решил использовать dynwrapx.dll, прочитал инфу по её работе, но сразу возникла проблема, как правильно вызвать функцию CreateWindowEx


'Set oShell = CreateObject("Wscript.Shell") 
'oShell.Run "RegSvr32 /s " & chr(34) & "\dynwrapx.dll" & chr(34) 

Set WinAPI = CreateObject("DynamicWrapperX")                    ' Создание объекта.
WinAPI.Register "user32.dll", "MessageBoxW", "i=hwwu", "r=l"    ' Регистрация функции из dll.
res = WinAPI.MessageBoxW(0, "Hello, world!", "Test", 4)         ' Вызов.


GUICreate()


Function GUICreate()
  WinAPI.Register "user32.dll", "CreateWindowExA",  _
                  "i=dwExStyle", "s=ClassName", "s=WindowName", _
                  "i=dwStyle", "i=X", "i=Y", "i=nWidth", "i=nHeight", _
                  "h=hWndParent", "h=hMenu", "h=hInstance", "i=lpParam"

  WinAPI.CreateWindowExA(0, "Window", "Test", 0, 20, 20, 300, 400, 0, 0, 0, 0, 0)
End Function

Я только первые 2 часа изучаю VBScript, так что сильно не ругайтесь..:)

5 (изменено: YMP, 2012-02-13 08:32:05)

Re: VBScript: Вызов API в VBScript

Создать окно через WinAPI можно, но имеет ли это смысл? Что потом делать будете с этим окном? Обрабатывать его сообщения? Сам скрипт придётся зациклить, чтобы он не завершался после создания окна, а все действия выполнять в обработке оконных сообщений.

Вообще, существует ведь ActiveX для работы с окнами, называется WindowSystemObject. Поищите, возможно, это то что нужно для ваших целей.

Что касается Dynwrapx, то вот пример, создающий окно. Работает вроде.

Set WinAPI = CreateObject("DynamicWrapperX")

IDI_APPLICATION = 32512
IDC_ARROW = 32512
COLOR_WINDOW = 5
CS_VREDRAW =  1
CS_HREDRAW =  2
ClsStyle = CS_VREDRAW or CS_HREDRAW
WS_OVERLAPPEDWINDOW = &HCF0000
WS_VISIBLE = &H10000000
WndStyle = WS_OVERLAPPEDWINDOW or WS_VISIBLE
WM_CLOSE = &H10     ' Сообщение, что юзер закрыл окно.
szClass = "TestWindowClass"
szTitle = "TestWindow"
wc = WinAPI.Space(24, "")   ' WNDCLASSEX, структура класса окна.

With WinAPI
    .Register "kernel32", "GetModuleHandleW", "i=p", "r=h"
    .Register "user32", "LoadIconW", "i=hl", "r=h"
    .Register "user32", "LoadCursorW", "i=hl", "r=h"
    .Register "user32", "RegisterClassExW", "i=p", "r=t"
    .Register "user32", "CreateWindowExW", "i=uwwullllhhhp", "r=h"
    .Register "user32", "DefWindowProcW", "i=hull", "r=l"
    ' Регистрируем оконную процедуру.
    pWndProc = .RegisterCallback(GetRef("WndProc"), "i=hull", "r=l")
    ' Заполняем структуру класса.
    hModule =  .GetModuleHandleW(0)
    .NumPut 48, wc, 0
    .NumPut ClsStyle, wc, 4
    .NumPut pWndProc, wc, 8
    .NumPut hModule, wc, 20
    .NumPut .LoadIconW(0, IDI_APPLICATION), wc, 24
    .NumPut .LoadCursorW(0, IDC_ARROW), wc, 28
    .NumPut COLOR_WINDOW + 1, wc, 32
    .NumPut .StrPtr(szClass), wc, 40
    ' Регистрируем класс.
    If .RegisterClassExW(wc) = 0 Then
        MsgBox "Ошибка при регистрации класса."
        WScript.Quit
    End If
    ' Создаём окно.
    hWnd = .CreateWindowExW(0, szClass, szTitle, WndStyle, 20, 20, 400, 300, 0, 0, hModule, 0)
    If hWnd = 0 Then
        MsgBox "Ошибка при создании окна."
        WScript.Quit
    End If
End With

' Цикл, чтобы скрипт не завершился, пока окно не закроется.
Close = 0
Do
    WScript.Sleep 500
Loop While Close = 0

' Оконная процедура, получающая сообщения окна.
Function WndProc(hWnd, uMsg, wParam, lParam)
    If uMsg = WM_CLOSE Then
        Close = 1
    End If
    WndProc = WinAPI.DefWindowProcW(hWnd, uMsg, wParam, lParam)
End Function

6 (изменено: YMP, 2012-02-13 13:34:41)

Re: VBScript: Вызов API в VBScript

Собственно, зациклить можно через message loop, как и положено.

Более продвинутый пример оконного безумства. В главное окно вставлен контрол Edit, позволяющий вводить и редактировать текст.


Set WinAPI = CreateObject("DynamicWrapperX")

szClass = "VBScriptWindowClass"
szTitle = "VBScript Window"
IDI_APPLICATION = 32512
IDC_ARROW = 32512
COLOR_WINDOW = 5
CS_VREDRAW =  1
CS_HREDRAW =  2
ClsStyle = CS_VREDRAW or CS_HREDRAW
WS_OVERLAPPEDWINDOW = &HCF0000
WS_VISIBLE = &H10000000
WndStyle = WS_OVERLAPPEDWINDOW or WS_VISIBLE
WS_CHILD =  &H40000000
WS_VSCROLL =  &H00200000
ES_MULTILINE =  &H0004
ES_AUTOVSCROLL =  &H0040
EditStyle = WS_CHILD or WS_VSCROLL or ES_MULTILINE or ES_AUTOVSCROLL or WS_VISIBLE
WM_CLOSE = &H10     ' Сообщение, что юзер закрыл окно.
WM_SIZE = 5
WM_SETFOCUS = 7
WM_KEYDOWN = &H100
VK_CONTROL = &H11 
VK_A = &H41
vk_prev = 0
EM_SETSEL = &HB1
wc = WinAPI.Space(24, "")   ' WNDCLASSEX, структура класса окна.
rc = WinAPI.Space(8, "")    ' RECT

With WinAPI
    .Register "kernel32", "GetModuleHandleW", "i=p", "r=h"
    .Register "user32", "LoadIconW", "i=hl", "r=h"
    .Register "user32", "LoadCursorW", "i=hl", "r=h"
    .Register "user32", "RegisterClassExW", "i=p", "r=t"
    .Register "user32", "CreateWindowExW", "i=uwwullllhhhp", "r=h"
    .Register "user32", "DefWindowProcW", "i=hull", "r=l"
    .Register "user32", "GetClientRect", "i=hp", "r=l"
    .Register "user32", "MoveWindow", "i=hlllll"
    .Register "user32", "SetFocus", "i=h"
    .Register "user32", "GetMessageW", "i=phll", "r=l"
    .Register "user32", "TranslateMessage", "i=p", "r=l"
    .Register "user32", "DispatchMessageW", "i=p", "r=l"
    .Register "user32", "PostQuitMessage", "i=l"
    .Register "user32", "SendMessage", "i=hull", "r=l"
    ' Регистрируем оконную процедуру.
    pWndProc = .RegisterCallback(GetRef("WndProc"), "i=hull", "r=l")
    ' Заполняем структуру класса.
    hModule =  .GetModuleHandleW(0)
    .NumPut 48, wc, 0
    .NumPut ClsStyle, wc, 4
    .NumPut pWndProc, wc, 8
    .NumPut hModule, wc, 20
    .NumPut .LoadIconW(0, IDI_APPLICATION), wc, 24
    .NumPut .LoadCursorW(0, IDC_ARROW), wc, 28
    .NumPut COLOR_WINDOW + 1, wc, 32
    .NumPut .StrPtr(szClass), wc, 40
    ' Регистрируем класс.
    If .RegisterClassExW(wc) = 0 Then
        MsgBox "Ошибка при регистрации класса."
        WScript.Quit
    End If
    ' Создаём главное окно.
    hwndEdit = 0        ' Для проверки в обработчике WM_SIZE.
    hwndMain = .CreateWindowExW(0, szClass, szTitle, WndStyle, 300, 200, 400, 300, 0, 0, hModule, 0)
    If hwndMain = 0 Then
        MsgBox "Ошибка при создании окна."
        WScript.Quit
    End If
    .GetClientRect hwndMain, rc
    w = .NumGet(rc, 8)
    h = .NumGet(rc, 12)
    ' Создаём дочернее окно Edit.
    hwndEdit = .CreateWindowExW(0, "EDIT", "", EditStyle, 0, 0, w, h, hwndMain, 0, hModule, 0)
    If hwndEdit = 0 Then
        MsgBox "Ошибка при создании контрола Edit."
        WScript.Quit
    End If
    .SetFocus hwndEdit

    ' Цикл очереди сообщений.
    msg = .Space(14, "")    ' MSG
    Do
        ret = .GetMessageW(msg, 0, 0, 0)
        If ret > 0 Then
            ' Чтобы работало сочетание Ctrl-A.
            If .NumGet(msg, 4, "t") = WM_KEYDOWN Then
                If .NumGet(msg, 8) = VK_A and vk_prev = VK_CONTROL Then
                    .SendMessage hwndEdit, EM_SETSEL, 0, -1
                End If
                vk_prev = .NumGet(msg, 8)
            End If
            .TranslateMessage(msg)
            .DispatchMessageW(msg)
        End If
    Loop While ret > 0
End With

' Оконная процедура, получающая сообщения окна.
Function WndProc(hWnd, uMsg, wParam, lParam)
    With WinAPI
        If uMsg = WM_SETFOCUS and hwndEdit <> 0 Then
            .SetFocus hwndEdit
            WndProc = 0
        End If
        If uMsg = WM_SIZE and hwndEdit <> 0 Then
            .GetClientRect hWnd, rc
            w = .NumGet(rc, 8)
            h = .NumGet(rc, 12)
            .MoveWindow hwndEdit, 0, 0, w, h, 1
            WndProc = 0
        End If
        If uMsg = WM_CLOSE Then
            .PostQuitMessage 0
            WndProc = 0
        End If
        WndProc = .DefWindowProcW(hWnd, uMsg, wParam, lParam)
    End With
End Function

7 (изменено: SergeyA, 2012-02-13 15:29:28)

Re: VBScript: Вызов API в VBScript

YMP, просто супер, то что нужно

8

Re: VBScript: Вызов API в VBScript

YMP, примеров подобных вроде не было. Может, выложите в Коллекцию?

9

Re: VBScript: Вызов API в VBScript

С помощью связки VBS+DWX еще очень удобно что-нибудь перехватывать, как вариант, подменять оконную процедуру.

10

Re: VBScript: Вызов API в VBScript

alexii
Мне не ясен тут практический смысл. Он должен быть хотя бы теоретически. Вот если ещё что-то подменять, как chessman предложил, а так просто создавать окно на WinAPI из скрипта — для чего?

11

Re: VBScript: Вызов API в VBScript

Могу только приветствовать.

Суть в том, что с «CreateWindow» примеров вовсе нет. Ни в Коллекции, ни здесь, в Общении.

12 (изменено: D_Pavel, 2014-02-11 09:25:30)

Re: VBScript: Вызов API в VBScript

Помогите. Пытаюсь перевести скрипт с AutoHotKey на JavaScript (можно и на VBscript, без разницы)
Суть скрипта в том, что он должен отслеживать устройство USB HID клавиатура, и принимать с него поступающие данные. Функция RegisterRawInputDevices регистрирует устройство таким образом, чтобы система посылала сообщение в активное окно.
Оригинал рабочего скрипта на "AHK":

OnMessage(0x00FF, "InputMsg")

VarSetCapacity(uDev, (8 + A_PtrSize), 0)
NumPut(1, uDev, 0, "UShort"); 1 = keyboard
NumPut(6,     uDev, 2, "UShort"); 6 = keyboard
NumPut(0,     uDev, 4, "UInt")
NumPut(0,    uDev, 8, "Ptr")
DllCall("RegisterRawInputDevices", "Ptr", &uDev, "UInt", 1, "UInt", 8 + A_PtrSize)

Return

InputMsg(wParam, lParam) {
    MsgBox, % lParam; тут обработчик сообщений
}

Новый скрипт на JavaScript:

        WinAPI = new ActiveXObject("DynamicWrapperX.2");

        WinAPI.Register("user32", "RegisterRawInputDevices", "i=puu", "r=l");
        PtrSize = WinAPI.Bitness() / 8;
        strucSize = 8 + PtrSize;
        uDev = WinAPI.MemAlloc( strucSize)

        WinAPI.NumPut (1, uDev, 0, "t");//1 = keyboard
        WinAPI.NumPut (6, uDev, 2, "t");//6 = keyboard
        WinAPI.NumPut (0, uDev, 4, "u");
        WinAPI.NumPut (0, uDev, 8, "p");
        
        res = WinAPI.RegisterRawInputDevices(uDev, 1, strucSize);
        console.log(res);
        
        window.addEventListener('message', function (e) {
            console.log(e.data);
            }
        );

Проблема в том что не срабатывает событие onMessage. Не знаю как правильно написать чтобы обрабатывать системное сообщение.

PS: И еще мне кажется что WinAPI.RegisterRawInputDevices(uDev, 1, strucSize) тоже не правильно выполняется.

13

Re: VBScript: Вызов API в VBScript

Немного погуглив, подозреваю, что тип 'message' — это не оконное сообщение, а что-то другое. Оконные же можно, по идее, смотреть через PeekMessage, например. Но тогда скрипт придётся в каком-то месте зациклить. Т.е. дальше его выполнение не пойдёт, будет крутиться цикл просмотра очереди сообщений.

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

PS: И еще мне кажется что WinAPI.RegisterRawInputDevices(uDev, 1, strucSize) тоже не правильно выполняется.

В чём это проявляется?

14 (изменено: D_Pavel, 2014-02-11 12:11:33)

Re: VBScript: Вызов API в VBScript

WinAPI.RegisterRawInputDevices(uDev, 1, strucSize)  раньше возвращало 0, сейчас вроде разобрался, возвращает 1.


        WinAPI.Register("user32", "SetWindowLong", "i=hll", "r=l");
        WinAPI.Register("user32", "GetActiveWindow", "r=l");
        ResHandle = WinAPI.GetActiveWindow();
        console.log("GetActiveWindow = " + ResHandle);
        pFunc = WinAPI.RegisterCallback(myFunc, "i=hl", "r=l");
        ret = WinAPI.SetWindowLong (ResHandle, -4, pFunc)
        console.log("SetWindowLong = " + ret);

Сейчас SetWindowLong возвращает 0. Это из-за того что окно не принадлежит потоку? Скрипт выполняется в браузере. Мне нужно создать еще одно окно скриптом, и в нем создать функцию обработчик?

Пробовал использовать GetMessage, но браузер зависает.

15

Re: VBScript: Вызов API в VBScript

Всё зависит от того, как браузер работает. Если скрипт выполняется не в том потоке, который создал окно, то сообщения до скрипта не дойдут. У каждого потока своя очередь сообщений.

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

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

16

Re: VBScript: Вызов API в VBScript

Меня сейчас устроит любой рабочий вариант. Только что за окно нужно создать? Окно браузера или пустое окно windows?

17

Re: VBScript: Вызов API в VBScript

Да, пустое окно, невидимое. Например, у каждого скрипта АНК есть скрытое окно, в которое можно сообщения посылать. Потом нужно, видимо, RegisterRawInputDevices указать хэндл этого окна, чтобы туда сообщения шли.

Пока такие идеи.

18

Re: VBScript: Вызов API в VBScript

И можно будет поменять процедуру нового окна на функцию которая находится в моем окне?

19

Re: VBScript: Вызов API в VBScript

Как проще всего создать окно? В примере выше много всего лишнего. Что можно убрать чтобы упростить?
Делаю так:

        WinAPI.Register("user32", "CreateWindowEx", "i=uwwullllhhhp", "r=h");
        hWnd = WinAPI.CreateWindowEx(0, "", "", 0, 0, 0, 0, 0, null, null, null, null)

Но возвращается 0.

20

Re: VBScript: Вызов API в VBScript

D_Pavel пишет:

И можно будет поменять процедуру нового окна на функцию которая находится в моем окне?

Что такое "моё окно"?

21

Re: VBScript: Вызов API в VBScript

Мое окно - это в котором находится скрипт.
Сделал как в примере выше, но ругается "Ошибка при регистрации класса." Как создать это окно на JavaScript?

IDI_APPLICATION = 32512
IDC_ARROW = 32512
COLOR_WINDOW = 5
CS_VREDRAW =  1
CS_HREDRAW =  2
ClsStyle = CS_VREDRAW + CS_HREDRAW
WS_OVERLAPPEDWINDOW = 0xCF0000
WS_VISIBLE = 0x10000000
WndStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE
WM_CLOSE = 0x10     // Сообщение, что юзер закрыл окно.
szClass = "TestWindowClass"
szTitle = "TestWindow"
wc = WinAPI.MemAlloc(24)   // WNDCLASSEX, структура класса окна.

    WinAPI.Register ("kernel32", "GetModuleHandleW", "i=p", "r=h");
    WinAPI.Register ("user32", "LoadIconW", "i=hl", "r=h");
    WinAPI.Register ("user32", "LoadCursorW", "i=hl", "r=h");
    WinAPI.Register ("user32", "RegisterClassExW", "i=p", "r=t");
    WinAPI.Register ("user32", "CreateWindowExW", "i=uwwullllhhhp", "r=h");
    WinAPI.Register ("user32", "DefWindowProcW", "i=hull", "r=l");
    // Регистрируем оконную процедуру.
    pWndProc = WinAPI.RegisterCallback(WndProc, "i=hull", "r=l");
    // Заполняем структуру класса.
    hModule =  WinAPI.GetModuleHandleW(0)
    WinAPI.NumPut (48, wc, 0);
    WinAPI.NumPut (ClsStyle, wc, 4);
    WinAPI.NumPut (pWndProc, wc, 8);
    WinAPI.NumPut (hModule, wc, 20);
    WinAPI.NumPut (WinAPI.LoadIconW(0, IDI_APPLICATION), wc, 24);
    WinAPI.NumPut (WinAPI.LoadCursorW(0, IDC_ARROW), wc, 28);
    WinAPI.NumPut (COLOR_WINDOW + 1, wc, 32);
    WinAPI.NumPut (WinAPI.StrPtr(szClass), wc, 40);
    // Регистрируем класс.
    if (WinAPI.RegisterClassExW(wc) == 0 ){
        alert( "Ошибка при регистрации класса.");
    }
    // Создаём окно.
    hWnd = WinAPI.CreateWindowExW(0, szClass, szTitle, WndStyle, 20, 20, 400, 300, 0, 0, hModule, 0)
    if (hWnd == 0){
        alert ("Ошибка при создании окна.");
    }
// Цикл, чтобы скрипт не завершился, пока окно не закроется.
Close = 0
do{
}while( Close == 0)

// Оконная процедура, получающая сообщения окна.
function WndProc(hWnd, uMsg, wParam, lParam){
    if (uMsg == WM_CLOSE){
        Close = 1;
    }
    WndProc = WinAPI.DefWindowProcW(hWnd, uMsg, wParam, lParam);
}

22

Re: VBScript: Вызов API в VBScript

D_Pavel пишет:

Мое окно - это в котором находится скрипт.

Как скрипт может находиться в окне? Что-то не пойму.

23

Re: VBScript: Вызов API в VBScript

Скрипт находится в файле. Файл открыт в браузере. У браузера есть окно. Может я не правильно понял.
Да не важно
В чем у меня ошибка? Окно не создается.

24

Re: VBScript: Вызов API в VBScript

Не знаю пока, посмотрю.

25

Re: VBScript: Вызов API в VBScript

Спасибо

26

Re: VBScript: Вызов API в VBScript

Размер структуры 48 байт, а не 24.

wc = WinAPI.MemAlloc(24)   // WNDCLASSEX, структура класса окна.

В оконной процедуре вместо

WndProc = WinAPI.DefWindowProcW(hWnd, uMsg, wParam, lParam);

должно быть

return WinAPI.DefWindowProcW(hWnd, uMsg, wParam, lParam);

27 (изменено: D_Pavel, 2014-02-12 08:16:13)

Re: VBScript: Вызов API в VBScript

Точно, 48. Я забыл что WinAPI.Space(24, "") - это в двухбайтовых единицах считается

28

Re: VBScript: Вызов API в VBScript

Если скрипт в составе веб-страницы, то цикл, предотвращающий завершение скрипта, не нужен, ведь страница и так не закроется.

29 (изменено: D_Pavel, 2014-02-12 12:18:09)

Re: VBScript: Вызов API в VBScript

Да.
Создал окно попроще, через имя класса "буттон" чтобы не регистрировать класс вручную:

        hWnd = WinAPI.CreateWindowExW(0, "Button", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

работает!
Большое спасибо за помощь! ! !

30

Re: VBScript: Вызов API в VBScript

А как послать нажатие кнопки?
Пытаюсь нажать кнопку MUTE, виснет браузер. Что-то не так с памятью. И слишком громоздко получилось.

            WinAPI.Register ("user32", "SendInput", "i=upl", "r=l");
            WinAPI.Register ("user32", "GetMessageExtraInfo", "r=l");

            var KEYBDINPUT = WinAPI.MemAlloc( 2 + 2 + 4 + 4 + 4 );
            WinAPI.NumPut (0, KEYBDINPUT, 0, "u");
            WinAPI.NumPut (0xAD, KEYBDINPUT, 4, "u");
            WinAPI.NumPut (8+2, KEYBDINPUT, 8, "u");
            WinAPI.NumPut (0, KEYBDINPUT, 12, "u");
            WinAPI.NumPut (WinAPI.GetMessageExtraInfo(), KEYBDINPUT, 16, "u");

            var INPUT = WinAPI.MemAlloc( 4 + 4 );
            WinAPI.NumPut (1, INPUT, 0, "u");
            WinAPI.NumPut (KEYBDINPUT, INPUT, 4, "u");
            
            WinAPI.SendInput( 1, INPUT, 8); 

31 (изменено: D_Pavel, 2014-02-14 07:26:27)

Re: VBScript: Вызов API в VBScript

А вот так не виснет, но выдает ошибку 87 - некорректный параметр.

            var INPUT = WinAPI.MemAlloc( 24 );
            WinAPI.NumPut (1, INPUT, 0, "u");
            WinAPI.NumPut (0, INPUT, 4, "u");
            WinAPI.NumPut (0xAD, INPUT, 8, "u");
            WinAPI.NumPut (8+2, INPUT, 12, "u");
            WinAPI.NumPut (0, INPUT, 16, "u");
            WinAPI.NumPut (WinAPI.GetMessageExtraInfo(), INPUT, 20, "u");
        
            WinAPI.SendInput( 1, INPUT, 24);
            alert (WinAPI.GetLastError() );

32 (изменено: D_Pavel, 2014-02-14 07:50:36)

Re: VBScript: Вызов API в VBScript

Все, разобрался:

WinAPI.keybd_event( 0xAD, 0, 0, 0);
WinAPI.keybd_event( 0xAD, 0, 2, 0);

33

Re: VBScript: Вызов API в VBScript

Не могу только придумать как получить текущую громкость.

34

Re: VBScript: Вызов API в VBScript

D_Pavel пишет:

Не могу только придумать как получить текущую громкость.

Не подскажу, я этим не занимался никогда.

SendInput у меня работает вот так (для 32 бит):


WinAPI.Register ("user32", "SendInput", "i=upl", "r=u");

INPUT_KEYBOARD = 1
KEYEVENTF_KEYUP = 2
VK = 0xAD

// Память для двух событий: down & up.
var INPUTS = WinAPI.MemAlloc( 56, 1 );  // С обнулением.
// Нажатие
WinAPI.NumPut (INPUT_KEYBOARD, INPUTS, 0, "u");
WinAPI.NumPut (VK, INPUTS, 4, "t");
// Отпускание
WinAPI.NumPut (INPUT_KEYBOARD, INPUTS, 28, "u");
WinAPI.NumPut (VK, INPUTS, 32, "t");
WinAPI.NumPut (KEYEVENTF_KEYUP, INPUTS, 36, "u")
        
WinAPI.SendInput(2, INPUTS, 28);

Размер union'a определяется самым большим его членом (MOUSEINPUT). WORD = 2 байта.

35 (изменено: D_Pavel, 2014-02-17 10:37:09)

Re: VBScript: Вызов API в VBScript

Еще немного упростил.
Вместо

var hWnd = WinAPI.CreateWindowExW(0, "STATIC", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);

сделал

var hWnd = WinAPI.GetForegroundWindow(0);

36

Re: VBScript: Вызов API в VBScript

А не проще для создания формы воспользоваться HTA?

37 (изменено: D_Pavel, 2014-04-01 12:14:48)

Re: VBScript: Вызов API в VBScript

Проще. Но в НТА труднее отлаживать.

38

Re: VBScript: Вызов API в VBScript

в C++ иногда в качестве аргумента в WinAPI передается NULL. Как такой NULL передавать в ф-ю WinAPI в VBScript и JScript?

win 7 x64, DWX 2.1

39

Re: VBScript: Вызов API в VBScript

Это указатель или хэндл, поэтому тип "p" или "h", значение 0.

40

Re: VBScript: Вызов API в VBScript

Хм. К примеру, ф-я ShellExecute.

HINSTANCE ShellExecute(
  _In_opt_  HWND hwnd,
  _In_opt_  LPCTSTR lpOperation,
  _In_      LPCTSTR lpFile,
  _In_opt_  LPCTSTR lpParameters,
  _In_opt_  LPCTSTR lpDirectory,
  _In_      INT nShowCmd
);

и, к примеру, вызов в C++

ShellExecute(hwnd, "find", "c:\\MyPrograms", NULL, NULL, 0);

Как оформить регистрацию такого и сам вызов?

win 7 x64, DWX 2.1

41

Re: VBScript: Вызов API в VBScript

Для строк нули также принимаются, поэтому можно, например, так:


DWX = new ActiveXObject("DynamicWrapperX");
DWX.Register("shell32:ShellExecuteW", "shex", "i=hwwwwl");
SW_SHOW = 5;
DWX.shex(0, "explore", "C:\\", 0, 0, SW_SHOW);

42 (изменено: unreal612, 2014-06-28 08:48:03)

Re: VBScript: Вызов API в VBScript

в DynamicWrapperX v2 есть какие-то выходные параметры. Это где они указываются? (желательно с примером конкретной WinAPI ф-и)

win 7 x64, DWX 2.1

43

Re: VBScript: Вызов API в VBScript

Там же, где и входные. Разница в том, что при входном типе параметра при вызове функции передаётся копия значения аргумента, а при выходном типе — указатель на значение. Но это возможно только в языках, передающих переменные методам по ссылке — например, в VBScript. В JScript это возможно только для строк, но не рекомендуется, т.к. нет гарантии, что строка тоже не будет скопирована при передаче. Последнее, как я понял, зависит от конкретной реализации движка.

Конкретной функции на ум не приходит, поэтому условный пример. Некая функция возвращает некое 32-битное целое через свой выходной параметр. Код на VBS.


DWX.Register "lib", "func", "i=L"
a = 0       ' Обнуляем выходную переменную.
DWX.func a
MsgBox a    ' Смотрим значение а, записанное функцией.

44 (изменено: unreal612, 2014-08-14 11:56:54)

Re: VBScript: Вызов API в VBScript

Как использовать WinAPI - GetVersionEx ?

ее синтаксис на С++:

BOOL WINAPI GetVersionEx(
  _Inout_  LPOSVERSIONINFO lpVersionInfo
);

где LPOSVERSIONINFO:

typedef struct _OSVERSIONINFOEX {
  DWORD dwOSVersionInfoSize;
  DWORD dwMajorVersion;
  DWORD dwMinorVersion;
  DWORD dwBuildNumber;
  DWORD dwPlatformId;
  TCHAR szCSDVersion[128];
  WORD  wServicePackMajor;
  WORD  wServicePackMinor;
  WORD  wSuiteMask;
  BYTE  wProductType;
  BYTE  wReserved;
} OSVERSIONINFOEX, *POSVERSIONINFOEX, *LPOSVERSIONINFOEX;

попытался заюзать так:

var WinAPI = new ActiveXObject("DynamicWrapperX.2"),
    sizeof_OSVERSIONINFOEX = 4*5 + 128*2 + 2*3 + 1*2,  // DWORD*5 + WCHAR[128] + WORD*3 + BYTE*2
    MemPtr = WinAPI.MemAlloc( sizeof_OSVERSIONINFOEX, 1),
    nonzero;

WinAPI.Register("kernel32.dll:GetVersionExW", "GetVersionEx", "i=H", "r=l");
WinAPI.NumPut( sizeof_OSVERSIONINFOEX, MemPtr, 0, 'u' );

var nonzero = WinAPI.GetVersionEx(MemPtr);
alert( nonzero ); // выводит 0 - значит где-то ошибка.

Где ошибка? Еще попытался заюзить для проверки ф-ю GetLastError. Она возвратила код 122, что, судя по http://msdn.microsoft.com/library/ms681382 , означает ...

ERROR_INSUFFICIENT_BUFFER
122 (0x7A)

The data area passed to a system call is too small.

PS.
Win 7 x64, hta-файл.

win 7 x64, DWX 2.1

45 (изменено: unreal612, 2014-08-14 12:38:25)

Re: VBScript: Вызов API в VBScript

Доперло.
MemPtr уже является адресом и надо во входных параметрах писать h, а не H. Т.е.

WinAPI.Register("kernel32.dll:GetVersionExW", "GetVersionEx", "i=h", "r=l");

win 7 x64, DWX 2.1

46

Re: VBScript: Вызов API в VBScript

Да, верно. Или, учитывая, что это указатель, более идеологически правильно использовать тип "p". По сути разницы не будет, но для читабельности кода, думаю, лучше.

Большими буквами обозначаются выходные числа, а здесь структура. Да и вообще это не работает в JScript, т.к. он передаёт аргументы по значению, т.е. в виде временных копий.

47

Re: VBScript: Вызов API в VBScript

Кстати, если нужен код ошибки от GetLastError, не нужно её регистрировать и потом вызывать. Т.к. нет гарантии, что между вызовом целевой функции и вызовом GetLastError не будет вызвана какая-то другая API-функция — либо объектом Dynwrapx, либо скриптовым движком. Тогда код ошибки может быть изменён.

Для этой цели теперь есть метод LastError. Он возвращает этот код (или его описание), если функция была зарегистрирована с флагом "l".


var WinAPI = new ActiveXObject("DynamicWrapperX.2"),
    sizeof_OSVERSIONINFOEX = 4*5 + 128*2 + 2*3 + 1*2,  // DWORD*5 + WCHAR[128] + WORD*3 + BYTE*2
    MemPtr = WinAPI.MemAlloc( sizeof_OSVERSIONINFOEX, 1),
    nonzero;

WinAPI.Register("kernel32.dll:GetVersionExW", "GetVersionEx", "i=H", "r=l", "f=l");
WinAPI.NumPut( sizeof_OSVERSIONINFOEX, MemPtr, 0, 'u' );

var nonzero = WinAPI.GetVersionEx(MemPtr);

WSH.echo(WinAPI.LastError() + "\n" + WinAPI.LastError(1));

---------------------------
Windows Script Host
---------------------------
122
Область данных, переданная по системному вызову, слишком мала.


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

48

Re: VBScript: Вызов API в VBScript

YMP пишет:

Большими буквами обозначаются выходные числа, а здесь структура. Да и вообще это не работает в JScript, т.к. он передаёт аргументы по значению, т.е. в виде временных копий.

понятно, но на VBScript все равно не перейду. Не нравится его синтаксис и некоторые заморочки.

YMP пишет:

Для этой цели теперь есть метод LastError. Он возвращает этот код (или его описание), если функция была зарегистрирована с флагом "l".

о, сенкс.

win 7 x64, DWX 2.1

49 (изменено: unreal612, 2014-09-15 15:18:33)

Re: VBScript: Вызов API в VBScript

в WinAPI есть ф-я CreateProcess (точнее CreateProcessW). У нее есть параметр "LPTSTR lpCommandLine". Для него написано

The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.

Если для него указывать "r=w", то это будет корректно или нет?
Т.к. непонятно, являются типы параметров "w" только для чтения (как строки-литералы в C++) или нет (PS, хотя подозревая, что нет).
Или для такого типа строки надо юзать MemAlloc и тип параметра "p"?

win 7 x64, DWX 2.1

50

Re: VBScript: Вызов API в VBScript

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

51 (изменено: unreal612, 2014-10-04 07:36:56)

Re: VBScript: Вызов API в VBScript

откуда-то из MSDN

strComputer = "."
Set colProcesses = GetObject("winmgmts:" & _
   "{impersonationLevel=impersonate}!\\" & strComputer & _
   "\root\cimv2").ExecQuery("Select * from Win32_Process")

For Each objProcess in colProcesses

    Return = objProcess.GetOwner(strNameOfUser)
    If Return <> 0 Then
        Wscript.Echo "Could not get owner info for process " & _ 
            objProcess.Name & VBNewLine _
            & "Error = " & Return
    Else
        Wscript.Echo "Process " _
            & objProcess.Name & " is owned by " _
            & "\" & strNameOfUser & "."
    End If
Next

т.е. strNameOfUser является выходной переменной. Как такое реализовать на JScript?

win 7 x64, DWX 2.1

52 (изменено: unreal612, 2014-10-04 07:55:11)

Re: VBScript: Вызов API в VBScript

и почему-то, если в данный vbs-код после

Return = objProcess.GetOwner(strNameOfUser)

вставить

WScript.Echo CStr(CreateObject("DynamicWrapperX.2").StrPtr(strNameOfUser))

то выводится

DynamicWrapperX.2: Значение аргумента вне диапазона для типа параметра

win 7 x64, DWX 2.1

53

Re: VBScript: Вызов API в VBScript

1. JScript: вызов методов WMI с выходными параметрами

2. Для StrPtr нужна строка, а strNameOfUser имеет тип VT_NULL. Если бы при этом его значением был 0, то это бы проканало как нулевой указатель (NULL). Но у меня, например, его значение почему-то 2, поэтому функция преобразования типов в DWX его не пропускает. Не может указатель на строку иметь значение 2.

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

54 (изменено: unreal612, 2014-10-06 22:29:37)

Re: VBScript: Вызов API в VBScript

Насчет 2-го не понял (понял, что что-то из серии - этот тип строки имеет какой-то подтип, который не нравится DynamicWrapperX)

Насчет 1-го сенкс. Почитал ту тему + поискал эти методы в "Введение в Windows Management Instrumentation (WMI)" на самом сайте.
Сделал так

var processes = wmiQuery(null, "Select * from Win32_Process")

for (var i=0; i<processes.length; ++i) {
    var process = processes[i];

    var nameOfUser = [];
    var Return = wmiExecMethod(process, "GetOwner", null, {user: nameOfUser});
    
    if (Return != 0)
        WScript.echo ("Could not get owner info for process " + process.name + "\r\nError = " + Return);
    else
        WScript.echo ("Process " + process.name + " is owned by \\" + nameOfUser[0] + ".");
}


// ===========================================
Enumerator.prototype.toArray = function () {
    var result = [];
    for (; !this.atEnd(); this.moveNext())
        result.push(this.item());
    return result;
}

function wmiQuery(moniker, query) {
    moniker = moniker || 'winmgmts:{impersonationLevel=impersonate}!//./root/cimv2';
    var items =  GetObject(moniker).execQuery(query);
    return (new Enumerator(items)).toArray();
}

function wmiExecMethod(sWbemObject, method, inParams, outParams) {
    var _inParams = null, _outParams;
    if (inParams) {
        _inParams = sWbemObject.methods_(method).inParameters.spawnInstance_();
        for (var inParam in inParams)
            if (inParams.hasOwnProperty(inParam))
                _inParams[inParam] = inParams[inParam];
    };

    _outParams = sWbemObject.execMethod_(method, _inParams);

    if (outParams) {
        for (var outParam in outParams)
            if (outParams.hasOwnProperty(outParam))
                outParams[outParam].push(_outParams[outParam]) ;
        return _outParams.returnValue;
    } else
        return _outParams;
}
win 7 x64, DWX 2.1

55

Re: VBScript: Вызов API в VBScript

кстати, в теме "WSH: как из скрипта определить его идентификатор процесса (PID)" PID определяется через запуск mshta, который все-таки моргает окном.
У себя сделал так без моргания:

function getScriptProcessID() {
    var
        wshShell = new ActiveXObject('WScript.Shell'),
        id = '' + (new Date).valueOf(),
        strPath = '"' + wshShell.expandEnvironmentStrings('%ComSpec%') + '" /k "' + id +'"',
        сhildProcess, processID;

    wshShell.run(strPath, 0);
    сhildProcess = wmiQuery(null, "SELECT * FROM Win32_Process WHERE CommandLine LIKE '%" + id + "%'")[0];
    processID = сhildProcess.parentProcessID;

    сhildProcess.terminate();
    return processID;
}
win 7 x64, DWX 2.1

56

Re: VBScript: Вызов API в VBScript

unreal612, нашёл в переписке с JSman-ом. Мы вот так делали. Тоже не моргает.

function GetPID() {
    with (GetObject("winmgmts:root\\cimv2:win32_process.Handle='" +
        new ActiveXObject("WScript.Shell").Exec("rundll32 kernel32,Sleep").ProcessId + "'")) {
        Terminate(); return ParentProcessId
    }
}
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

57

Re: VBScript: Вызов API в VBScript

Не очень удачный способ для случаев, когда скриптов запущено несколько.
А вообще варианты тут обсуждались.

58

Re: VBScript: Вызов API в VBScript

Flasher, почему ? На чём падает ? O_o

P.S Запустил 6 раз. Всё норм.

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

59

Re: VBScript: Вызов API в VBScript

Спутал с другим методом. А у этого с вызовом rundll какой-то косяк был, дома попробую вспомнить.

60

Re: VBScript: Вызов API в VBScript

Flasher, что-нибудь вспомнилось ?

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