Здесь redir.exe - это вспомогательная утилитка, превращающая вызов
'TheConsoleApp.exe | redir.exe 2 AkelPad.exe'
в
'AkelPad.exe "Output of TheConsoleApp.exe"'
Но это, во-первых, некрасиво (мелькает консоль + AkelPad вызывается из командной строки) и, во-вторых, использует "костыли".
DV, общий алгоритм такой(на псевдо-псевдо коде, ибо под рукой нету работающего куска):
1. Создаем неименований пайп. CreatePipe (
&hRead, - конец чтения
&hWrite, - конец записи
в SECURITY_ATTRIBUTES устанавливаем наследование хендлов, либо иным фигом hWrite-у обеспечить валидность для детей )
2. Струкутра STARTUPINFO si;
si.dwFlags = STARTF_USESTDHANDLES|остальные флаги;
si.hStdOutput = hWrite - конец на запись пайпа.
3. CreateProcess( "Консольное.ехе", ....., &si, .... )
4. ReadFile( hRead, буффер куда читать из пайта искомое имя файла )
Infocatcher
Уже оговаривалось, что использование сторонних объектов и тем более ответственных за события по таймауту, может приводить к непресказуемым результатам.
DV
В 4.8.8 можно будет использовать следующий код:
Instructor wrote:Infocatcher
Уже оговаривалось, что использование сторонних объектов и тем более ответственных за события по таймауту, может приводить к непресказуемым результатам.
Хм, и правда.
Еще одно наблюдение: вроде, достаточно сделать вот так
И по ходу дела возник еще один вопрос: есть ли простой способ использовать SetTimer() в обычном скрипте (который сам по себе не остается висеть в памяти и сразу же завершается).
Не уверен насчет практического применения, но вот с тестированием без этого сложновато.
Infocatcher wrote:И по ходу дела возник еще один вопрос: есть ли простой способ использовать SetTimer() в обычном скрипте (который сам по себе не остается висеть в памяти и сразу же завершается).
Условие противоречит самой задаче Если скрипт сразу завершается, то как он среагирует на событие по таймеру?
Instructor wrote:Условие противоречит самой задаче Если скрипт сразу завершается, то как он среагирует на событие по таймеру?
Не-не-не. Сам по себе, без использования таймеров, скрипт сразу же завершается. Теперь добавляем таймер, но он не работает, потому как скрипт завершается до того, как он сработает. Вот можно ли это как-нибудь простым способом обойти?
https://gist.github.com/Infocatcher/9952951/revisions
1. Убираю использование new ActiveXObject("htmlfile"), но по-прежнему периодически падает.
2. Делаю заготовку для теймера, но сразу же дает ошибку на oSys.RegisterCallback().
(просто для информации)
Сегодня потребовалось из JScript использовать достаточно сложно конфигурируемый COM-объект, одним из свойств которого является то, что обычно называется ComArray. Здесь проблемы в том, что встроенный в JScript объект Array не совместим ни с ComArray, ни с VBArray (что невыгодно отличает JScript от VBScript). Здесь я привожу "внутреннее" решение для JScript без использования вспомогательного .vbs скрипта:
function getComArray(arr)
{
var dict = new ActiveXObject("Scripting.Dictionary");
for (i in arr)
{
dict.add(i, arr[i]);
}
return dict.Items();
}
// Usage Example:
var myObj = new ActiveXObject("My.Object");
myObj.Properties = getComArray(new Array("prop1", "prop2"));
Infocatcher wrote:Не-не-не. Сам по себе, без использования таймеров, скрипт сразу же завершается. Теперь добавляем таймер, но он не работает, потому как скрипт завершается до того, как он сработает. Вот можно ли это как-нибудь простым способом обойти?
Да, обойти можно. Чтобы не завершать скрипт, надо его не завершать. Т.е. использовать цикл сообщений (WindowGetMessage). Нужно понимать, что вызов "user32::SetTimer" никого не ждет, а сразу возвращается.
var hMainWnd=AkelPad.GetMainWnd();
var oSys=AkelPad.SystemFunction();
var lpTimerCallback;
var nIDEvent=10; //AkelPad.SendMessage(hMainWnd, 1319 /*AKD_UNIQUEID*/, 0, 0);
if (lpTimerCallback=oSys.RegisterCallback("TimerProc"))
{
oSys.Call("user32::SetTimer", hMainWnd, nIDEvent, 1000, lpTimerCallback);
AkelPad.ScriptNoMutex();
AkelPad.WindowGetMessage();
}
function TimerProc(hWnd, uMsg, nIDEvent, dwTime)
{
oSys.Call("user32::SetWindowText" + _TCHAR, hMainWnd, "MyTitle");
oSys.Call("user32::PostQuitMessage", 0);
oSys.Call("user32::KillTimer", hMainWnd, nIDEvent);
oSys.UnregisterCallback(lpTimerCallback);
}
1. Убираю использование new ActiveXObject("htmlfile"), но по-прежнему периодически падает.
Падения можно анализировать с итоговым вариантом, который преполагается, что работает.
2. Делаю заготовку для теймера, но сразу же дает ошибку на oSys.RegisterCallback().
TYPE_E_AMBIGUOUSNAME 0x8002802C - какие-то проблемы с наложением имен. GetTypeInfo не может получить информацию по функции. Видимо из-за использования функций в функциях. В данном случае указываем функцию явно:
var nIDEvent=AkelPad.SendMessage(hMainWnd, 1319 /*AKD_UNIQUEID*/, 0, 0) || 10;
?
Сейчас ведь это сообщение не распознается и должно вернуть 0.
Instructor wrote:Падения можно анализировать с итоговым вариантом, который преполагается, что работает.
А он и работает, просто текст в строке состояния статичный и не мигает.
То есть тупо убрано мигание, так что если реализовать его другим способом – вряд ли падения исчезнут, как мне кажется.
Заодно вопрос. Вот такое ведь тоже должно работать:
function getComArray(arr)
{
var dict = new ActiveXObject("Scripting.Dictionary");
for (i in arr)
{
dict.add(i, arr[i]);
}
return dict.Items();
}
// Usage Example:
var myObj = new ActiveXObject("My.Object");
myObj.Properties = getComArray(new Array("prop1", "prop2"));
Кстати, три момента:
1. for (i in arr) создаст глобальную переменную i, должно быть for (var i in arr):
Array.prototype.forEach = function() {};
var arr = ["a", "b"];
for(var i in arr)
WScript.Echo(i);
3. new Array("prop1", "prop2") эквивалентно простому ["prop1", "prop2"]. Тут вообще можно попасться на отличие между new Array(5) и new Array(5, 6) – в первом случае будет создан пустой массив с length == 5.
Infocatcher wrote:Сейчас ведь это сообщение не распознается и должно вернуть 0.
Да.
Заодно вопрос. Вот такое ведь тоже должно работать...
Возможно. У нас помоему только Infocatcher балуется такими конструкциями
Infocatcher wrote:Нельзя ли это приспособить для автоматизированного получения количества аргументов (чтобы вручную не указывать)?
Еще бы знать об этом свойстве при написании RegisterCallback Прийдется первый параметр совсем убрать.
Infocatcher wrote:Так и есть, падает.
Не воспроизводится. Из видимого я бы заменил
"AkelPad.WindowSubClass(hMainWnd, -> 1 /*WSC_MAINPROC*/", а после попробовал запустить под отладкой, чтобы найти момент ошибки.