Centrum skryptów - Systemy operacyjne

Jak wyświetlić komunikat lub zmienić wygląd kursora podczas wykonywania długiej operacji w aplikacji HTA?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

Cześć Skrypciarze!

Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy.

Jak wyświetlić komunikat lub zmienić wygląd kursora podczas wykonywania długiej operacji w aplikacji HTA?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Mam aplikację HTA, w której wykonuję wyszukiwanie, a następnie tworzę tabele z wynikami. Samo wyszukiwanie zajmuje około 30 sekund. Wyniki wyświetlane są w określonym zakresie i wyświetlają się dopiero po zakończeniu wyszukiwania. Chcę, aby po uruchomieniu wyszukiwania wyświetlany był komunikat („Searching…”), który byłby zastępowany przez tabelę po zakończeniu. Okazało się, że po uruchomieniu okna komunikatu, zakres aktualizuje się w oczekiwany sposób. Nie podoba mi się jednak używanie do tego celu okna komunikatu. Czy mogę to zrobić bez okna komunikatu?

-- MF

Cześć Skrypciarze! Pytanie

Cześć, MF. Większość mojego życia spędzam, skupiając się na pracy (przynajmniej się staram, ale czasem sam nie wiem, na czym ona polega). W każdym razie od czasu do czasu zdarza mi się na chwilę opuścić szurnięty świat skryptów i przenieść się do jeszcze bardziej szurniętego świata, czyli tzw. realu. Przykładowo, kilka tygodni temu organizacja zajmująca się nadużywaniem prawa w USA Michigan Lawsuit Abuse Watch (j.ang.), ogłosiła zwycięzcę corocznego konkursu na najbardziej absurdalne ostrzeżenie. Zwycięzca roku 2007? Tabliczka z ostrzeżeniem umieszczona na małym traktorze, zalecająca jego użytkownikom unikanie śmierci.

To naprawdę jest śmieszne; oczywiście producenci traktorów boją się, że ktoś będzie używał ich maszyny i umrze, a oni zostaną pozwani, ponieważ nikt nie powiedział, że nie wolno umierać podczas jazdy na traktorze. Tak się teraz zastanawiam, to całkiem dobra rada; a tak w ogóle to tabliczki z takim ostrzeżeniem powinny znajdować się na praktycznie wszystkim. W końcu „unikaj śmierci” to rada przydatna nie tylko dla kierowców traktorów.

Jedyny problem polega na tym, że ani na chwilę nie możemy przestać uważać i cały czas musimy się mieć na baczności (dotyczy to także osób, które nie jeżdżą tymi samymi drogami i nie parkują na tym samym parkingu, co nasza Redaktorka.) Szczerze mówiąc, nie pozostaje nam nic innego, jak tylko unikać śmierci i temu poświęcać całą naszą uwagę. Dlatego też, dzisiejsza odpowiedz będzie bardzo prosta, dzięki temu jednym okiem będę się wystrzegał nieszczęść, a drugim spoglądał na następujący kod aplikacji HTA:

<SCRIPT Language = "VBScript">

    Sub Subroutine1

        DataArea.InnerHTML = "Searching ...."

        document.body.style.cursor = "wait"

        idTimer = window.setTimeout("Subroutine2", 2000, "VBScript")

    End Sub



    Sub Subroutine2

        window.clearTimeout(idTimer)



        strComputer = "."

        Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

        Set colEvents = objWMIService.ExecQuery("Select * From Win32_NTLogEvent")



        For Each objProcess in colEvents

            i = i + 1

        Next



        DataArea.InnerHTML = "Total events: " & i

        document.body.style.cursor = "arrow"

    End Sub

</SCRIPT>



<body>

    <input type="button" value="Count Events" onClick="Subroutine1"><p>

    <span id=DataArea>This is a span named DataArea.</span>

</body>

Wiem, że wielu z was już próbowało zrobić coś podobnego i wszyscy napotykali na ten sam problem. Wywołujecie podprocedurę, która ma za zadanie zmienić wartość zakresu lub może zmienić kursor na klepsydrę (taki mały bonus, który dorzuciłem do dzisiejszej rubryki). Po wykonaniu tej czynności podprocedura powinna pobrać pewne dane, co może chwilę potrwać. Następnie te dane zastępują komunikat w zakresie i kursor zmienia się ponownie w strzałkę. Łatwe i przyjemne.

Z wyjątkiem jednej rzeczy: nie działa. Początkowa wiadomość nigdy nie zostaje wyświetlona i kursor nigdy nie zamienia się w klepsydrę. Aplikacja HTA po prostu ignoruje niektóre wiersze kodu.

Macie rację: wcale nie takie łatwe, ani przyjemne.

Co się dzieje w rzeczywistości? Cóż, prawdę mówiąc, nie mam całkowitej pewności. Ale nie to jest najważniejsze. Ważne jest to, że znam sposób, jak obejść ten problem. I jak dotąd nikomu nic się nie stało.

Więc co tak naprawdę robimy? Na początek być może zauważyliście, że mamy całkiem prostą aplikację HTA; składa się ona z przycisku oznaczonego Count Events oraz zakresu o identyfikatorze DataArea. Zasada działania aplikacji HTA jest całkiem prosta: kiedy użytkownik kliknie przycisk, uruchamia się podprocedura o nazwie Subroutine1. Ona z kolei uruchamia proces, w którym wszystkie zdarzenia w dzienniku zdarzeń są podliczane, a ostateczny wynik jest wyświetlany w zakresie. Podliczanie zdarzeń w dziennikach zdarzeń może trochę potrwać; dlatego też wyświetlany jest komunikat Searching…, a kursor zmienia się w klepsydrę.

Są jeszcze dwie rzeczy, których oczekują wszyscy twórcy aplikacji HTA; chodzi o to, że aplikacje HTA nigdy nie wyświetlają komunikatów, ani nie zmieniają kursora. Dlaczego? Tego też nie wiem na pewno. Ale wiem, co zrobić, żeby HTA wykonała to, czego się od niej oczekuje.

Jak widać, podprocedura Subroutine1 nie jest skomplikowana:

Sub Subroutine1

    DataArea.InnerHTML = "Searching ...."

    document.body.style.cursor = "wait"

    idTimer = window.setTimeout("Subroutine2", 2000, "VBScript")

End Sub

W wierszu 1 zmieniamy właściwość InnerHTML zakresu na komunikat Searching …. W wierszu 2 ustawiamy włączamy kursor oczekiwania systemu (w większości wersji systemu Windows jest to klepsydra, natomiast w systemie Vista jest to dziwny, niebieski zawijas.). Przechodzimy od razu do wiersza 3:

idTimer = window.setTimeout("Subroutine2", 2000, "VBScript")

Używamy teraz metody setTimeout w celu utworzenia nowego czasomierza o nazwie idTimer. W aplikacji HTML czasomierz umożliwia nam tymczasowe zatrzymanie skryptu, w podobny sposób, co polecenie Wscript.Sleep. Jak widzimy, do metodzie setTimeout przekazujemy trzy parametry:

  • Subroutine2. Nazwa podprocedury, którą chcemy uruchomić po zakończeniu pracy czasomierza.
  • 2000. Jest to czas wyrażony w milisekundach, który ma upłynąć, zanim czasomierz wywoła podprocedurę Subroutine2. Minęło już trochę czasu, odkąd ostatni raz zajmowaliśmy się milisekundami, więc oto wskazówka: w każdej sekundzie jest 1000 milisekund. Zatrzymanie skryptu na 2000 milisekund to tak naprawdę jego zatrzymanie na 2 sekundy.
  • VBScript. Parametr wymagany, informujący skrypt, że podprocedura Subroutine2 została napisana w języku VBScript.

Innymi słowy, kliknięcie przycisku powoduje wykonanie podprocedury Subroutine1. W czasie działania podprocedura wyświetla okna komunikatu w zakresie, zmienia kursor, a następnie tworzy czasomierz o nazwie idTimer. Jedynym zadaniem czasomierza idTimer jest odczekanie 2 sekund i wywołanie podprocedury Subroutine2. Dlaczego? Ponieważ samo wywołanie jednej podprocedury, zmiany zakresu i kursora, zatrzymanie skryptu na kilka sekund, a następnie wywołanie drugiej podprocedury w celu pobrania danych załatwia całą sprawę: zakres zostaje zaktualizowany, kursor się zmienia i życie jest takie, jakie powinno być.

Co się więc dzieje w podprocedurze Subroutine2? Na początek używamy metody clearTimeout w celu zagwarantowania, że nasz czasomierz i (a także nasza podprocedura) uruchomi się tylko raz:

window.clearTimeout(idTimer)

Teraz używamy standardowego kodu WMI w celu pobrania kolekcji wszystkich zdarzeń z dzienników zdarzeń. Następnie uruchamiamy pętlę For Each, która przejdzie przez każdy element w kolekcji i podliczy wszystkie zdarzenia po kolei:

For Each objProcess in colEvents

    i = i + 1

Next
Słuszna uwaga: są lepsze sposoby na policzenie liczby zdarzeń we wszystkich dziennikach zdarzeń. (Więcej informacji znajduje się w przewodniku Microsoft Windows 2000 Scripting Guide (j.ang).). Wybraliśmy tę właśnie, ponieważ potrzebowaliśmy kodu, którego wykonanie potrwa około minuty. Gdybyśmy podliczali coś innego, na przykład liczbę procesów uruchomionych na komputerze, wszystko stałoby się tak szybko, że moglibyśmy nie zauważyć, czy komunikat został wyświetlony, a kursor zmieniony.

Po podliczeniu wszystkich zdarzeń w dziennikach wyświetlamy te dane w zakresie (czyli tam, gdzie MF wyświetli tabelę) i zmieniamy kursor z powrotem na strzałkę:

DataArea.InnerHTML = "Total events: " & i

document.body.style.cursor = "arrow"

I to wszystko, co musimy zrobić w tej kwestii.

Zachęcam do obejrzenia innych tabliczek ostrzegawczych, biorących udział w konkursie. Mnie osobiście najbardziej podoba się zdobywca drugiego miejsca – ostrzeżenie na metce koszuli: „Zdjąć przed prasowaniem”. Podoba mi się ona głównie dlatego, że znałem takiego jednego gościa, który poparzył się prasując koszulę, którą miał na sobie. Nigdy się nie przyznał, że poparzył się właśnie w ten sposób, no ale kto by się do czegoś takiego przyznał?

 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne