Управління ходом виконання сценарію за допомогою IE

  1. Перехоплення подій IE
  2. коректне завершення
  3. Використання сценарію IE Control Window
  4. Лістинг 1. Сценарій для запуску і завершення роботи IE

Забезпечити сценарій графічним інтерфейсом можна, скориставшись можливостями Windows Script Host (WSH). WSH дозволяє встановлювати з'єднання між джерелами подій, що генеруються створеними ним об'єктами COM, і спеціальними функціями всередині сценарію. Сценарій може передати дані на сервер COM і продовжити своє виконання. Коли в результаті деякого події відбувається помилка в сервері COM, в сценарії автоматично виконується процедура обробки даної події.

В принципі, для надання графічного інтерфейсу сценарієм можна використовувати практично будь-який COM-об'єкт, який має графічний інтерфейс і генерує деяка подія при виході. Особисто я віддаю перевагу Microsoft Internet Explorer (IE), оскільки даний компонент є практично на всіх Windows-комп'ютерах, а його універсальність може виявитися досить корисною для розширення функціональності сценаріїв. Спочатку я роз'ясню викладену ідею на прикладі простої форми, після чого буде описаний деякий пакувальник, що надає пару нескладних функцій управління ходом виконання, які далі ви зможете використовувати в будь-якому сценарії.

Слід зазначити, що даний пакувальник не є засобом на всі випадки життя. Зокрема, коли через нього здійснюється зупинка сценарію, то при цьому не виконуються ніякі процедури очищення. Він всього лише формує вікно для перегляду ходу виконання будь-якого запущеного сценарію, а також надає можливість для його екстреної зупинки. Недоліком пропонованого рішення є також і те, що для запуску IE необхідна достатня кількість пам'яті, що може стати істотною проблемою при його запуску на комп'ютерах з обмеженою кількістю пам'яті і на низькошвидкісних системах. Однак накладні витрати, пов'язані з виділенням пам'яті різко скорочуються, якщо таким же чином запускається друга копія IE. Якщо при першому запуску IE зі сценарію для нього потрібно 9300 Кб оперативної пам'яті, то другий запущений екземпляр IE вимагає вже 500кб пам'яті або трохи більше, а кожна наступна запущена копія IE вимагає вже близько 200Кб додаткової пам'яті. При цьому IE не виконує будь-яких дій, тому сам по собі він практично не використовує ресурси процесора.

Перехоплення подій IE

Компонент IE має не залежить від версії програмний ідентифікатор (ProgID) InternetExplorer.Application, а також може генерувати кілька подій, одне з яких називається onQuit і відбувається при завершенні роботи IE шляхом натискання кнопки Close, комбінації клавіш Alt + F4 або при виборі в меню File пункту Exit. Зупинка сценарію відбувається при закритті запущеного їм примірника IE, для чого використовуються наявні в WSH можливості обробки подій.

Базовий код для запуску і зупинки IE наведено в лістингу 1 . Як видно з фрагмента, зазначеного міткою A, для запуску IE використовується метод CreateObject об'єкта WScript (але не внутрішній метод VBScript CreateObject). Метод WScript.CreateObject відрізняється від звичайного CreateObject тим, що він дозволяє працювати з подіями в сценаріях. При перегляді фрагмента коду з міткою A у вас може виникнути питання, для чого потрібен аргумент "IE_". В описі методу WScript.CreateObject, наявному в документації ( http://msdn.microsoft.com/library/en-us/script56/html/wsmthcreateobject.asp ), Сказано, що необов'язковий аргумент strPrefix є "строкове значення, що представляє собою префікс функції". Наприклад, якщо аргумент strPrefix має значення MYOBJ_, і об'єкт генерує подія з ім'ям OnBegin, тоді Windows Script Host викличе наявну в сценарії процедуру MYOBJ_OnBegin. Метод CreateObject повертає покажчик на інтерфейс IDispatch об'єкта. Зверніть увагу на те, що в оригінальній документації міститься помилка, яку я тут виправив. У документації пропущений символ підкреслення при першій згадці MYOBJ. До речі кажучи, якщо вас цікавить, чому в якості останнього символу префікса використовується саме знак підкреслення, а не якийсь інший символ, то відповідь полягає в тому, що так склалося історично. У Visual Basic (VB), як і в інших середовищах програмування, автоматично створюють процедури обробки (приймачі) подій, породжуваних об'єктами, ім'я приймача події традиційно містить ім'я об'єкта, приєднане через символ підкреслення.

А що нам каже документація? Тільки те, що ми можемо включати в сценарії свої обробники подій. Отже, IE породжує подія onQuit, для відповідних функцій оголошений префікс IE_, тому можна включити в сценарій процедуру IE_onQuit. В результаті, якщо IE генерує подія onQuit, то сценарій, незалежно від того, що він робить в даний момент, негайно викликає процедуру IE_onQuit (див. Фрагмент коду з міткою C лістингу 1). Слід зазначити, що можливість перехоплення подій, що генеруються створеними в сценарії об'єктами, може мати багато практичних застосувань. Зокрема, це дозволяє мати механізм примусового завершення в сценаріях, які перейшли в нескінченний цикл або виконуються надмірно довго.

Середня частина сценарію (код, зазначений на лістингу 1 міткою B) починається з того, що вікно IE робиться видимим. Internet Explorer, як і багато інших сервери COM, не робиться видимим при запуску автоматично. Далі запускається цикл, який, будучи наданий сам собі, є нескінченним. Команда wscript.sleep є стандартним засобом, застосовуваним в тих випадках, коли сценарій повинен виконувати циклічну перевірку, очікуючи деякого події. Тут слід зазначити, що якщо не передбачити в циклі наявність періодичних пауз, то він може поглинути значну частину ресурсів процесора.

При запуску сценарію через CScript або WScript відкривається вікно IE. Якщо при цьому подивитися на список диспетчера задач, то там буде відображатися запущений сервер сценаріїв (відповідно, CScript або WScript). При закритті вікна IE на екрані відображається слово exiting (вихід). Якщо сценарій був запущений через сервер CScript, то після закриття вікна IE ім'я CScript відразу ж зникне зі списку запущених завдань. Якщо ж для запуску сценарію використовувався сервер WScript, то тоді, для того щоб WScript завершив виконання, потрібно закрити вікно WScript.Echo.

коректне завершення

Хоча описана технологія дозволяє досить просто реалізувати можливість аварійного завершення сценарію, вона проте має ряд недоліків. По-перше, при запуску декількох повнорозмірних копій IE засмічується робочий стіл і займається значна площа екранного простору. По-друге, всі ці вікна IE є повністю функціональними, в результаті чого може виникнути ситуація, коли користувач ненавмисно скористається одним з вікон як звичайним браузером, після чого закриє його. Результатом цього з'явиться непередбачувана поведінка того сценарію, з якого було запущено дане вікно IE. І ще одна проблема полягає в тому, що якщо на комп'ютері одночасно запущено кілька сценаріїв, то визначити якому з них належить те чи інше вікно IE досить важко.

Всі ці незручності можна легко усунути, якщо скористатися можливостями об'єктної моделі IE. Коли ви почнете працювати з IE, вас здивує те багатство і різноманітність можливостей, яке надає його об'єктна модель для ефективного розширення можливостей WSH. У сценарії на лістингу 2 показаний приклад того, як можна організувати запуск IE за допомогою нескладного вбудованого коду, який можна далі використовувати в будь-якому сценарії. В даному прикладі усунені всі перераховані вище проблеми, і дуже малоймовірно, що його застосування може якось негативно позначитися на працездатності вашого сценарію в цілому.

Взаємодія об'єктної моделі IE з іншою процедурою може бути організовано дуже просто. Замість того щоб створювати пряме посилання на об'єкт IE, як було показано в прикладі лістингу 1, у фрагменті коду, позначеного в лістингу 2 міткою A, спочатку оголошується загальнодоступна (public) змінна IE, а потім викликається процедура з ім'ям IEScriptWindow. Обробник події IE_onQuit (Лістинг 2, код з міткою B) здійснює примусовий вихід з сценарію при закритті користувачем вікна IE. Сама процедура IEScriptWindow, настроює параметри вікна IE, призначеного для контролю виконання сценарію, позначена на лістингу 2 міткою C. Для того щоб використовувати приклад з лістингу 2 в існуючому сценарії потрібно всього лише вставити код, позначений міткою A, перед текстом основного сценарію, а код позначений мітками B і C після тексту сценарію.

Процедура IEScriptWindow є приклад того, як можна працювати з деякими властивостями і методами об'єкта IE. Даний приклад може послужити відправною точкою для будь-яких ваших ідей щодо подальшої модифікації пропонованого програмного інструменту. Більш докладно властивості і методи IE описані в документації Microsoft Developer Network (MSDN) Library, яка доступна за адресою: http://msdn.microsoft.com/workshop/browser/webbrowser/reference/objects/internetexplorer.asp .

Міткою D на лістингу 2 позначений фрагмент коду, який наказував би IE відобразити порожню локальну сторінку, після чого запускається цикл, що виконується до моменту повної готовності IE до роботи. Даний підхід є доброю практикою, оскільки компонент IE є скоріше деяку сукупність слабосвязанних компонентів, ніж просто один додаток. Будь-яке вікно IE містить в собі документ, який має тіло (body), що містить, в свою чергу набір певних елементів. Сам IE запускається і починає працювати до того, як повністю инициализируется міститься в ньому документ, навіть якщо за замовчуванням використовується порожня сторінка. Відображення порожньої сторінки до моменту повної готовності IE до роботи запобігає можливість передчасного завершення сценарію з видачею невиразного повідомлення про помилку. Коли IE повністю готовий до роботи, його властивість ReadyState приймає значення READYSTATE_COMPLETE.

За допомогою коду, позначеного на лістингу 2 міткою E, видаляються непотрібні елементи вікна, що необхідно для виключення можливості випадкового використання даного примірника IE в якості браузера для навігації по Web-сайтів. Кожна з показаних тут рядків коду видаляє з вікна рядка адреси і меню, а також панель інструментів і рядок стану, так що, як ви можете бачити, ця копія IE буде мати досить нестандартний вид.

Наступним кроком є ​​завдання розмірів вікна IE, що ілюструє код, позначений на лістингу 2 міткою F. Перший рядок в даному фрагменті служить для того щоб не дозволити абонентам натискання кнопки Maximize і, відповідно, розтягування вікна IE на весь екран (при цьому можливості згортання і відновлення вікна зберігаються). В принципі ви можете встановити значення ширини і висоти вікна рівними 0, в результаті чого на екрані буде видно тільки значок в панелі завдань, але я віддаю перевагу задавати висоту 52 пікселя і ширину 200 пікселів. Якщо задати висоту в 32 пікселя, тоді на екрані відобразиться тільки рядок заголовка, в той час як трохи більший розмір вікна по висоті дозволить відображати в тілі документа спливає текст. Ширина вікна, рівна 200 пікселів, достатня для відображення в цьому вікні імені файлу з восьми символів і трьох символів розширення навіть в тому випадку якщо на комп'ютері за замовчуванням включений режим відображення з великими шрифтами.

Добре б, щоб у вікні IE була також представлена ​​інформація про те, який саме сценарій зараз запущений. Для цього можна скористатися властивістю Document.Title, присвоївши йому значення, що відповідає описам повного шляху до запускається сценарієм, однак при цьому може знадобитися розширення рядка заголовка, до того ж потрібно буде попередньо оцінити довжину рядка, щоб опис шляху могло там повністю поміститися. Слід також враховувати і те, що довжина рядка заголовка вікна IE не може бути більше 95 символів. У першому рядку фрагмента коду з міткою G лістингу 2 в якості заголовка встановлюється ім'я файлу сценарію: Wscript.ScriptName. Якщо для своїх сценаріїв ви використовуєте стандартний спосіб іменування файлів (вісім символів для імені і три для розширення), то в цьому випадку ім'я файлу прекрасно впишеться в рядок заголовка.

Для виведення додаткової інформації в сценарії використовується властивість Body.Title. Для більшості елементів Web-сторінки їх властивість Title може бути використано для відображення спливаючого тексту, що з'являється, коли користувач підводить і затримує на даному елементі вказівник. Я задіяв властивість Body.Title для відображення часу запуску сценарію і повного шляху до нього, при цьому IE відображає цю досить об'ємну інформацію тільки тоді, коли курсор миші затримується на невеликому елементі тіла.

І, нарешті, фрагмент з міткою G, який доповнює сценарій ще двома особливостями. По-перше, вікно IE автоматично забезпечується смугами прокрутки. Однак на вікні малого розміру, яке використовується в нашому сценарії, ці смуги прокрутки виглядають досить потворно, тому я приховав їх, привласнивши властивості Body.Scroll значення No. Крім цього, було додано останній штрих, який полягає в тому, щоб зробити це вікно видимим.

При запуску сценарію, наведеного в лістингу 2, на екран виводиться вікно, показане на рисунку 1. Як видно з цього малюнка, вікно IE має розмір, достатній для відображення в рядку заголовка імені сценарію з деяким запасом, при цьому кнопка Maximize неактивна, а кнопки Minimize і Close доступні. Коли користувач підводить покажчик миші в область тіла вікна і затримує його там, то у спливаючому вікні відображається час запуску сценарію і повний шлях до нього.

Дуже добре також і те, що код запуску IE дуже просто інтегрується в будь-які сценарії. Для того щоб запустити описане вікно IE з вашого сценарію, досить включити в нього процедури IE_onQuit і IEScriptWindow. Цим буде забезпечено запуск процедури IEScriptWindow на початку вашого сценарію.

Використання сценарію IE Control Window

Вікно IE Control Window найкращим чином підходить для застосування при обробці пакетних завдань, що виконуються тривалий час, роботу яких можна безпечно перервати в будь-який момент. Однією з таких задач є сценарій, що обробляє велику кількість документів. В лістингу 3 показаний приклад сценарію такого типу. Він переглядає каталог, ім'я якого визначається змінної targetPath, а потім стискає все знаходяться в ньому стиснені документи, що мають дату створення, більш ранню, ніж та, яка задається змінною maxAge. Зміст даного прикладу полягає не в технічних деталях, а в тому, що є практичне завдання, яка може виконуватися значний час, і може виникнути необхідність її зупинки.

Для того щоб забезпечити сценарій стиснення файлів графічним інтерфейсом потрібно просто вставити його текст в середину сценарію, формує вікно IE. Як показано в лістингу 4 , Код сценарію стиснення файлів (позначений в лістингу 4 міткою A) вставляється в сценарій запуску вікна IE відразу після виклику процедури IEScriptWindow. Тут є ще один додатковий нюанс: в сценарій стиснення файлів відразу за останнім рядком його основного тексту додана команда IE.Quit (фрагмент з міткою B лістингу 4), що закриває вікно IE по завершенні роботи даного сценарію, що служить індикатором того, що сценарій стиснення файлів завершив роботу.

Безумовно, можливість примусової зупинки потрібно далеко не для всіх сценаріїв. Наприклад, якщо раптово зупинити роботу сценарію, що виконує складні завдання адміністрування, то виникли в результаті цього побічні ефекти будуть непередбачувані. Але при реалізації завдань, подібних розглянутим нами процедурі стиснення файлів, які можна без фатальних наслідків зупиняти і знову запускати, використання вікна IE для контролю ходу виконання сценарію може виявитися вельми корисним.

Лістинг 1. Сценарій для запуску і завершення роботи IE
Option Explicit Dim IE 'BEGIN Callout A Set IE = WScript.CreateObject (_ "InternetExplorer.Application", "IE_")' END Callout A 'BEGIN Callout B IE.Visible = True Do wscript.sleep 10 Loop' END Callout B ' BEGIN Callout C Sub IE_onQuit WScript.Echo "exiting" WScript.Quit End Sub

'END Callout C

Лістінг 2. Сценарій IE Control Window
Option Explicit 'BEGIN Callout A Public IE IEScriptWindow' END Callout A BEGIN COMMENT 'Початок тела основного сценарію. END COMMENT Do WScript.Sleep 10 Loop BEGIN COMMENT 'Кінець тела основного сценарію. END COMMENT 'BEGIN Callout B Sub IE_onQuit WScript.Quit End Sub' END Callout B 'BEGIN Callout C Sub IEScriptWindow () BEGIN COMMENT' Як сервер сценаріїв Використовують WScript або CScript. END COMMENT CONST READYSTATE_COMPLETE = 4 BEGIN COMMENT 'УВАГА: Якщо потрібно обробляти події,' то необхідно використовувати метод WScript. CreateObject 'і задати відповідний префікс для події. END COMMENT Set IE = WScript.CreateObject (_ "InternetExplorer.Application", "IE_") BEGIN COMMENT 'В деяких випадках IE готовий до роботи не одразу після запуску,' тому для його ініціалізації включаємо навігацію, 'потім запускаємо цикл очікування до моменту , 'коли статус IE прийме значення READYSTATE _ COMPLETE. END COMMENT 'BEGIN Callout D IE.Navigate "about: blank" Do until IE.ReadyState = READYSTATE_COMPLETE WScript.Sleep 10 Loop' END Callout D BEGIN COMMENT 'Видаляємо непотрібні елементи призначеного для користувача інтерфейсу. END COMMENT 'BEGIN Callout E IE.AddressBar = False IE.MenuBar = False IE.ToolBar = False IE.StatusBar = False' END Callout E BEGIN COMMENT 'Задаємо розміри вікна. 'Для деяких дисплеїв може знадобитися визначити вікна по висоті. END COMMENT 'BEGIN Callout F IE.Resizable = False IE.Height = 52 IE.Width = 200' END Callout F BEGIN COMMENT 'Формуємо заголовок і спливає текст підказки в тілі вікна. END COMMENT 'BEGIN Callout G IE.Document.Title = WScript.ScriptName & String (30, "_") IE.Document.Body.Title = "Start Time:" & Now & vbCrLf _ & "Script:" & WScript. ScriptFullName IE.Document.Body.Scroll = "No" IE.Visible = True 'END Callout G End Sub' END Callout C
Лістинг 3. Сценарій стиснення файлів
'Бітова маска стиснення. Const Compressed = & H800 Public fso, sh, MaxAge Dim targetPath MaxAge = 90 targetPath = "D: public" Set fso = CreateObject ( "Scripting.FileSystemObject") Set sh = CreateObject ( "WScript.Shell") RecurseCompress targetPath Sub RecurseCompress (sFol ) Dim fld, files, folder, file, cmd Dim isOld, isNotCompressed, isDocument Set fld = fso.GetFolder (sFol) set files = fld.files for each file in files isOld = CBool ​​((Now () - file.DateLastAccessed) > MaxAge) isNotCompressed = CBool ​​(file.Attributes isDocument = CBool ​​(InStr (file.type, "Document")) 'Стисканню піддаються тільки старі стиснені документи. If isOld and isDocument and isNotCompressed Then' Зверніть увагу 'на додаткові зовнішні лапки,' які необхідні, щоб обробляти файли, 'опис шляхів до яких містить прогалини. cmd = "% COMSPEC% / c compact / c" "" & fi le.path & "" "" 'При запуску зовнішньої команди використовуються' режим приховування (0) вікна командного рядка 'і режим очікування (true)' завершення виконання команди, 'таким чином, дані на екран не виводяться,' що вивільняє ресурси ЦПУ . Sh.Run cmd, 0, true end if next 'Цикл, необхідний для рекурсивного перегляду підкаталогів. If fld.SubFolders.Count> 0 Then For Each folder In fld.SubFolders RecurseCompress folder.Path Next End If End Sub
Лістинг 4. Впровадження сценарію стиснення файлів в IE Control Window
Option Explicit Public IE IEScriptWindow 'BEGIN Callout A' Текст з міткою A являє собою зовнішній сценарій, 'впроваджуваний в сценарій IE control window. 'Бітова маска стиснення. Const Compressed = & H800 Public fso, sh, MaxAge Dim targetPath MaxAge = 90 targetPath = "D: Public" Set fso = CreateObject ( "Scripting.FileSystemObject") Set sh = CreateObject ( "WScript.Shell") RecurseCompress targetPath 'BEGIN Callout B IE.Quit 'END Callout B Sub RecurseCompress (sFol) Dim fld, files, folder, file, cmd Dim isOld, isNotCompressed, isDocument Set fld = fso.GetFolder (sFol) set files = fld.files for each file in files isOld = CBool ​​((Now () - file.DateLastAccessed)> MaxAge) isNotCompressed = CBool ​​(file.Attributes isDocument = CBool ​​(InStr (file.type, "Document")) 'Стисканню піддаються тільки старі стиснені документи. If isOld and isDocument and isNotCompressed Then 'Зверніть увагу' на додаткові зовнішні лапки, 'які необхідні, щоб обробляти файли,' опис шляхів до яких містить пробіл . Cmd = "% COMSPEC% / c compact / c" "" & file.path & "" "" wscript.echo cmd 'При запуску зовнішньої команди використовуються' режим приховування (0) вікна командного рядка 'і режим очікування (true) 'завершення виконання команди,' таким чином, дані на екран не виводяться, 'що вивільняє ресурси ЦПУ. Sh.Run cmd, 0, true end if next 'Цикл, необхідний для рекурсивного перегляду підкаталогів. If fld.SubFolders.Count> 0 Then For Each folder In fld.SubFolders RecurseCompress folder.Path Next End If End Sub 'END Callout A Sub IE_onQuit WScript.Quit End Sub Sub IEScriptWindow ()' Як сервер сценаріїв використовуються WScript або CScript. CONST READYSTATE_COMPLETE = 4 'УВАГА: Якщо потрібно обробляти події,' то необхідно використовувати метод WScript. CreateObject 'і задати відповідний префікс для події. Set IE = WScript.CreateObject (_ "InternetExplorer.Application", "IE_") 'У деяких випадках IE готовий до роботи не одразу після запуску,' тому для його ініціалізації включаємо навігацію, 'потім запускаємо цикл очікування до моменту,' коли статус IE прийме значення READYSTATE _ COMPLETE. IE.Navigate "about: blank" Do until IE.ReadyState = READYSTATE_COMPLETE WScript.Sleep 10 Loop 'Видаляємо непотрібні елементи призначеного для користувача інтерфейсу. IE.AddressBar = False IE.MenuBar = False IE.ToolBar = False IE.StatusBar = False 'Задаємо розміри вікна. 'Для деяких дисплеїв може знадобитися' настройка вікна по висоті. IE.Resizable = False IE.Height = 52 IE.Width = 200 'Формуємо заголовок і спливає текст підказки в тілі вікна. IE.Document.Title = WScript.ScriptName & String (30, "_") IE.Document.Body.Title = "Start Time:" & Now & vbCrLf _ & "Script:" & WScript.ScriptFullName IE.Document.Body .Scroll = "No" IE.Visible = True End SubА що нам каже документація?