Вывод уведомлений пользователям с помощью PowerShell
Несмотря на то, что PowerShell консольный язык, иногда необходимо из скрипта PowerShell оповестить пользователя об определенном событии или необходимости выполнить определенное действие. Например, вывести уведомление о завершении какого-либо длительного PoSh скрипта, или об наступлении какого-то важного события.
Самый простой способ вывести окошко с произвольным тестом через подсистему сценариев Windows – Wscript.
Следующий код выведет обычное текстовое окно с необходимым текстом и кнопкой OK.
$wshell = New-Object -ComObject Wscript.Shell
$Output = $wshell.Popup(«Скрипт формирования отчета выполнен»)
С помощью различных свойств метода Popup вы можете настроить вид модального окна сообщения. В том числе можно вернуть в скрипт результаты ответа пользователя на вопрос (Да / Нет).
$Output = $wshell.Popup(«Скрипт формирования отчета завершен! Хотите вывести его на экран?»,0,»Отчет готов»,4+32)
Общий синтаксис и параметры метода Popup:
— строка, текст сообщения.
- 0 — кнопка ОК.
- 1 — кнопки ОК и Отмена.
- 2 — кнопки Стоп, Повтор, Пропустить.
- 3 — кнопки Да, Нет, Отмена.
- 4 — кнопки Да и Нет.
- 5 — кнопки Повтор и Отмена.
- 16 — значок Stop.
- 32 — значок Question.
- 48 — значок Exclamation.
- 64 — значок Information.
Описание: возвращает целое значение, с помощью которого можно узнать, какая кнопка была нажата пользователем. Возможные значения:
- -1 — таймаут.
- 1 — кнопка ОК.
- 2 — кнопка Отмена.
- 3 — кнопка Стоп.
- 4 — кнопка Повтор.
- 5 — кнопка Пропустить.
- 6 — кнопка Да.
- 7 — кнопка Нет.
Более привлекательные и приятные взгляду всплывающие сообщения (ballons) можно вывести в Windows 7, 8.1 и 10 через API Windows Forms. Следующий PowerShell код выведет всплывающее сообщение рядом с панелью уведомлений Windows 10, которое автоматически исчезнет через 10 секунд.
Add-Type -AssemblyName System.Windows.Forms
$global:balmsg = New-Object System.Windows.Forms.NotifyIcon
$path = (Get-Process -id $pid).Path
$balmsg.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)
$balmsg.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Warning
$balmsg.BalloonTipText = ‘Это текст всплывающего сообщения для пользователя Windows 10’
$balmsg.BalloonTipTitle = «Внимание $Env:USERNAME»
$balmsg.Visible = $true
$balmsg.ShowBalloonTip(10000)
Кроме того для создания красочных всплывающих сообщений в Windows 10 (PowerShell 5.0+)можно использовать отдельный PowerShell модуль BurntToast из галереи PowerShell.
Модуль устанавливается из онлайн репозитория с помощью менеджера пакетов Windows 10:
Install-Module -Name BurntToast
Теперь, например, в ранее рассматриваемый скрипт автоматического отключение от Wi-FI сети при подключении к Ethernet можно добавить красочное уведомление:
New-BurntToastNotification -Text «Отключение от Wi-Fi сети», «Вы были отключены от Wi-Fi сети, т.к. Вше устройство было подключено к скоростному Ethernet подключению.» -AppLogo C:\PS\changenetwork.png
Итак, теперь вы знаете как вывести уведомление пользователя через PowerShell. Если у пользователя есть динамики, можно даже сыграть ему мелодию:
Операционная система Microsoft Windows 3.1 для программиста
1.4. Обработка сообщений
Откуда берутся сообщения?
Большинство сообщений создают драйверы устройств ввода/вывода, таких, как клавиатура, мышь или таймер. Драйверы создают сообщения при поступлении аппаратных прерываний. Например, когда вы нажимаете и затем отпускаете клавишу, драйвер обрабатывает прерывания от клавиатуры и создает несколько сообщений. Аналогично сообщения создаются при перемещении мыши или в том случае, когда вы нажимаете кнопки на корпусе мыши. Можно сказать, что драйверы устройств ввода/вывода транслируют аппаратные прерывания в сообщения.
Куда направляются сообщения, созданные драйверами?
Прежде всего сообщения попадают в системную очередь сообщений Windows. Системная очередь сообщений одна. Далее из нее сообщения распределяются в очереди сообщений приложений. Для каждого приложения создается своя очередь сообщений.
Очередь сообщения приложений может пополняться не только из системной очереди. Любое приложение может послать сообщение любому другому сообщению, в том числе и само себе.
Основная работа, которую должно выполнять приложение, заключается в обслуживании собственной очереди сообщений. Обычно приложение в цикле опрашивает свою очередь сообщений. Обнаружив сообщение, приложение с помощью специальной функции из программного интерфейса Windows распределяет его нужной функции окна, которая и выполняет обработку сообщения.
Когда вы посмотрите на исходный текст нашего первого приложения, обрабатывающего сообщения, вас может удивить тот факт, что функция WinMain не выполняет никакой работы, имеющей отношение к поведению приложения. Внутри этой функции находятся инициализирующий фрагмент и цикл обработки сообщений (Message Loop). Вся основная работа выполняется в функции окна, которой передаются.
Грубо говоря, приложения Windows похожи на загружаемые драйверы MS-DOS. Эти драйверы также состоят из инициализирующего фрагмента и функции, обрабатывающей команды, выдаваемые драйверу. Приложение Windows после инициализации переходит в состояние постоянного опроса собственной очереди сообщений. Как только происходит какое-либо событие, имеющее отношение к приложению, в очереди приложения появляется сообщение и приложение начинает его обрабатывать. После обработки приложение вновь возвращается к опросу собственной очереди сообщений. Иногда функция окна может получать сообщения непосредственно, минуя очередь приложения.
Так как Windows — мультизадачная операционная система, ее разработчики должны были предусмотреть механизм совместного использования несколькими параллельно работающими приложениями таких ресурсов, как мышь и клавиатура. Так как все сообщения, создаваемые драйверами мыши и клавиатуры, попадают в системную очередь сообщений, должен существовать способ распределения этих сообщений между различными приложениями.
В Windows существует понятие фокуса ввода (input focus), помогающее в распределении сообщений. Фокус ввода — это атрибут, который в любой момент времени может относиться только к одному окну. Если окно имеет фокус ввода, все сообщения от клавиатуры распределяются сначала в очередь сообщений приложения, создавшего окно, а затем — функции окна, владеющего фокусом ввода. Нажимая определенные клавиши, вы можете перемещать фокус ввода от одного окна к другому. Например, если вы работаете с диалоговой панелью, содержащей несколько окон, предназначенных для ввода текста, с помощью клавиши вы можете переключать фокус с одного такого окна на другое и вводить текст в различные окна диалоговой панели. Существуют также комбинации клавиш, с помощью которых вы можете переключиться на другое приложение. При этом фокус ввода будет отдан другому окну, принадлежащему другому приложению.
Сообщения от драйвера мыши всегда передаются функции того окна, над которым находится курсор мыши. При необходимости приложение может выполнить операцию захвата (capturing) мыши. В этом случае все сообщения от мыши будут поступать в очередь приложения, захватившего мышь, вне зависимости от положения курсора мыши.
Простейший цикл обработки сообщений состоит из вызовов двух функций — GetMessage и DispatchMessage.
Функция GetMessage предназначена для выборки сообщения из очереди приложения. Сообщение выбирается из очереди и записывается в область данных, принадлежащую приложению.
Функция DispatchMessage предназначена для распределения выбранного из очереди сообщения нужной функции окна. Так как приложение обычно создает много окон и эти окна используют различные функции окна, необходимо распределить сообщение именно тому окну, для которого оно предназначено. Поэтому приложение должно распределить сообщение после его выборки из очереди приложения, в котором находятся сообщения для всех окон. Windows оказывает приложению существенную помощь в решении этой задачи — для распределения приложению достаточно вызвать функцию DispatchMessage.
Вот как выглядит простейший вариант цикла обработки сообщений:
Завершение цикла обработки сообщений происходит при выборке из очереди специального сообщения, в ответ на которое функция GetMessage возвращает нулевое значение. Тип MSG описан в файле windows.h.
Процесс обработки сообщений схематически показан на рис. 1.9.
Рис. 1.9. Процесс обработки сообщений
На этом рисунке слева показаны ресурсы и подсистемы Windows, справа — приложения. Сообщения поступают от драйверов таких устройств, как клавиатура, мышь, таймер, и попадают в системную очередь сообщений. Из системной очереди сообщений Windows выбирает сообщения, предназначенные для приложения, и помещает их в очередь сообщения приложения.
Функция WinMain в цикле обработки сообщений с помощью функции GetMessage выбирает сообщения из очереди сообщений приложения и распределяет их функциям окон, вызывая функцию DispatchMessage.
На нашем рисунке для простоты показано только одно приложение, в котором определена только одна функция окна. Реально же существует много приложений, и каждое приложение имеет несколько функций окна. Каждое приложение вызывает в цикле обработки сообщений функцию GetMessage, выбирая сообщения из своей очереди. Затем каждое приложение распределяет выбранное сообщение одной из своих функций окна, для чего используется функция DispatchMessage.
Функция окна получает сообщения при создании окна, в процессе работы приложения, а также при разрушении окна.
Сообщение с кодом WM_CREATE передается функции окна в момент создания окна. Функция окна при обработке этого сообщения выполняет инициализирующие действия (аналогично конструктору класса в языке C++). Коды сообщений определены в файле windows.h, включаемом в исходные тексты любых приложений Windows.
В процессе работы приложения функция окна может получать сообщения с различными кодами как через очередь сообщений приложения, так и непосредственно, в обход очереди сообщений. Обработчики этих сообщений, определенные в функции окна, являются методами для работы с окном как с объектом.
При разрушении структуры данных окна (при уничтожении окна) функция окна получает сообщение с кодом WM_DESTROY. Обработчик этого сообщения действует как деструктор. Если ваша функция окна во время обработки сообщения WM_CREATE создала какие-либо структуры данных, эти структуры должны быть разрушены (а заказанная для них память возвращена операционной системе) во время обработки сообщения WM_DESTROY.
Вывод текста с использованием Windows API функций
Вывод текста с использованием Windows API функций
Содержание материала
Вывод текста является одной из основных задач, которую приходится решать в программе при организации вывода данных. Речь пойдет о выводе текста с использованием Windows API функций. Данная статья, безусловно не претендует на полноту обзора этой тематики, но о некоторых «подводных камнях» я все же расскажу.
Функции, которые позволяют это выполнять, весьма разнообразны, и использовать их, как Вы уже поняли, можно в разных ситуациях и случаях, и собственно говоря, именно Вам и решать, какие использовать. Кроме функций, которые непосредственно выводят текст, также существует внушительный список «подсобных» функций.
Давайте глянем на tCanvas. В этом классе реализовано только две функции TextOut и TextRect. Когда задача стоит просто в выводе текста на цветном фоне (например, combo box цветов), то функций этого класса предостаточно, и в большинстве случаев я ими и пользуюсь. Но давайте заглянем за ширму. Функция TextOut использует одноименную функцию Windows, а TextRect использует функцию ExtTextOut, т.е. если на прямую вызывать функции Windows, можно получить тот же результат. Кроме того, в этих функциях есть передаваемые параметры, которые класс прячет, использование которых в определенных ситуациях не может быть не нужным и полезным. Формат функций я буду приводить из модуля windows.pas поставляемый с Delphi 3.
function TextOut(DC: HDC; X, Y: Integer; Str: PChar; Count:
Справочную информацию о передаваемых параметрах Вы сможете посмотреть в файле справки, но давайте я первый раз все же расскажу. Все GDI функции вывода имеют параметр DC — контекст устройства, на который нужно нарисовать. Естественно, Canvas подставляет туда Canvas.Handle. Если Вы хотите нарисовать на чем-то другом, то должны самостоятельно получить контекст устройства функциями, типа GetDC. Не забывайте (!) освобождать ресурсы функцией ReleaseDC.
X, Y — привязочные координаты, относительно которых происходит прорисовка. По умолчанию, привязка выполнена к левому верхнему углу. Я конечно немного не правильно выразился — в Windows принято понятие «выравнивание», а не «привязка». Оно настраивается через функцию SetTextAlign, но о ней чуть позже.
Str — переменная, которая содержит выводимый текст, а Count — длина этого текста. В качестве переменной Str можно использовать переменную, типа array [0..n] of Chat; можно передавать просто текст: ‘Пример текста’. Если текст находится у Вас в переменной типа string то нужно произвести приведение типов: PChar(VarString).
function ExtTextOut(DC: HDC; X, Y: Integer; Options: Longint;
Rect: PRect; Str: PChar; Count: Longint; Dx: PInteger): BOOL;
Как видно уже с самого названия и предаваемых параметров, функция имеет гораздо больше возможностей, нежели предыдущая. Прежде всего, текст выводится в прямоугольнике, т.е. как бы сперва выводится прямоугольник, а затем в нем текст, но гораздо быстрее, чем это производилось бы двумя функциями.
Если значение Options будет содержать ETO_CLIPPED, то текст будет виден только в указанном прямоугольнике. Заметьте, что в функцию передается PRect. Это означает, что параметр может быть пустым, т.е. nil. В этом случае, функция будет работать аналогично TextOut. Если вы используете переменную r:tRect, то в функцию должны передать @r.
Выравнивание также, устанавливается предварительно при помощи SetTextAlign.
Наиболее интересен параметр DX. Это ссылка на массив, типа array [0..n] of integer, где каждый элемент является шириной символа. Настоящая ширина может отличатся от указанного значения. Это можно использовать, например, для имитации моноширного шрифта, или для сжатия текста таким образом, чтоб он помещался в отводимую область.
function DrawText(hDC: HDC; lpString: PChar; nCount: Integer;
var lpRect: TRect; uFormat: UINT): Integer;
В отличии от предыдущих функций, функция DrawText не имеет параметров X, Y и использует для руководства координат параметр lpRect. Заметим, что этот параметр является переменной, т.к. функция может модифицировать значения, если ее вызвать с параметром uFormat равным DT_CALCRECT, при этом прорисовка не будет осуществлятся. Параметр uFormat может включать в себя все значения выравнивания по этому предварительной глобальной настройки при помощи SetTextAlign не требуется.
По умолчанию текст, который не вместится в lpRect будет обрезаться. Чтобы этого не происходило, в параметре uFormat используйте DT_NOCLIP.
Используйте DT_WORDBREAK, если необходимо отобразить текст в несколько строк. Без этого параметра, даже если в строке есть символ #13 (перевод строки), все равно текст будет выводится в одну строку. При использовании значения DT_CALCRECT и DT_WORDBREAK изменятся будет lpRect.bottom, без DT_WORDBREAK — lpRect.right.
По-прежнему есть проблема с вертикальным выравниванием по центру (DT_VCENTER). Оно работает только для однострочного текста, т.е. для многострочного текста сперва придется вычислить lpRect, а затем изменив lpRect.top и lpRect.bottom, добиться желаемого результата.
Добавить комментарий
Не использовать не нормативную лексику.
Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.
ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!