Режим сна для сценариев HTA

В нескольких моих скриптах .HTA, которые я создал, мне была нужна команда VBScript WScript.Sleep, которая просто ожидает несколько миллисекунд без использования процессора. И когда я просматриваю Интернет, кажется, что я не единственный, кто ищет это:

https://www.google.nl/search?q=hta+sleep

(Могу поспорить, что если вы прочитаете это, вам, вероятно, также понадобится (ред.))

Лучшее решение, которое я смог найти, это решение, использующее команду PING. Но особенно для ситуации, когда нужно было просто приостановить выполнение сценария на несколько 100 мс, это решение выглядит странно, поскольку использует внешнюю команду и запускает все виды (сетевых) процессов, которые вряд ли имеют какое-либо отношение к соответствующему сценарию .HTA.

Поэтому первое, что мне пришло в голову, - это использовать класс WMI Win32_PingStatus, чтобы избежать внешней команды, но затем я начал задаваться вопросом, почему не полностью основывать ее на WMI. Мне потребовалось несколько часов, чтобы получить правильные классы и методы WMI, но в конце концов мне это удалось ...

Ответы на вопрос(4)

Решение Вопроса

При написании HTA 's вы должны думать асинхронно. Попробуйте переписать свой код для использованияwindow.setTimeout, В следующем примере я буду использоватьwindow.setTimeout чтобы звучал звонок каждые 2 секунды:





Bell Test

Option Explicit
Dim objWShell
Set objWShell = CreateObject("WScript.Shell")
Sub DoPing
    divText.innerText = Now
    objWShell.Run "%COMSPEC% /c ECHO " & Chr(7), 0, False
    window.setTimeOut "DoPing", 2000
End Sub
Sub window_OnLoad
   window.ResizeTo 240,130
   DoPing
End Sub



TEST


Sub Sleep(iMilliSeconds)

    With GetObject("winmgmts:\\.\root\cimv2")
        With .Get("__IntervalTimerInstruction").SpawnInstance_()
            .TimerId = "Sleep"
            .IntervalBetweenEvents = iMilliSeconds
            .Put_()
        End With
        .ExecNotificationQuery("SELECT * FROM __TimerEvent WHERE TimerId='Sleep'").NextEvent
    End With

End Sub

Добавлено 2015-02-11:

К сожалению, эта функция нене работает при использовании Internet Explorer 10 (см. комментарии ниже). Если установлен Internet Explorer 11, он работает, если вы запускаете HTA от имени администратора.

 iRon01 июн. 2013 г., 19:00
Вы'Правильно, разница на самом деле IE, IE8 работает нормально ... (я продолжу исследовать это на следующей неделе)
 Teemu01 июн. 2013 г., 11:49
Интересно, но я получаюAccess denied при выполнении.Put_(), Есть идеи...?
 Teemu03 июн. 2013 г., 09:48
Работает также с IE9, но не с IE10. Я пытался поиграть с безопасностью WMI, но безрезультатно. Это'Я найду время, чтобы ознакомиться со всем этим, это кажется довольно сложным ...
 iRon01 июн. 2013 г., 18:07
я узнаю это из некоторых других HTA со встроенными вызовами WMI. этоWindows 8 (Я создал разрез в Windows 7 и действительно только что подтвердил ошибку в Windows 8). Обходной путь - запустить его от имени администратора, но это делает решение в целом менее интересным. Нужно расследовать, или кто-нибудь еще знает, как обойти это?
 iRon03 июн. 2013 г., 17:13
Я провел небольшое расследование и тестирование сегодня, но, к сожалению, нетЯ нашел решение для IE10. Лично я нене думаю, что это правильно, что мне нужны повышенные права для установки таймера ...
 iRon04 июн. 2013 г., 10:53
Я подал отчет об ошибке для IE10 в Microsoft:connect.microsoft.com/IE/feedback/details/789421
 Teemu01 июн. 2013 г., 18:30
На самом деле я'м с использованием Windows7 (с IE10).Это код WMI работает в приложении, я проверил вашsleep() функция. Я попробовал с VBS, а также перевел ваш код на JavaScript, но оба способа я получаюAccess denied ошибка.

У меня была такая же проблема с HTA. Мое решение с VBS ...

Sub sleep (Timesec)
    Set objwsh = CreateObject("WScript.Shell") 
    objwsh.Run "Timeout /T " & Timesec & " /nobreak" ,0 ,true
    Set objwsh = Nothing
End Sub

' example wait for 3 seconds
sleep 3

Подпрограмма вызовет команду оболочки, свернутую и без использования клавиатуры. Разрешается только ^ C, но это не будет предоставлено пользователю в этой ситуации.

Подожди (2000)паузы 2 секунды

Sub Wait(Time)
  Dim wmiQuery, objWMIService, objPing, objStatus
  wmiQuery = "Select * From Win32_PingStatus Where Address = '1.1.1.1' AND Timeout = " & Time
  Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
  Set objPing = objWMIService.ExecQuery(wmiQuery)
  For Each objStatus in objPing
  Next
End Sub

Ваш ответ на вопрос