76

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

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

77

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

Прошу помощи в освоении DynamicWrapperX.

Интересует пример активации установленной на ПК программы с параметрами.
Конкретней: запуск Adobe Reader, с открытием конкретного файла и посылке в Adobe Reader
комбинации клавиш CTRL+L.

Если сообщение не в тему - прошу извинить.

78

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

Для таких вещей гораздо удобнее использовать AutoHotkey. Тут на форуме есть раздел про него. А так же описание возможностей: http://www.script-coding.com/AutoHotkeyTranslation.html. Если нет желания или возможности устанавливать AutoHotkey на целевой машине, можно будет скрипт скомпилировать в EXE.

79

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

По некоторым причинам не могу использовать AutoHotkey.
Нужен vbscript.
Запуск на ПК Adobe Reader в скрипте реализована, но не могу послать именно ему комбинацию клавиш. Думал может с помощью DynamicWrapperX получиться.

80

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

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

81 (изменено: Flasher, 2015-08-12 13:39:44)

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

vzaitsev
Я подобные вещи обычно делаю стандартными средствами:

With CreateObject("WScript.Shell")
  Set Exec = .Exec("C:\Path to Program.exe ""C:\Path to my file.ext""")
  PID = Exec.ProcessID : Do : A = .AppActivate(PID) : Loop Until A
  Wscript.Sleep 50 : .SendKeys "^l"
End With

А если прямо таки необходимо работать с классами/хэндлами окон, то лучше посмотреть в сторону AutiItX3.

82 (изменено: YMP, 2015-08-12 10:12:32)

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

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

83

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

Через API у меня работает так. При условии, что программа уже запущена с открытым документом.


Set DWX = CreateObject("DynamicWrapperX")
DWX.Register "user32", "FindWindowW", "i=ww", "r=h"
DWX.Register "user32", "SetForegroundWindow", "i=h", "r=l"
DWX.Register "user32", "SendInput", "i=upl", "r=u"

window_class = "AcrobatSDIWindow"

hwnd = DWX.FindWindowW( window_class, 0 )

If hwnd = 0 Then
    MsgBox "Окно не найдено."
    WScript.Quit
End If

If DWX.Bitness = 32 Then
    input_size = 28
    input_data = "01000000 A200 0000 00000000 00000000 00000000 00000000 00000000" &_
                 "01000000 4C00 0000 00000000 00000000 00000000 00000000 00000000" &_
                 "01000000 4C00 0000 02000000 00000000 00000000 00000000 00000000" &_
                 "01000000 A200 0000 02000000 00000000 00000000 00000000 00000000"
Else
    input_size = 40
    input_data = "01000000 00000000 A200 0000 00000000 00000000 00000000 0000000000000000" &_
                 "0000000000000000" &_
                 "01000000 00000000 4C00 0000 00000000 00000000 00000000 0000000000000000" &_
                 "0000000000000000" &_
                 "01000000 00000000 4C00 0000 02000000 00000000 00000000 0000000000000000" &_
                 "0000000000000000" &_
                 "01000000 00000000 A200 0000 02000000 00000000 00000000 0000000000000000" &_
                 "0000000000000000"
End If

INPUTS = DWX.MemAlloc( input_size * 4 )
DWX.MemWrite input_data, INPUTS

ret = DWX.SetForegroundWindow( hwnd )

If ret = 0 Then
    MsgBox "Ошибка активации окна."
    DWX.MemFree INPUTS
    WScript.Quit
End If

ret = DWX.SendInput( 4, INPUTS, input_size )

If ret = 0 Then
    MsgBox "Ошибка посылки клавиш."
End If

DWX.MemFree INPUTS

84 (изменено: Flasher, 2015-08-12 13:40:26)

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

YMP пишет:

Не полноэкранный режим, а просто максимальное растягивание окна.

В XP быть не должно, это в последующих версиях добавка шифта появилась при задействовании верхнего регистра. Исправил.

85

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

YMP пишет:

Через API у меня работает так. При условии, что программа уже запущена с открытым документом.

Классссс! Работает. Проверил на XP (x32). Большое Спасибо!
Если можно в код вставить комментарии, т.к. мне не все понятны команды.
Через API я еще не работал.
Я так понимаю, что данный код будет работать на х32 и х64, при условии регистрации в системе библиотеки dynwrapx.dll (http://www.script-coding.com/dynwrapx.html).

86

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

При условии, что в системе обе версии зарегистрированы (32 и 64 бита). Какая из них будет использоваться, зависит от того, каким интерпретатором будет выполняться скрипт. В 64-битных Windows есть как 64-, так и 32-битный интерпретатор.

Чтобы понять, как работает код, почитайте описание функции SendInput. Ей передаётся массив из 4-х структур INPUT (они тоже описаны на MSDN). input_size — это размер такой структуры, разный для 32 и 64 бит. В первой прописано нажатие Ctrl, во второй нажатие L, потом отпускания этих клавиш. Клавиши обозначены соответствующими кодами виртуальных клавиш: Ctrl — A2, L — 4C. Список этих кодов можно найти в Интернете. Единица в начале означает, что передаётся событие клавиатуры, а двойка в двух последних структурах означает отпускание.

87

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

vzaitsev пишет:

Классссс! Работает. Проверил на XP (x32). Большое Спасибо!

К сожалению рано радовался.
Скрипт работает нормально если его запустить на ПК нажав на нем Ентер.
Если запускать скрипт при старте ОС, то может не сработать. Фокус на окне Adobe Reader не устанавливается, если загружаются еще программы.
Т.е. скрипт с подключением библиотеки dynwrapx.dll аналогичен следующему без библиотеки:
WshShell.AppActivate ("Adobe Reader")
WScript.Sleep 1000
WshShell.SendKeys "^l"

Вопрос: можно-ли послать комбинацию клавиш именно окну (приложению)?

88

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

vzaitsev
Так а мой скрипт чем не устроил?

89

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

Flasher пишет:

vzaitsev
Так а мой скрипт чем не устроил?

Код клавиш посылается на клавиатуру, а не приложению.
Если окно не в фокусе, оно не получит эту комбинацию.

90

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

vzaitsev
Комбинация клавиш посылается после активации окна приложения вообще-то. Сперва стоило попробовать, не так ли?

91

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

Flasher пишет:

vzaitsev
Комбинация клавиш посылается после активации окна приложения вообще-то. Сперва стоило попробовать, не так ли?

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

92 (изменено: Flasher, 2015-08-14 13:14:11)

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

vzaitsev
Этот промежуток составляет 50 мс, половину доли секунды. Какова вероятность, что какое-то ещё окно в этом промежутке появится? Не говоря о том, что этот промежуток условный, т.е. его можно изменить под себя.

P.S.: В цитировании предыдущего поста нет никакой необходимости.

93

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

vzaitsev пишет:

Вопрос: можно-ли послать комбинацию клавиш именно окну (приложению)?

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

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

94 (изменено: maksim32, 2016-03-19 09:39:34)

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

Столкнулся с проблемой: в оконной функции у некоторых сообщений, например WM_NCPAINT и WM_ERASEBKGND параметр wParam иногда получается типа unknown.

+ открыть спойлер

https://pp.vk.me/c631928/v631928861/1e84e/xQpoTTgDlK4.jpg


DWX.RegisterCallback(MainWndProc, "i=hupp", "r=p"); // HWND,UINT,WPARAM,LPARAM
...
function MainWndProc(hWnd, uMsg, wParam, lParam) {
 if(uMsg == WM_ERASEBKGND) stdout("WM_ERASEBKGND:  wParam = ("+typeof(wParam)+")"+wParam);
 if(uMsg == WM_NCPAINT) stdout("WM_NCPAINT:  wParam = ("+typeof(wParam)+")"+wParam);
 switch(uMsg) {
  case WM_DESTROY:
   DWX.PostQuitMessage(0);
   return 0;
 }
 return DWX.DefWindowProcW(hWnd, uMsg, wParam, lParam);
}

Тут, в wParam, судя по описанию WM_ERASEBKGND и WM_NCPAINT - дескриптор.

Аналогичная программа на C:
https://pp.vk.me/c631928/v631928861/1e868/HqR088uLP4g.jpg

В принципе, решить проблему просто - тип wParam указать не "p", а "h". Но это может всплыть в ином месте, где используется этот тип "p".



YMP пишет:

Поэтому на данный момент разница между "p" и "h", "u" и "l", и т.д. — чисто мнемоническая.

Получается, "p" и "h" не эквивалентны - при работе с "h" проблем не возникает:


// Различия между типами "p" и "h"
function stdout(val){try{WScript.StdOut.WriteLine(val);}catch(e){}} // debug

var DWX;
try{DWX=new ActiveXObject("DynamicWrapperX.2");}
catch(e){WScript.Echo("Ошибка. Не установлен компонент DynamicWrapperX 2.");WScript.Quit();}
if(DWX.Bitness()!=64) WScript.Quit();


var fn0=function(v_P, v_H){
 stdout("("+typeof(v_P)+")"+v_P+", ("+typeof(v_H)+")"+v_H);
 return 0;
}
var lpnf0=DWX.RegisterCallback(fn0, "i=ph", "r=l");
DWX.RegisterAddr(lpnf0, "TestFunction", "i=ph", "r=l");

DWX.TestFunction(-0x8000000000000400, -0x8000000000000400); // минимальное число (при ...401 уже не сработает) (- не "нейтрализуется")
DWX.TestFunction( 0x7FFFFFFFFFFFFFFF,  0x7FFFFFFFFFFFFFFF); // реальное минимальное число
DWX.TestFunction( 0xFFFFFFFFFFFFFBFF,  0xFFFFFFFFFFFFFBFF); // максимальное число
DWX.TestFunction(-0x0000000000000001, -0x0000000000000001); // реальное максимальное число (unsigned, если)
DWX.TestFunction(-150903375, -150903375); // на все отрицательные числа p "ответит" unknown
DWX.TestFunction(-0x7FFFFFFFFFFFFBFF, -0x7FFFFFFFFFFFFBFF); // и тут от p unknown
DWX.TestFunction(-0x7FFFFFFFFFFFFA00, -0x7FFFFFFFFFFFFA00); // тут уже преобразовывается


Версия DWX: 2.1.1.1 x64
Версия JScript: 5.812 x64
Версия Windows: 10.0.10586.104 x64

95

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

Да, они эквивалентны при передаче числа из скрипта, но не эквивалентны при передаче числа в скрипт (для возвращаемых значений и параметров callback-функций).

Если вы передаёте число из скрипта, то обозначите ли вы его как 0xFFFFFFFFFFFFFFFF или как -1, в памяти будет один и тот же набор битов. Т.е. вызываемой API-функции это без разницы. Она получает набор битов, тип числа там никак не обозначен, и она сама знает, как его интерпретировать в смысле знаковости.

В то же время скриптовый движок может не иметь типа переменной для 64-битных беззнаковых чисел, и втайне от вас поместит 0xFFFFFFFFFFFFFFFF в знаковый тип, т.е. передаст его в DWX как -1. Или вообще его забракует, и тогда вы сами можете попытаться использовать -1, если знаете о том, что в памяти разницы не будет. Первая версия DWX отрицательные числа для указателей не принимала, т.к. это адрес, а адрес не может быть отрицательным. Такой строгий контроль вызывал неудобства в силу вышеозвученных причин, и я его убрал.

Что касается передачи числа извне в скрипт, то тут уже не всё равно, знаковое число или беззнаковое, поскольку его тип должен быть явным образом указан в передаваемой скрипту переменной. Если передать указатель как отрицательное, а вы станете с ним производить какие-то вычисления, вполне логично ожидая, что он положителен, то получится неверный результат. Исходя из этого, тип "p" интерпретируется как положительный, и если величина числа превысит диапазон дробного двойной точности (VT_R8), то используется тип VT_UI8, который JScript'у неизвестен, поэтому и обозначается им как unknown.

Хэндлы в принципе тоже беззнаковый тип, но они используются просто как некие условные числа, идентифицирующие какие-то объекты Винды. Вычислять с ними нечего, максимум можно их сравнить, чтобы узнать, один это объект или разные. Этому их знаковость никак не мешает. Поэтому они интерпретируются DWX как знаковые. Теоретически и там величина числа может выйти за пределы VT_R8, и тогда будет использован VT_I8, который тоже неизвестен JScript'у. Но здесь это, думаю, маловероятно, поскольку не видно смысла использовать такие большие числа для условных идентификаторов. Разве что адрес объекта может использоваться как его идентификатор.

Кстати, wParam в обеих упомянутых вами функциях — это хэндл, поэтому вполне логично использовать для них тип "h".

96 (изменено: Parazit, 2018-03-29 13:45:40)

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

А как работать со структурами?
Примерчик один можно?

DWX = new ActiveXObject("DynamicWrapperX");
DWX.Register("kernel32.dll", "CreateDirectoryW", "i=wv", "r=l");
a = DWX.CreateDirectoryW("C:\\111", "");

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

97

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

А вам она там точно нужна? Можно просто нуль передать, типом "p".

DWX = new ActiveXObject("DynamicWrapperX");
DWX.Register("kernel32.dll", "CreateDirectoryW", "i=wp", "r=l");
a = DWX.CreateDirectoryW("C:\\111", 0);

А вообще под структуры выделяется память методом MemAlloc и в неё пишутся значения её членов через NumPut.

98

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

Хотелось бы увидеть любой пример, как работать со структурами.
Ведь большинство API функций, как раз, без структур не обходятся.

99 (изменено: maksim32, 2018-03-29 15:59:22)

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

Вот, как пример работы со структурой, с учётом битности хоста. Если нужно много работать со структурами, лучше написать класс, который будет вычислять offset'ы с учетом alignment'ов при инициализации нового типа структуры в зависимости от разрядности хоста и потом по ним получать/записывать данные. Потому что с этими магическими числами-смещениями с увеличением количества структур легко запутаться.

var DWX = new ActiveXObject("DynamicWrapperX.2");
DWX.Register("kernel32", "CreateDirectoryW", "i=wp", "r=l"); // LPCWSTR,LPSECURITY_ATTRIBUTES; BOOL

var NULL = 0, FALSE = 0;

// Если безопасность важна, то нужно выделить под структуру память и заполнить параметрами (причем для хостов разной битности будут разные размеры указателей, соответственно, разные смещения):
var bit = DWX.Bitness();
// для x32 размер структуры 12, т.к. sizeof(DWORD) {4 байта} + sizeof(LPVOID) {4 байта} + sizeof(BOOL) {4 байта}, т.е. все alignment'ы равны 0.
// для x64 размер структуры 24, т.к. sizeof(DWORD) {4 байта} + alignment {4 байта} + sizeof(LPVOID) {8 байт} + sizeof(BOOL) {4 байта} + alignment {4 байта}
var nLength = bit === 32 ? 12 : 24; // sizeof(SECURITY_ATTRIBUTES)
var lpSecAttrib = DWX.MemAlloc(nLength);
DWX.NumPut(nLength, lpSecAttrib, 0, "u"); // DWORD
DWX.NumPut(NULL, lpSecAttrib, bit === 32 ? 4 : 8, "p"); // LPVOID
DWX.NumPut(FALSE, lpSecAttrib, bit === 32 ? 8 : 16, "l"); // BOOL
var bResult = DWX.CreateDirectoryW("New folder (1)", lpSecAttrib);
if(bResult !== FALSE) WScript.Echo("OK (1)");
else WScript.Echo("Error (1)");
DWX.MemFree(lpSecAttrib);

// Если безопасность не важна, то функция может принимать и NULL:
var bResult = DWX.CreateDirectoryW("New folder (2)", NULL);
if(bResult !== FALSE) WScript.Echo("OK (2)");
else WScript.Echo("Error (2)");

100 (изменено: Parazit, 2018-03-29 16:41:23)

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

maksim32, спасибо.
А почему Bool равен 4 байта? Это результат выравнивания?
И для чего вообще делается выравнивание?