1 (изменено: DnsIs, 2012-03-23 07:34:35)

Тема: JScript: Асинхронный ping

Решил переложить код, на Jscript, столкнулся с трудностями.

/*
    Массив адресов/имён опрашиваемых машин
    В принципе, можно получать из сетевого окружения, с контроллера домена
    или перебором доступных адресов подсети */
var arrComputers = ["192.168.1.43", "192.168.1.42"],
    lngCount = arrComputers.length,
    objSWbemServicesEx = GetObject("winmgmts:{impersonationLevel=impersonate}!\\\\.\\Root\\CIMV2"),
    objSWbemSink = WScript.CreateObject("WbemScripting.SWbemSink", "Sink_");

for (strComputer in arrComputers) {
    /* В коллекции «objSWbemNamedValueSet» будем передавать адрес/имя хоста (замечание: в данном конкретном случае
     сие, в принципе, необязательно, поскольку класс Win32_PingStatus и так содержит
     свойство «.Address», но тут показана сама технология передачи данных в процедуру асинхронной обработки)*/
    var objSWbemNamedValueSet = WScript.CreateObject("WbemScripting.SWbemNamedValueSet");
    objSWbemNamedValueSet.Add ("HostName", strComputer);
    
    // Все запросы будут обрабатываться в единственной процедуре обработки
    objSWbemServicesEx.ExecQueryAsync (objSWbemSink, "SELECT * FROM Win32_PingStatus where Address = '" + strComputer + "'", null, null, null, objSWbemNamedValueSet);
}
// Ожидаем, пока не будут обработаны все асинхронные запросы
do {
    WScript.Sleep (100);
}
while (lngCount = 0);

objSWbemSink.Cancel();

WScript.Quit();

/*=============================================================================
 Процедура асинхронной обработки экземпляра объекта (замечание: в данном конкретном случае
 будет возвращаться единственный объект, однако, в большинстве случаев запросы
 возвращают множество объектов)*/
function  Sink_OnObjectReady(objWbemObject, objWbemAsyncContext) {
    strComputer = [];
    
    strComputer = objWbemAsyncContext.Item("HostName");
    
    if (!objWbemObject.StatusCode) {
        if (!objWbemObject.StatusCode) {
            WScript.Echo (strComputer + "\tOn" + "\tResponse time: " + objWbemObject.ResponseTime + " ms");
        } else {
            WScript.Echo (strComputer +"\tOff" + "\tStatus code: " + objWbemObject.StatusCode);
        }
    } else {
        WScript.Echo (strComputer + "\tNot found");
    }
}

/*=============================================================================
 Процедура, вызываемая при завершении асинхронной обработки*/
function Sink_OnCompleted(iHResult, objWbemErrorObject, objWbemAsyncContext) {
    objWbemAsyncContext.DeleteAll();
    objWbemAsyncContext = "";
    
    // Уменьшаем счётчик оставшегося числа асинхронных обработок
    lngCount = lngCount--;
}

Че то не фурычит. Помогите исправить пожалуйста.
И еще вопрос возник в процессе. Прототип ExecQueryAsync:

HRESULT ExecQueryAsync(
  [in]  const BSTR strQueryLanguage,
  [in]  const BSTR strQuery,
  [in]  long lFlags,
  [in]  IWbemContext *pCtx,
  [in]  IWbemObjectSink *pResponseHandler
);

5 параметров, но в исходном примере почему то 6:

objSWbemServicesEx.ExecQueryAsync objSWbemSink, "SELECT * FROM Win32_PingStatus WHERE ADDRESS = '" & strComputer & "'", , , , objSWbemNamedValueSet

Я слепой, да?

Нас невозможно сбить с пути, нам пофигу куда идти.

2 (изменено: Rumata, 2012-03-23 10:23:52)

Re: JScript: Асинхронный ping

DnsIs пишет:

И еще вопрос возник в процессе. Прототип ExecQueryAsync: <...> 5 параметров, но в исходном примере почему то 6

Смотрите из раздела Scripting API Objects, например http://msdn.microsoft.com/en-us/library … 85%29.aspx

objWbemObjectSet = .ExecQueryAsync( _
  [ ByVal objWbemSink ], _
  ByVal strQuery, _
  [ ByVal strQueryLanguage ], _
  [ ByVal iFlags ], _
  [ ByVal objwbemNamedValueSet ], _
  [ ByVal objWbemAsyncContext ] _
)

Вопрос на засыпку. В Вашем примере два хоста ["192.168.1.43", "192.168.1.42"]. Вы проверяли их доступность той vbscript-программой?

Ну и вот! Я по мере возможности стараюсь обращать внимание коллег на серьезную ошибку, которую допускают многие vb-программисты - неправильное использование циклов с массивами. Здесь я развернуто расписал - Javascript/JScript: правильное использование циклов for-in и for.

Вот фрагменты программы, которых затронула правка.


...
for (var i = 0; i < arrComputers.length; i++) {
    var strComputer = arrComputers[i];
...
// Ожидаем, пока не будут обработаны все асинхронные запросы
while (lngCount) {
    WScript.Sleep (100);
}
...
    // Уменьшаем счётчик оставшегося числа асинхронных обработок
    lngCount--;
}
( 2 * b ) || ! ( 2 * b )

3 (изменено: DnsIs, 2012-03-23 11:30:26)

Re: JScript: Асинхронный ping

Преогромнейешее спасибо, Rumata.

Хосты ["192.168.1.43", "192.168.1.42"], как раз это соседние компы, которые доступны.

lngCount--;  - Мой косяк, исправил уже потом. (хоть на выполнение кода и не влияет).

Цикл while, я тоже обычно пишу как и вы, сделал "do ... while...", что бы не отклонятся от оригинала (правда не знаю зачем это мне было нужно). Но вы помогли найти мне ошибку: просто "while (lngCount = 0);" меняем на "while (lngCount);" и все пашет.

И цикл "for...in", стараюсь не применять, но все по той же непонятной причине, сделал как в оригинале, не понимая до конца как он работает.
Почитаю вашу статейку, пойму. Спасибо за труды. 8)
Хотя после прочтения статьи, я начал писать все чаще вот так вот:

for    (i = arrComputers.length; --i >= 0;) {}

Ну и рабочий код

/*    Массив адресов/имён опрашиваемых машин
    В принципе, можно получать из сетевого окружения, с контроллера домена
    или перебором доступных адресов подсети */
var i,
    arrComputers = ["google.com", "www.ru", "localhost", "test"],
    lngCount = arrComputers.length,
    objSWbemServicesEx = GetObject("winmgmts:{impersonationLevel=impersonate}!\\\\.\\Root\\CIMV2"),
    objSWbemSink = WScript.CreateObject("WbemScripting.SWbemSink", "Sink_");

for    (i = arrComputers.length; --i >= 0;) {
/*   В коллекции «objSWbemNamedValueSet» будем передавать адрес/имя хоста (замечание: в данном конкретном случае
     сие, в принципе, необязательно, поскольку класс Win32_PingStatus и так содержит
     свойство «.Address», но тут показана сама технология передачи данных в процедуру асинхронной обработки)*/
    var objSWbemNamedValueSet = WScript.CreateObject("WbemScripting.SWbemNamedValueSet");
    objSWbemNamedValueSet.Add ("HostName", arrComputers[i]);
    
    // Все запросы будут обрабатываться в единственной процедуре обработки
    objSWbemServicesEx.ExecQueryAsync (objSWbemSink, "SELECT * FROM Win32_PingStatus where Address = '" + arrComputers[i] + "'", null, null, null, objSWbemNamedValueSet);
}

// Ожидаем, пока не будут обработаны все асинхронные запросы
while (lngCount) {
    WScript.Sleep (100);
} 

objSWbemSink.Cancel();
WScript.Quit();

/*=============================================================================
 Процедура асинхронной обработки экземпляра объекта (замечание: в данном конкретном случае
 будет возвращаться единственный объект, однако, в большинстве случаев запросы
 возвращают множество объектов)*/
function  Sink_OnObjectReady(objWbemObject, objWbemAsyncContext) {
    var strComputer = [],
        strComputer = objWbemAsyncContext.Item("HostName");
    if (!objWbemObject.StatusCode) {
        if (!objWbemObject.StatusCode) {
            WScript.Echo (strComputer + "\tOn" + "\tResponse time: " + objWbemObject.ResponseTime + " ms");
        } else {
            WScript.Echo (strComputer +"\tOff" + "\tStatus code: " + objWbemObject.StatusCode);
        }
    } else {
        WScript.Echo (strComputer + "\tNot found");
    }
}

/*=============================================================================
 Процедура, вызываемая при завершении асинхронной обработки*/
function Sink_OnCompleted(iHResult, objWbemErrorObject, objWbemAsyncContext) {
    objWbemAsyncContext.DeleteAll();
    objWbemAsyncContext = "";
     // Уменьшаем счётчик оставшегося числа асинхронных обработок
    lngCount--;
}

Так что можно в коллекцию добавить, как JScript-вариант.

Нас невозможно сбить с пути, нам пофигу куда идти.

4

Re: JScript: Асинхронный ping

DnsIs пишет:

ngCount--;  - Мой косяк, исправил уже потом. (хоть на выполнение кода и не влияет)

Влияет. См. сообщение №9


var x = 10;

x = x--;
alert(x);

x = (x--);
alert(x);

===========

DnsIs пишет:

Цикл while, я тоже обычно пишу как и вы, сделал "do ... while...", что бы не отклонятся от оригинала (правда не знаю зачем это мне было нужно). Но вы помогли найти мне ошибку: просто "while (lngCount = 0);" меняем на "while (lngCount);" и все пашет.

Ошибка не здесь.

while (lngCount = 0);

Это неверная запись оператора сравнения.

// присваивание
a = b

// сравнение
a == b

Надо было написать один из вариантов

while ( lngCount )

while ( lngCount != 0 )

===========

DnsIs пишет:

Хотя после прочтения статьи, я начал писать все чаще вот так вот

Выигрыш незначительный.

( 2 * b ) || ! ( 2 * b )

5

Re: JScript: Асинхронный ping

Rumata пишет:

Влияет. См. сообщение №9


var x = 10;

x = x--;
alert(x);

x = (x--);
alert(x);

Это означает лишь то, что у меня в списке процессов [пошел смотреть, убивать]... висит 9 шт "wscript.exe". А-ха-ха-ха-ха.

Хотя странно, вроде бы у декремента (--) приоритет выше чем у равно (=).


В остальном конечно же вы правы.

Нас невозможно сбить с пути, нам пофигу куда идти.

6

Re: JScript: Асинхронный ping

DnsIs пишет:

Хотя странно, вроде бы у декремента (--) приоритет выше чем у равно

Все верно, согласно приоритетам:

1. взять значение переменой x
2. уменьшить x на единицу
3. сохранить значение из п.1 в переменной x

( 2 * b ) || ! ( 2 * b )

7

Re: JScript: Асинхронный ping

Тогда так.

x = --x;

Ыыыыыыы. 8)

Нас невозможно сбить с пути, нам пофигу куда идти.