Вывод информации об успешном выполнении команды powershell. Конвейеризация и управление выводом команд Windows PowerShell

04.03.2011 Дон Джоунз

Каждому, кто составлял сценарии PowerShell, наверняка приходилось тратить немало времени на их отладку. Ошибки неизбежны, когда нужно добиться, чтобы компьютер выполнил то или иное действие. На первый взгляд в PowerShell немного средств, упрощающих отладку. В этой статье мы рассмотрим несколько основных методов отладки и некоторые приемы, с помощью которых можно избежать ошибок

В PowerShell нет встроенного графического отладчика для построчной проверки сценариев, однако выручают бесплатные и коммерческие инструменты сторонних поставщиков. В таких редакторах, как PowerGUI компании Quest Software (powergui.org), Idera PowerShellPlus (powershellplus.com) и PrimalScript компании SAPIEN Technologies (www.primaltools.com) используют различные методы построчного выполнения сценариев PowerShell, чтобы видеть содержимое переменных и в целом упростить отладку. Однако для успешного применения любого из этих инструментов необходимо овладеть общими навыками отладки.

Прежде чем приступить к отладке, нужно определить объект поиска, иными словами, что считать ошибкой. Существует две отчетливые разновидности ошибок.

Первый тип ошибки: толстые пальцы

Первый тип - простая синтаксическая ошибка. Опечатка. Сбой оператора. Толстые пальцы. Выберите название, которое вам больше нравится. Обнаружить эти ошибки довольно просто, так как PowerShell выдает сообщение, в котором указывается номер строки, содержащей неверный символ. Однако сведения о номере строки мало помогут пользователям Notepad, так как в программе не показаны номера строк. По этой причине рекомендуется заменить Notepad на бесплатную программу PowerGUI или коммерческий редактор сценариев.

Возможности коммерческих редакторов не ограничиваются лишь нумерацией строк, а некоторые их функции помогут предотвратить опечатки. Главная из них - выделение синтаксиса, то есть представление исходного текста сценария различными цветами. Ключевая особенность цветового выделения заключается в том, что элементы окрашиваются в нужный цвет только в случае правильного написания. Поэтому пользователям редакторов с функцией выделения синтаксиса полезно изучить цветовые обозначения команд, переменных, строк литералов и т. д. Если они не окрашиваются нужным цветом во время ввода, значит, произошла ошибка. Остановитесь и выясните причину ошибки.

Если что-то пропущено, от PowerShell поступают сигналы. Обратите внимание на сообщения об ошибках. Очень часто администраторам трудно устранить неполадки просто потому, что они не читают этих сообщений. При виде красного текста на экране они впадают в панику и начинают пробовать разные способы. Но в сообщении указано, в какой строке исходного текста содержится ошибка. Поэтому сосредоточьтесь, внимательно прочитайте сообщение, уясните его смысл и постарайтесь найти причину неполадки.

В хорошем редакторе сценариев можно получить дополнительную информацию, запустив в PowerShell своего рода «предполетную проверку» сценария. Обычно эту функцию называют динамической проверкой синтаксиса. Часто внимание пользователя незамедлительно привлекается к простым ошибкам, еще до запуска сценария. В некоторых редакторах используется красное подчеркивание (как при проверке правописания в Microsoft Word); в других применяются иные визуальные индикаторы.

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

Function get-что-нибудь { # Исходный текст }

Это лучше, чем следующая аморфная запись:

Function get-что-нибудь {# Исходный текст}

Второй тип ошибки: расхождения желаемого и действительного

В результате ошибок второго типа не удается достичь желаемых результатов. Сценарий выполняется без запинок, но не решает поставленную задачу. PowerShell обычно не выдает сообщений об ошибках такого типа или же сообщения не содержат полезной информации. Возможны всего две причины возникновения ошибок подобного типа.

Логическая ошибка. Иногда программисты допускают простые логические ошибки. Например, составлен сценарий, который должен посчитать от 1 до 10:

For ($i=0; $i -lt 10; $i++) { Write-host $i }

Сценарий выполняется успешно, но отображаются числа от 0 до 9. Результат близок, но не совсем соответствует намерениям программиста. В этом случае полезно остановиться и вспомнить принципы выполнения сценариев. Представьте, как программа PowerShell прочитывает сценарий, отметьте содержимое переменных на каждом шаге и результаты каждого шага. Для приведенного сценария ход рассуждений может быть следующим.

Сначала нужно назначить переменной $i значение 0 (записываем $i=0). 0 меньше 10? Да, поэтому используем Write-Host для отображения значения 0 (записывается результат 0) и увеличиваем значение переменной $i на единицу. На данном этапе $i содержит 1 (записываем $i=1). 1 меньше 10? Да, поэтому отображается значение 1 (записывается результат 0) и переменная $i увеличивается на единицу. Теперь $i содержит 2 (записываем $i=2). Это число меньше 10, поэтому оно выводится на экран (записывается результат 2) и т. д.

Так будет продолжаться, пока значение $i не достигнет 10. В результате сравнения оказывается, что 10 не меньше 10, поэтому PowerShell не отображает это число. Как показано в примере, элементарные логические ошибки становятся очевидными, если уделить время простому анализу алгоритма.

Неверные предположения. Поэтапное воспроизведение алгоритма поможет найти не только элементарные, но и более серьезные логические ошибки, так как запись на бумаге содержит перечень ожидаемых состояний. Предположим, программист мысленно воспроизвел сценарий и записал события, которые, по его мнению, должны произойти. В ходе выполнения сценария происходит нечто другое. Такую ошибку можно назвать «ложными ожиданиями» или «незнанием». Причина проста: значение переменной, свойства или результат метода иные, чем предполагалось. В результате анализа логики сценария был составлен письменный перечень ожидаемых состояний. Нужно лишь составить аналогичный список с помощью PowerShell и посмотреть, какие результаты отличаются от ожидаемых. Обнаружив различия, вы найдете ошибку.

Существует два основных метода формирования в PowerShell списка, соответствующего создаваемому в процессе мысленной проверки алгоритма. Эти методы основаны на использовании команд Write-Debug и Set-PSDebug. Существует и третий способ с использованием интерактивного отладчика в редакторе сценариев. В сущности, этот метод представляет собой комбинацию двух базовых методов, которые будут рассмотрены в данной статье. Полезно освоить базовые приемы, прежде чем воспользоваться более удобным способом интерактивного отладчика в редакторе.

Метод 1: Write-Debug

В первом методе используется команда Write-Debug. По умолчанию вывод этой команды подавляется. Чтобы разрешить вывод, необходимо добавить в начало сценария строку

$DebugPreference = "Continue"

Затем следует ввести инструкции Write-Debug непосредственно после каждой инструкции, в которой изменяется содержимое переменной, например:

$var = get-service Write-Debug "`$var contains $var"

Обратите внимание на небольшую хитрость: вывод команды Write-Debug заключен в двойные кавычки. В результате переменные заменяются их содержимым. Для первой переменной используется обратный апостроф (экранирующий символ в PowerShell), поэтому символ $ экранирован. Это приводит к тому, что первый элемент $var отображается как есть, а имя переменной выводится на экран. Второй элемент $var заменяется его содержимым.

Затем нужно ввести инструкцию Write-Debug в каждый цикл и конструкцию принятия решения. В листинге показано, как применить метод для цикла for и конструкции if. В инструкции Write-Debug во фрагменте A используется тот же прием с двойными кавычками и обратным апострофом, чтобы выяснить содержимое $i при каждом повторении цикла for. В конструкции if используются две функции Write-Debug, в том числе и в конструкции else (фрагмент B). Таким образом удается собрать данные для диагностики независимо от ветвления, несмотря на отсутствие программного кода, который бы исполнялся, когда значение $i не больше 2. Обратите внимание, что для вывода инструкций Write-Debug используется одинарная кавычка, чтобы не заменять переменную $i ее содержимым.

После добавления всех инструкций Write-Debug нужно запустить сценарий и сравнить вывод с записанными ожидаемыми значениями. Отметьте любые различия. Возможно, придется пересмотреть ожидания, но любое различие следует рассматривать как указатель на потенциальную ошибку.

Если сценарий выполняется, как ожидалось, просто замените $DebugPreference в начале сценария на

$DebugPreference = "SilentlyContinue"

и диагностический вывод будет подавлен. Удалять инструкции Write-Debug не обязательно. Оставив их на месте, можно облегчить отладку сценария в будущем.

Метод 2: Set-PSDebug

Второй метод основан на использовании встроенного пошагового отладчика Set-PSDebug для построчного выполнения сценария. В длинных сценариях процедура может показаться утомительной, но в PowerShell 1.0 приходится довольствоваться этим. В PowerShell 2.0 появились контрольные точки, о которых будет рассказано в следующей статье. С их помощью можно задать момент перехода сценария в режим ожидания, не выполняя его построчно.

Для запуска отладчика выполните команду

Set-PsDebug -step

Позднее его можно отключить командой

Set-PsDebug -off

Включенный отладчик действует на все сценарии (а также на команды, введенные в командной строке). Нужно просто запустить сценарий и приступить к отладке. Каждый раз, обнаруживая строку сценария, PowerShell отображает ее и просит подтверждения, чтобы продолжить выполнение. Полезно иметь распечатку с пронумерованными строками, чтобы точно видеть, какое место сценария выполняет PowerShell. Чтобы выполнить строку, нажмите клавишу Enter. В процессе выполнения можно сравнивать ожидаемые результаты с реально полученными.

Не нажимайте клавишу Enter всякий раз, когда сценарий изменяет переменную или готовится обратиться к свойству переменной или объекта. Вместо этого введите S и нажмите Enter. При этом выполнение сценария приостанавливается, и на экране появляется особое приглашение. С его помощью можно:

  • обращаться к переменным, чтобы увидеть их содержимое;
  • запускать команды, чтобы увидеть их результат;
  • просматривать свойства объекта, чтобы увидеть их содержимое.

Различие между реальными и ожидаемыми результатами свидетельствует об ошибке. Выполните команду Exit, чтобы выйти из режима ожидания и возобновить выполнение сценария с того места, где он был остановлен.

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

К отладке готов?

Процедура отладки не обязательно сложна при методичном и согласованном подходе. Не расстраивайтесь, получая сообщение об ошибке. Внимательно прочитайте и уясните смысл сообщения. Отнеситесь к нему как к полезной (хотя и непрошеной) подсказке.

Если результаты не соответствуют ожидаемым, документируйте свои предположения и выясните, почему они не соответствуют действительности. Основная причина ошибок в том, что программист не знает, чего ожидать на каждом шаге выполнения сценария. Это типично для начинающих администраторов, которые пытаются, например, использовать сценарии, заимствованные из Интернета. Уделив время изучению сценария, вы не только ускорите отладку, но и больше узнаете о PowerShell и сможете успешно создавать собственные сценарии в будущем, а умение выполнять отладку всегда пригодится в работе.

Дон Джоунз ([email protected]) - инструктор по PowerShell (www.windowsitpro.com/go/DonJonesPowerShell), имеет звание MVP; автор более 35 книг, выступает на таких технологических конференциях, как Microsoft TechEd и Windows Connections


Отладка в Windows PowerShell


Во время написания программы или скрипта любой начинающий программист столкнется с проблемой где ему нужно повторить код дважды и в этот могут помочь функции в Powershell . Функции так же называют методами и процедурами. Кроме многократного использования они так же полезны для выделения одной части скрипта от другой, хоть она и выполняется один раз. Методы описанные ниже существуют во множестве языках и работают по похожему сценарию.

Создание

Представим, что каждое утро вы проверяете 50 последних логов за 14 часов журнала Application с помощью этой команды:

Get-EventLog -LogName Application -Newest 50 | where TimeWritten -ge (Get-Date).AddHours(-14)

Команда не очень сложная, но в скором времени ее надоест писать. Для сокращения этой работы ее можно выделить в отдельную функцию:

Function Get-DayLog { Get-EventLog -LogName Application -Newest 50 | where TimeWritten -ge (Get-Date).AddHours(-14) }

Любая функция обязательно должна состоять из трех вещей:

  • function - объявляет и говорит что после нее будет название;
  • имя функции - название, по которому мы будем ее вызывать. В нашем случае имя Get-DayLog;
  • скобки - обозначают начало и конец выражения.

После написания функции она вызывается по имени:

Get-DayLog

Учитывая, что нам может потребоваться получить данные не за последние 14 часов и более чем за 50 дней нам может потребуется изменить ее передав параметры.

Именование

Не обязательно использовать имя такого же плана, как принято в Powershell, то есть вместо "Get-DayLog" можно писать "daylog". Такой подход рекомендуем и является распространенной практикой, который поможет отличить запуск сторонней программы от функции.

Функции в Powershell всегда именуются по следующему признаку. Первое слово это глаголы типа:

  • Get - получить;
  • Set - изменить;
  • Install - установить;
  • New - создать.

Второе имя - это существительное, как в случае выше DayLog(дневной лог). У Microsoft есть утвержденный список глаголов, который доступен по ссылке на английском языке. Если вы не будете придерживаться этих правил и захотите добавить свою функцию (командлет или модуль) в один из репозиториев, то он может не пройти модерацию.

Передача параметров

Чаще всего функции принимают какой-то объект и возвращают. Для примера может потребоваться изменить время, когда эти логи созданы и их количество. В существующей функции такой возможности нет. Вы можете править код каждый раз, но это не подход программиста. Что бы такая возможность появилась в функции нужно добавить параметры, которая она будет принимать:

Function Get-DayLog ($param1,$param2) { Get-EventLog -LogName Application -Newest $param1 | where TimeWritten -ge (Get-Date).AddHours($param2) }

Параметры функции обозначаются в круглые скобки и пишутся после названия функции и до выражения.

Теперь, для вызова функции, требуется передавать два параметра:

Get-DayLog -param1 50 -param2 -14

При вызове функции мы передаем два обязательных параметра со значениями. Эти значения, внутри функции, будут доступны под названиями $param1 и $param2. Эти переменные мы передаем в команду получения и фильтрации логов.

Установка значений по умолчанию

В нашей задаче, чаще всего, мы получаем только 50 последних логов и нам не хочется указывать их каждый раз. Если мы не будем указывать этот параметр в существующей функции, то получим ошибку. Что бы этого избежать нужно указать значение по умолчанию. На примере ниже я присвоил $param1 значение 50. Оно будет использоваться только в том случае, если мы не используем этот параметр при вызове:

Function Get-DayLog ($param1=50,$param2) { Get-EventLog -LogName Application -Newest $param1 | where TimeWritten -ge (Get-Date).AddHours($param2) } Get-DayLog -param2 -7

Мы должны всегда указывать ключ param2, что добавляет немного работы. Что бы это исправить достаточно поменять их местами:

Function Get-DayLog ($param2,$param1=50) { Get-EventLog -LogName Application -Newest $param1 | where TimeWritten -ge (Get-Date).AddHours($param2) } Get-DayLog -7 1 Get-DayLog -7

Как видно на примере, если мы не указываем ключи param1 и param2 важна последовательность, так как именно в такой последовательности они будут присвоены переменным внутри функций.

Возвращение значений

В отличие от других языков, если мы присвоим переменной $result результат функции Get-DayLog, то она будет содержать значения:

$result = Get-DayLog -7 1

Это будет работать до тех пор, пока мы не решим изменить функцию присвоив переменные:

Function Get-DayLog ($param2,$param1=50) { $events = Get-EventLog -LogName Application -Newest $param1 | where TimeWritten -ge (Get-Date).AddHours($param2) } $result = Get-DayLog -7 $result $events

Мы не можем получить результат используя переменную $result, так как функция не выводит информацию, а хранит ее в переменной $events. Вызывая $events мы тоже не получаем информацию, так как тут работает понятие "область видимости переменных".

Так как функции это отдельная часть программы вся логика и ее переменные не должны касаться другой ее части. Область видимости переменных подразумевает это же. Все переменные, созданные внутри функции остаются в ней же. Эту ситуацию можно исправить с помощью return:

Function Get-DayLog ($param2,$param1=50) { $events = Get-EventLog -LogName Application -Newest $param1 | where TimeWritten -ge (Get-Date).AddHours($param2) return $events } $result = Get-DayLog -7 $result

Я бы рекомендовал всегда возвращать значения через return, а не использовать вывод используя команды типа Write-Output внутри функции. Использование return останавливает работу функции и возвращает значение, а это значит что его не стоит ставить по середине логики если так не планировалось.

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

Function Get-Salary ($Zarplata) { $nalog = $Zarplata * 0.13 $zarplata_bez_nds = $Zarplata - $nalog return $nalog,$zarplata_bez_nds } Get-Salary -Zarplata 100000

Я вернул оба значения разделив их запятой. По умолчанию всегда возвращается массив. это набор не именованных параметров. Более подробно о них мы уже писали.

В случае с массивами, что бы добавит надпись о зарплате, и налоге нужно использовать индексы:

$result = Get-Salary -Zarplata 100000 # Определяем тип данных $result.GetType() Write-Host "это зарплата" $result Write-Host "это налог" $result

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

Function Get-Salary ($Zarplata) { $nalog = $Zarplata * 0.13 $zarplata_bez_nds = $Zarplata - $nalog return @{"Налог"=$nalog;"Зарплата"=$zarplata_bez_nds;} } Get-Salary -Zarplata 100000

Использование массивов

Передача массивов в виде параметров

В предыдущих статьях было множество примеров по работе с массивами и хэш таблицами. Их же, как и любой другой тип данных, мы можем передавать в функцию. Для примера все команды Powershell, которые имеют ключ ComputerName, могут выполняться удаленно. Большинство таких команд могут принимать в виде значений массивы, то есть нам не обязательно передавать поочередно имена компьютеров.

Функция будет принимать массив с именами компьютеров и возвращать все остановленные сервисы. Я так же объявлю этот тип строгим, для наглядности, хотя и без этого в любом случае сработает:

Function Get-ServiceStopped ($Computers){ $services = Get-Service -ComputerName $Computers | where Status -eq Stopped return $services } Get-ServiceStopped "127.0.0.1","localhost"

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

Function Get-ServiceStopped ($Computers){ $services = Get-Service -ComputerName $Computers | where Status -eq $Computers[-1] return $services } Get-ServiceStopped "127.0.0.1","localhost","Stopped"

Хэш таблицы

Параметры хэш таблиц и могут передаваться не просто в функцию, а как параметры командлетов. Добавим в нашу функцию запуск сервиса, если он остановлен:

Function Get-ServiceStopped ($Params){ $services = Get-Service @Params | where Status -eq Stopped $services = Start-Service $services return $services } Get-ServiceStopped @{Name="WinRM";ComputerName=@("127.0.0.1","localhost")}

Знак @ в команде объявляет, что данные хэш таблицы будут использоваться как параметры команды. Важно, чтобы их имена соответствовали настоящим параметрам.

Условия

Нет никаких ограничений на использования условий. Это бывает достаточно удобно, когда функция должна вернуть разные значения.

Ниже приведен пример, где в зависимости от скорости загрузки основной части сайта будет возвращен разный ответ. Если скорость ответа меньше 76 миллисекунды нормальная, в случае если более долгого ответа вернется другой результат:

Function Get-SiteResponse { # Начало отсчета $start_time = Get-Date # Выполнение запроса $request = Invoke-WebRequest -Uri "https://сайт" # Фиксирование окончания выполнения $end_time = Get-Date # Высчитываем разницу во времени $result = $end_time - $start_time # Проверка и возвращение результата if ($result.Milliseconds -lt 76) { return "Скорость ответа нормальная " + $result.Milliseconds} else{ return "Сайт отвечает долго " + $result.Milliseconds } } Get-SiteResponse

Switch

Мы уже говорили про в предыдущих статьях. Если коротко, то это более удобные условия. Используя предыдущий пример, но со Switch, это будет выглядеть так:

Function Get-SiteResponse { # Начало отсчета $start_time = Get-Date # Выполнение запроса $request = Invoke-WebRequest -Uri "https://сайт" # Фиксирование окончания выполнения $end_time = Get-Date # Высчитываем разницу во времени $result = $end_time - $start_time # Проверка и возвращение результата switch($result.Milliseconds) { {$PSItem -le 76} { return "Скорость ответа нормальная " + $result.Milliseconds} default { return "Сайт отвечает долго " + $result.Milliseconds } } } Get-SiteResponse

Другой пример Switch это вызов функции в зависимости от переданных параметров. На примере ниже я вызываю функцию, в которой находится Switch. В эту функцию я передаю имя компьютера, которое проверяется на упоминание указанных фраз и вызывает соответствующую функцию. Каждая функция, которая устанавливает обновления, возвращает значение в Switch, а затем происходит return внутри нее:

Function Install-SQLUpdates { # делаем установку return "Установка обновлений на SQL сервер прошла успешно" } function Install-ADUpdates { # делаем установку return "Установка обновлений на сервер AD прошла успешно" } function Install-FileServerUpdates { # делаем установку return "Установка обновлений на файловый сервер прошла успешно" } function Make-Switch ($computer) { # Проверка имени компьютера $result = switch($computer){ {$computer -like "SQL*"} {Install-SqlUpdates} {$computer -like "AD*"} {Install-ADUpdates} {$computer -like "FileServer*"} {Install-FileServerUpdates} default {"Такого типа компьютеров нет"} } return $result } Make-Switch "AD1"

Со switch так же удобно передавать булевы значения. В примере ниже если указан ключ -On сервис включится, а если его нет выключится:

Function Switch-ServiceTest ($on) { if ($on) {Write-Output "Сервис включен"} else {"Сервис выключен"} } Switch-ServiceTest -On Switch-ServiceTest

Передача через конвейер или Pipeline

Вы наверняка работали через команды Powershell, которые позволяли использовать конвейер следующим образом:

Get-Process -Name *TestProc* | Stop-Process

Если мы захотим использовать подход описанный выше, создав новые команды в виде функций, то конвейер не будет работать:

Function Get-SomeNum { # Генерация числа $num = Get-Random -Minimum 5 -Maximum 10 return $num } function Plus-SomeNum ($num) { Write-Host "Прибавление числа " $num $num += $num return $num } Get-SomeNum Plus-SomeNum 5 Get-SomeNum | Plus-SomeNum

Выполнив следующую команду мы сможем увидеть, что значения, которые могут приниматься через конвейер помечаются специальным атрибутом:

Get-Help Stop-Process -Parameter Name

Таких атрибутов всего два:

  • ValueFromPipelineByPropertyName - получение значения из конвейера по имени;
  • ValueFromPipeline - получение через конвейер только значения.

Кроме этого, внутри нашей функции, мы должны добавить специальный блок Process. Наш скрипт в итоге будет выглядеть так:

Function Get-SomeNum { $num = Get-Random -Minimum 5 -Maximum 10 return $num } function Plus-SomeNum { Param ( $num) process { Write-Host "Прибавление числа " $num $num += $num return $num } } 1..5 | Plus-SomeNum Get-SomeNum | Plus-SomeNum

Атрибут расширения функции, который добавляет некоторые возможности в функции позволяя им работать как команду.

Если бы мы не указали блок Process функция бы вернула только последней результат из массива 1..5:

Если наши команды будут иметь критический характер, такой как удаление, или через конвейер может передаваться несколько значений, то стоит использовать атрибут ValueFromPipelineByPropertyName. Таким образом мы исключим попадания через конвейер случайного значения. На примере ниже я изменил

Function Get-SomeNum { $num = Get-Random -Minimum 5 -Maximum 10 $object = @{num=$num} return $object } function Plus-SomeNum { Param ( $num) process { Write-Host "Прибавление числа " $num $num += $num return $num } } Get-SomeNum | Plus-SomeNum @{num=5} | Plus-SomeNum @{bad=5} | Plus-SomeNum

Как уже писалось ValueFromPipelineByPropertyName принимает только именованные параметры и в случае с именем "bad" мы получаем ошибку:

  • Не удается привязать объект ввода к любым параметрам команды, так как команда не принимает входные данные конвейера
  • The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

Причем передавать именованные параметры через хэш таблицы мы не можем, только через pscustomobject.

Вы можете указывать сразу два атрибута таким образом:

Это позволит использовать и значение с именем, если оно указано либо без него. Это не спасет вас от ситуации, если вы передаете параметр с другим именем:

Передача через конвейер нескольких значений

Для примера рассмотрим ситуацию, где нам нужно передать через конвейер два значения. Если Get-SomeNum будет возвращать массив, то через конвейер у нас будет проходить каждое число по отдельности. Это еще один повод использовать именованные параметры:

Function Get-SomeNum { $number1 = Get-Random -Minimum 5 -Maximum 10 $number2 = Get-Random -Minimum 1 -Maximum 5 $object = @{num1=$number1;num2=$number2} return $object } function Plus-SomeNum { Param ( $num1, $num2) begin {$num1 += $num1 $num2 = $num2 * $num2} process { return @{"Результат сложения"=$num1; "Результат умножения"=$num2} } } Get-SomeNum | Plus-SomeNum

Windows PowerShell является мощным средством и может выполнять практически все, что хочет человек на своем компьютере. Но единственная проблема заключается в том, что это инструмент командной строки и не имеет графического интерфейса. Тем не менее, это может быть полезно, когда интерфейс на основе графического интерфейса не работает или перестает отвечать. К сожалению, главным является тот факт, что обычному пользователю не хватает знаний об использовании PowerShell в полной мере. Но сегодня мы попытаемся обсудить 10 лучших команд PowerShell, которые могут помочь пользователю сделать больше в Windows 10.

Команды PowerShell, которые помогут пользователю сделать больше

Прежде чем мы начнем, необходимо подчеркнуть, что некоторые из этих командлетов могут переключать определенные параметры или конфигурацию на вашем компьютере. Командлет — это сценарий PowerShell, который выполняет одну функцию. Поэтому, чтобы быть в безопасности, сначала создайте точку восстановления системы. Если во время выполнения одного из следующих командлетов что-то пойдет не так, вы всегда сможете восстановить свой компьютер.

Мы рассмотрим командлеты , которые могут выполнять следующие действия:

  1. Запустите приложение UWP.
  2. Получить справку о любом командлете.
  3. Получите похожие команды.
  4. Найти определенный файл.
  5. Прочитайте содержимое файла.
  6. Найти информацию обо всех услугах на компьютере.
  7. Найти информацию обо всех процессах на компьютере.
  8. Установка политики выполнения.
  9. Скопируйте файл или каталог.
  10. Удалить файл или каталог.

1] Запустите приложение UWP

PowerShell — отличный инструмент, который можно использовать для запуска приложений UWP за считанные секунды. Но главное заключается в правильном выполнении команды. Ты можешь использовать

Start-Process "ms-settings:"

Команда просто для запуска приложения Windows Настройки UWP. Вы можете узнать больше о других URI для других приложений UWP здесь на microsoft.com.

2] Получите справку о любом командлете

Если вы когда-либо не понимаете, какую команду вы должны использовать для выполнения определенной задачи. Или то, что делает конкретный командлет, вам не нужно беспокоиться. Вы можете просто использовать командлет Get-Help, чтобы сделать это. Вы можете использовать его следующими способами:

Get-Help Получить помощь Get-Help -Full Get-Help -Example Get-Help *

Здесь первая запись расскажет вам, как использовать этот командлет. Вторая запись даст вам простое резюме конкретного командлета. Третья запись даст подробную информацию о соответствующем командлете. Четвертая запись будет содержать все, что показывает третий командлет, но добавит пример того, как использовать этот командлет. И, наконец, пятый командлет перечислит каждую команду, которая доступна для вашего использования.

3] Получить похожие команды

Чтобы найти команды аналогичного типа или содержащие в себе определенную фразу, вы можете использовать командлет Get-Command . Однако в нем не перечислен каждый командлет в PowerShell, поэтому вы используете некоторые конкретные фильтры. Вы можете использовать следующие команды:

Get-Command -Name Get-Command -CommandType

Первый командлет поможет вам найти командлет с определенной фразой, а второй — отфильтровать командлеты, выполняющие определенную функцию.

4] Поиск определенного файла

Если вам нужно найти определенный файл или каталог в определенном месте, вы можете использовать командлет Get-Item . Вы можете использовать его как

Get-Item

перечислить содержимое конкретного пути.

5] Прочитайте содержимое файла

Get-Content

6] Прочтите информацию обо всех службах на компьютере .

Вы можете использовать командлет Get-Service , чтобы перечислить все службы, запущенные или остановленные на вашем компьютере. Кроме того, вы можете использовать следующие связанные командлеты для выполнения их соответствующих функций:

Start-Service Стоп-Service Suspend-Service Resume-Service Рестарт-Сервис

7] Читайте информацию обо всех процессах на компьютере

Подобно командлету Get-Service, вы можете использовать командлет Get-Process , чтобы вывести список всех процессов, запущенных на вашем компьютере.В качестве альтернативы вы можете использовать следующие связанные командлеты для выполнения соответствующих функций:

Запуск процесса Stop-Process Служба ожидания

8] Настройка политики выполнения

Хотя в PowerShell поддерживается создание и выполнение сценариев, существуют ограничения для каждого из них в рамках некоторых мер безопасности. Вы можете переключить уровень безопасности на любой из 4 уровней. Вы можете использовать командлет Set-ExecutionPolicy , а затем любой из уровней безопасности, указанных в

Set-ExecutionPolicy Неограниченный Set-ExecutionPolicy Все подписано Set-ExecutionPolicy Удаленная подпись Set-ExecutionPolicy Restricted

Здесь политики сверху вниз варьируются от самого низкого до самого высокого уровня безопасности.

9] Скопируйте файл или каталог

Пользователь может использовать командлет Copy-Item

Copy-Item "E: \ TWCTest.txt" -Destination "D: \"

10] Удалить файл или каталог

Подобно командлету Copy-Item, пользователь может использовать командлет Copy-Item для копирования одного файла или каталога в другое место назначения. Синтаксис этого командлета

Remove-Item "E: \ TWCTest.txt"

Работая в оболочке PowerShell, мы пока не задумывались, каким образом система формирует строки текста, которые выводятся на экран в результате выполнения той или иной команды (напомним, что командлеты PowerShell возвращают.NET-объекты, которые, как правило, не знают, каким образом отображать себя на экране).

На самом деле в PowerShell имеется база данных (набор XML-файлов), содержащая модули форматирования по умолчанию для различных типов.NET-объектов. Эти модули определяют, какие свойства объекта отображаются при выводе и в каком формате: списка или таблицы. Когда объект достигает конца конвейера, PowerShell определяет его тип и ищет его в списке объектов, для которых определено правило форматирования. Если данный тип в списке обнаружен, то к объекту применяется соответствующий модуль форматирования; если нет, то PowerShell просто отображает свойства этого.NET-объекта.

Также в PowerShell можно явно задавать правила форматирования данных, выводимых командлетами, и подобно командному интерпретатору Cmd.exe перенаправлять эти данные в файл, на принтер или в пустое устройство.

Форматирование выводимой информации

В традиционных оболочках команды и утилиты сами форматируют выводимые данные. Некоторые команды (например, dir в интерпретаторе Cmd.exe) позволяют настраивать формат вывода с помощью специальных параметров.

В оболочке PowerShell вывод форматируют только четыре специальных командлета Format (табл. 17.3). Это упрощает изучение, так как не нужно запоминать средства и параметры форматирования для других команд (остальные командлеты вывод не форматируют).

Таблица 17.3. Командлеты PowerShell для форматирования вывода
Командлет Описание
Format-Table Форматирует вывод команды в виде таблицы, столбцы которой содержат свойства объекта (также могут быть добавлены вычисляемые столбцы). Поддерживается возможность группировки выводимых данных
Format-List Вывод форматируется как список свойств, в котором каждое свойство отображается на новой строке. Поддерживается возможность группировки выводимых данных
Format-Custom Для форматирования вывода используется пользовательское представление (view)
Format-Wide Форматирует объекты в виде широкой таблицы, в которой отображается только одно свойство каждого объекта

Как уже отмечалось выше, если ни один из командлетов Format явно не указан, то используется модуль форматирования по умолчанию, который определяется по типу отображаемых данных. Например, при выполнении командлета Get-Service данные по умолчанию выводятся как таблица с тремя столбцами (Status, Name и DisplayName):

PS C:\> Get-Service Status Name DisplayName ------ ---- ----------- Stopped Alerter Оповещатель Running ALG Служба шлюза уровня приложения Stopped AppMgmt Управление приложениями Stopped aspnet_state ASP.NET State Service Running Ati HotKey Poller Ati HotKey Poller Running AudioSrv Windows Audio Running BITS Фоновая интеллектуальная служба пер... Running Browser Обозреватель компьютеров Stopped cisvc Служба индексирования Stopped ClipSrv Сервер папки обмена Stopped clr_optimizatio... .NET Runtime Optimization Service v... Stopped COMSysApp Системное приложение COM+ Running CryptSvc Службы криптографии Running DcomLaunch Запуск серверных процессов DCOM Running Dhcp DHCP-клиент...

Для изменения формата выводимых данных нужно направить их по конвейеру соответствующему командлету Format . Например, следующая команда выведет список служб с помощью командлета Format-List :

PS C:\> Get-Service | Format-List Name: Alerter DisplayName: Оповещатель Status: Stopped DependentServices: {} ServicesDependedOn: {LanmanWorkstation} CanPauseAndContinue: False CanShutdown: False CanStop: False ServiceType: Win32ShareProcess Name: ALG DisplayName: Служба шлюза уровня приложения Status: Running DependentServices: {} ServicesDependedOn: {} CanPauseAndContinue: False CanShutdown: False CanStop: True ServiceType: Win32OwnProcess . . .

Как мы видим, при использовании формата списка выводится больше сведений о каждой службе, чем в формате таблицы (вместо трех столбцов данных о каждой службе в формате списка выводятся девять строк данных). Однако это вовсе не означает, что командлет Format-List извлекает дополнительные сведения о службах. Эти данные содержатся в объектах, возвращаемых командлетом Get-Service , однако командлет Format-Table , используемый по умолчанию, отбрасывает их, потому что не может вывести на экран более трех столбцов.

При форматировании вывода с помощью командлетов Format-List и Format-Table можно указывать имена свойства объекта, которые должны быть отображены (напомним, что просмотреть список свойств, имеющихся у объекта, позволяет рассмотренный ранее командлет Get-Member ). Например:

PS C:\> Get-Service | Format-List Name, Status, CanStop Name: Alerter Status: Stopped CanStop: False Name: ALG Status: Running CanStop: True Name: AppMgmt Status: Stopped CanStop: False . . .

Вывести все имеющиеся у объектов свойства можно с помощью параметра * , например:

PS C:\> Get-Service | Format-table *

Перенаправление выводимой информации

В оболочке PowerShell имеются несколько командлетов, с помощью которых можно управлять выводом данных. Эти командлеты начинаются со слова Out , их список можно увидеть следующим образом:

PS C:\> Get-Command out-* | Format-Table Name Name ---- Out-Default Out-File Out-Host Out-Null Out-Printer Out-String

По умолчанию выводимая информация передается командлету Out-Default , который, в свою очередь, делегирует всю работу по выводу строк на экран командлету Out-Host . Для понимания данного механизма нужно учитывать, что архитектура PowerShell подразумевает различие между собственно ядром оболочки (интерпретатором команд) и главным приложением (host), которое использует это ядро. В принципе, в качестве главного может выступать любое приложение, в котором реализован ряд специальных интерфейсов, позволяющих корректно интерпретировать получаемую от PowerShell информацию. В нашем случае главным приложением является консольное окно, в котором мы работаем с оболочкой, и командлет Out-Host передает выводимую информацию в это консольное окно.

Параметр Paging командлета Out-Host , подобно команде more интерпретатора Cmd.exe, позволяет организовать постраничный вывод информации, например:

Get-Help Get-Process –Full | Out-Host -Paging

Сохранение данных в файл

Командлет Out-File позволяет направить выводимые данные вместо окна консоли в текстовый файл. Аналогичную задачу решает оператор перенаправления (>), однако командлет Out-File имеет несколько дополнительных параметров, с помощью которых можно более гибко управлять выводом: задавать тип кодировки файла (параметр Encoding ), задавать длину выводимых строк в знаках (параметр Width ), выбирать режим перезаписи файла (параметры Append , noClobber ). Например, следующая команда направит информацию о зарегистрированных на компьютере службах в файл C:\service.txt, причем данный файл будет записан в формате ASCII.

Несмотря на то, что PowerShell консольный язык, иногда необходимо из скрипта PowerShell оповестить пользователя об определенном событии или необходимости выполнить определенное действие. Например, вывести уведомление о завершении какого-либо длительного PoSh скрипта, или об наступлении какого-то важного события.

Самый простой способ вывести окошко с произвольным тестом через подсистему сценариев Windows – Wscript.

Следующий код выведет обычное текстовое окно с необходимым текстом и кнопкой OK.

$wshell = New-Object -ComObject Wscript.Shell
$Output = $wshell.Popup("Скрипт формирования отчета выполнен")

С помощью различных свойств метода Popup вы можете настроить вид модального окна сообщения. В том числе можно вернуть в скрипт результаты ответа пользователя на вопрос (Да / Нет).

$Output = $wshell.Popup("Скрипт формирования отчета завершен! Хотите вывести его на экран?",0,"Отчет готов",4+32)

Общий синтаксис и параметры метода Popup:

Popup(,,,<Type>) </b></p><p>Параметры:</p><ul><li><Text> — строка, текст сообщения.</li><li><SecondsToWait> — необязательный, число. Количество секунд, по истечении которого окно будет автоматически закрыто.</li><li><Title> — необязательный, строка. Текст заголовка окна сообщения.</li><li><Type> — необязательный, число. Комбинация флагов, определяет тип кнопок и значка. Возможные значения флагов:<ul><li>0 — кнопка ОК.</li><li>1 — кнопки ОК и Отмена.</li><li>2 — кнопки Стоп, Повтор, Пропустить.</li><li>3 — кнопки Да, Нет, Отмена.</li><li>4 — кнопки Да и Нет.</li><li>5 — кнопки Повтор и Отмена.</li><li>16 — значок Stop.</li><li>32 — значок Question.</li><li>48 — значок Exclamation.</li><li>64 — значок Information.</li> </ul></li> </ul><p>Описание: возвращает целое значение, с помощью которого можно узнать, какая кнопка была нажата пользователем. Возможные значения:</p><ul><li>-1 — таймаут.</li><li>1 — кнопка ОК.</li><li>2 — кнопка Отмена.</li><li>3 — кнопка Стоп.</li><li>4 — кнопка Повтор.</li><li>5 — кнопка Пропустить.</li><li>6 — кнопка Да.</li><li>7 — кнопка Нет.</li> </ul><p>Более привлекательные и приятные взгляду всплывающие сообщения (ballons) можно вывести в Windows 7, 8.1 и 10 через API Windows Forms. Следующий PowerShell код выведет всплывающее сообщение рядом с панелью уведомлений Windows 10, которое автоматически исчезнет через 10 секунд.</p><p>Add-Type -AssemblyName System.Windows.Forms<br>$global:balmsg = New-Object System.Windows.Forms.NotifyIcon<br>$path = (Get-Process -id $pid).Path<br>$balmsg.Icon = ::ExtractAssociatedIcon($path)<br>$balmsg.BalloonTipIcon = ::Warning<br>$balmsg.BalloonTipText = "Это текст всплывающего сообщения для пользователя Windows 10"<br>$balmsg.BalloonTipTitle = "Внимание $Env:USERNAME"<br>$balmsg.Visible = $true<br>$balmsg.ShowBalloonTip(10000)</p><p><img src='https://i0.wp.com/winitpro.ru/wp-content/uploads/2018/10/vsplyvayushee-uvedomlenie-v-powershell.png' width="100%" loading=lazy></p><p>Кроме того для создания красочных всплывающих сообщений в Windows 10 (PowerShell 5.0+)можно использовать отдельный PowerShell модуль BurntToast из галереи PowerShell.</p><p>Модуль устанавливается из онлайн репозитория с помощью :<br> Install-Module -Name BurntToast</p><p>Теперь, например, в ранее рассматриваемый можно добавить красочное уведомление:</p><p>New-BurntToastNotification -Text "Отключение от Wi-Fi сети", "Вы были отключены от Wi-Fi сети, т.к. Вше устройство было подключено к скоростному Ethernet подключению." -AppLogo C:\PS\changenetwork.png</p><p>Итак, теперь вы знаете как вывести уведомление пользователя через PowerShell. Если у пользователя есть динамики, можно даже сыграть ему мелодию:</p><p>::beep(440,500)<br>::beep(440,500)<br>::beep(440,500)<br>::beep(349,350)<br>::beep(523,150)<br>::beep(440,500)<br>::beep(349,350)<br>::beep(523,150)<br>::beep(440,1000)<br>::beep(659,500)<br>::beep(659,500)<br>::beep(659,500)<br>::beep(698,350)<br>::beep(523,150)<br>::beep(415,500)<br>::beep(349,350)<br>::beep(523,150)<br>::beep(440,1000)<br>::beep(880,500)<br>::beep(440,350)<br>::beep(440,150)<br>::beep(880,500)<br>::beep(830,250)<br>::beep(784,250)<br>::beep(740,125)<br>::beep(698,125)<br>::beep(740,250)<br>::beep(455,250)<br>::beep(622,500)<br>::beep(587,250)<br>::beep(554,250)<br>::beep(523,125)<br>::beep(466,125)<br>::beep(523,250)<br>::beep(349,125)<br>::beep(415,500)<br>::beep(349,375)<br>::beep(440,125)<br>::beep(523,500)<br>::beep(440,375)<br>::beep(523,125)<br>::beep(659,1000)<br>::beep(880,500)<br>::beep(440,350)<br>::beep(440,150)<br>::beep(880,500)<br>::beep(830,250)<br>::beep(784,250)<br>::beep(740,125)<br>::beep(698,125)<br>::beep(740,250)<br>::beep(455,250)<br>::beep(622,500)<br>::beep(587,250)<br>::beep(554,250)<br>::beep(523,125)<br>::beep(466,125)<br>::beep(523,250)<br>::beep(349,250)<br>::beep(415,500)<br>::beep(349,375)<br>::beep(523,125)<br>::beep(440,500)<br>::beep(349,375)<br>::beep(261,125)<br>::beep(440,1000)</p> <script>document.write("<img style='display:none;' src='//counter.yadro.ru/hit;artfast_after?t44.1;r"+ escape(document.referrer)+((typeof(screen)=="undefined")?"": ";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth? screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+";h"+escape(document.title.substring(0,150))+ ";"+Math.random()+ "border='0' width='1' height='1' loading=lazy>");</script> <div style="font-size:0px;height:0px;line-height:0px;margin:0;padding:0;clear:both"></div> <div class='yarpp-related'> <div class="block_post"> <span class="h1 color_green recomend" style="margin:15px 0 30px;">Рекомендуем почитать</span> <div> <article class="postBox"> <div class="images"> <noindex><a href="/devices/raznye-cms-kakoi-dvizhok-vybrat-dlya-sozdaniya-svoei-igry/"><img width="370" height="190" src="/uploads/e912f3127a8dadc4c4995ca0b0750d28.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Какой движок выбрать для создания своей игры" / loading=lazy></a></noindex> </div> <div class="info left"> <div class="category_name" style="margin:6px 0 0;"><a href="/category/devices/" rel="category tag">Устройства</a></div> <strong><a href="/devices/raznye-cms-kakoi-dvizhok-vybrat-dlya-sozdaniya-svoei-igry/" rel="bookmark" title="Какой движок выбрать для создания своей игры">Какой движок выбрать для создания своей игры</a></strong> </div> </article> <article class="postBox"> <div class="images"> <noindex><a href="/programs/chem-lightroom-otlichaetsya-ot-photoshop-lightroom-i-photoshop---kto-zhe-luchshii-drug/"><img width="370" height="190" src="/uploads/d97f10777841ff96483786f7e6f1ff55.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Lightroom и Photoshop - кто же лучший друг фотографа?" / loading=lazy></a></noindex> </div> <div class="info left"> <div class="category_name" style="margin:6px 0 0;"><a href="/category/programs/" rel="category tag">Программамы</a></div> <strong><a href="/programs/chem-lightroom-otlichaetsya-ot-photoshop-lightroom-i-photoshop---kto-zhe-luchshii-drug/" rel="bookmark" title="Lightroom и Photoshop - кто же лучший друг фотографа?">Lightroom и Photoshop - кто же лучший друг фотографа?</a></strong> </div> </article> <article class="postBox"> <div class="images"> <noindex><a href="/for-beginners/raznica-mezhdu-photoshop-i-lightroom-chem-lightroom-otlichaetsya-ot-photoshop-lightroom-delaet/"><img width="370" height="190" src="/uploads/7f240a84bb095be1870c8eac31ce228e.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Чем Lightroom отличается от Photoshop Lightroom делает резервное копирование" / loading=lazy></a></noindex> </div> <div class="info left"> <div class="category_name" style="margin:6px 0 0;"><a href="/category/for-beginners/" rel="category tag">Для начинающих</a></div> <strong><a href="/for-beginners/raznica-mezhdu-photoshop-i-lightroom-chem-lightroom-otlichaetsya-ot-photoshop-lightroom-delaet/" rel="bookmark" title="Чем Lightroom отличается от Photoshop Lightroom делает резервное копирование">Чем Lightroom отличается от Photoshop Lightroom делает резервное копирование</a></strong> </div> </article> <article class="postBox"> <div class="images"> <noindex><a href="/security/kak-nastroit-fotoshop-dlya-raboty-s-foto-nastroiki-fotoshopa/"><img width="370" height="190" src="/uploads/3983a2ef628cc21692d6eecd296b3e45.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Настройки "Фотошопа": рекомендации Что цветовой профиль в фотошопе" / loading=lazy></a></noindex> </div> <div class="info left"> <div class="category_name" style="margin:6px 0 0;"><a href="/category/security/" rel="category tag">Безопасность</a></div> <strong><a href="/security/kak-nastroit-fotoshop-dlya-raboty-s-foto-nastroiki-fotoshopa/" rel="bookmark" title="Настройки "Фотошопа": рекомендации Что цветовой профиль в фотошопе">Настройки "Фотошопа": рекомендации Что цветовой профиль в фотошопе</a></strong> </div> </article> <article class="postBox"> <div class="images"> <noindex><a href="/pc-device/kak-poluchit-skrytyi-oblik-artefakta-v-wow-legion-kak-otkryt-vse/"><img width="370" height="190" src="/uploads/f4882bbdc4bed3a2b090121e6c482af8.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Как открыть все облики артефакта в WOW Legion Секретный облик дк" / loading=lazy></a></noindex> </div> <div class="info left"> <div class="category_name" style="margin:6px 0 0;"><a href="/category/pc-device/" rel="category tag">Устройство ПК</a></div> <strong><a href="/pc-device/kak-poluchit-skrytyi-oblik-artefakta-v-wow-legion-kak-otkryt-vse/" rel="bookmark" title="Как открыть все облики артефакта в WOW Legion Секретный облик дк">Как открыть все облики артефакта в WOW Legion Секретный облик дк</a></strong> </div> </article> <article class="postBox"> <div class="images"> <noindex><a href="/setting/makrosy-l2-interlyud-makrosy-osnovnye-pravila-sozdaniya/"><img width="370" height="190" src="/uploads/b0f5b340aa583f06158433cac8fc88f5.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Макросы л2 интерлюд. Макросы. Основные правила создания макроса" / loading=lazy></a></noindex> </div> <div class="info left"> <div class="category_name" style="margin:6px 0 0;"><a href="/category/setting/" rel="category tag">Настройка </a></div> <strong><a href="/setting/makrosy-l2-interlyud-makrosy-osnovnye-pravila-sozdaniya/" rel="bookmark" title="Макросы л2 интерлюд. Макросы. Основные правила создания макроса">Макросы л2 интерлюд. Макросы. Основные правила создания макроса</a></strong> </div> </article> </div> </div> </div> </div> <div class="soc_buttons clearfix"> <div class="pluso" data-background="#ebebeb" data-options="medium,square,line,horizontal,counter,theme=01" data-services="vkontakte,odnoklassniki,facebook,twitter,google,moimir,email,print" data-user="1187196371"></div> </div> </div> <noindex> <div id="smartrotator_ad_14"></div> <div id="smartrotator_ad_15"></div> </noindex> </div> <aside class="right-sidebar"> <div class="rightBox"> <div id="nav_menu-2" class="rightBoxMid widget_nav_menu"><div class="menu-right-menu-container"> <ul id="menu-right-menu" class="menu"> <li id="menu-item-" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-"><a href="/category/working-with-files/"><img src="/assets/m1.png" loading=lazy>Работа с файлами</a> </li> <li id="menu-item-" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-"><a href="/category/devices/"><img src="/assets/m3.png" loading=lazy>Устройства</a> </li> <li id="menu-item-" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-"><a href="/category/pc-device/"><img src="/assets/m4.png" loading=lazy>Устройство ПК</a> </li> <li id="menu-item-" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-"><a href="/category/windows/"><img src="/assets/m5.png" loading=lazy>Windows</a> </li> <li id="menu-item-" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-"><a href="/category/security/"><img src="/assets/m2.png" loading=lazy>Безопасность</a> </li> </ul> </div></div> </div><div class="rightBox"> <div id="enhancedtextwidget-27" class="rightBoxMid widget_text enhanced-text-widget"><div class="textwidget widget-text"><div id="smartrotator_ad_40"></div> </div></div> </div><div class="rightBox"> </div><div class="rightBox"> <div id="enhancedtextwidget-35" class="rightBoxMid widget_text enhanced-text-widget"><div class="textwidget widget-text"><div id="smartrotator_ad_32"></div></div></div> </div><div class="rightBox"> <div id="enhancedtextwidget-10" class="rightBoxMid widget_text enhanced-text-widget"><div class="textwidget widget-text"><div id="smartrotator_ad_41"></div></div></div> </div> </aside> <div class="clear"></div> </div> </div> <footer> <div class="top"> <noindex><div class="block_width"> <a href="/" class="logo left"><img src="/images/logo.svg" alt="Мой компьютер - Просто о сложном" loading=lazy></a> <div class="send right"> <div class="left"> <span class="title">Подписаться на обновления</span> <span class="small">работы в саду и огороде</span> </div> <div class="form_block right"> <div class="Subscribers" id="Subscribers"> <div> <form class="es_widget_form" data-es_form_id="es_widget_form"> <div class="es_lablebox"><label class="es_widget_form_email">Email *</label></div> <div class="es_textbox"> <input type="text" id="es_txt_email" class="es_textbox_class" name="es_txt_email" value="" maxlength="225"> </div> <div class="es_button"> <input type="button" id="es_txt_button" class="es_textbox_button es_submit_button" name="es_txt_button" value="Subscribe"> </div> <div class="es_msg" id="es_widget_msg"> <span id="es_msg"></span> </div> </form> </div> </div> </div> </div> </div></noindex> </div> <div class="bottom1"> <div class="block_width"> <div class="link"> <div id="footerInner"> <div class="boxFooter"> <div class="textwidget"> <a href="/category/windows/">Windows</a> <a href="/category/security/">Безопасность</a> <a href="/category/for-beginners/">Для начинающих</a> <a href="/category/setting/">Настройка </a> <a href="/category/programs/">Программамы</a> <a href="/category/working-with-files/">Работа с файлами</a> <a href="/category/devices/">Устройства</a> <a href="/category/pc-device/">Устройство ПК</a> <a href="">О проекте</a> <a href="/feedback/">Обратная связь</a> </div> </div></div> </div> </div> </div> <div class="bottom2"> <div class="block_width"> <div class="copyright left"> <span></span> </div> <div class="counter right"> <noindex> </script> </noindex> </div> </div> </footer> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"> <script type="text/javascript" src="https://raw.githubusercontent.com/robflaherty/jquery-scrolldepth/master/jquery.scrolldepth.min.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> <script type="text/javascript"> $(function() { //We initially hide the all dropdown menus $('#dropdown_nav li').find('.sub-menu').hide(); //When hovering over the main nav link we find the dropdown menu to the corresponding link. $('#dropdown_nav li').hover(function() { //Find a child of 'this' with a class of .sub_nav and make the beauty fadeIn. $(this).find('.sub-menu').fadeIn(400); } , function() { //Do the same again, only fadeOut this time. $(this).find('.sub-menu').fadeOut(100); } ); } ); </script> <script type="text/javascript"> /* использование: <a class='scrollTop' href='#' style='display:none;'></a> ------------------------------------------------- */ $(function(){ var e = $(".scrollTop"); var speed = 5000; e.click(function(){ $("html:not(:animated)" +( !$.browser.opera ? ",body:not(:animated)" : "")).animate({ scrollTop: 0} , 2500 ); return false; //важно! } ); //появление function show_scrollTop(){ ( $(window).scrollTop()>300 ) ? e.fadeIn(300) : e.hide(); } $(window).scroll( function(){ show_scrollTop()} ); show_scrollTop(); } ); </script> <script type="text/javascript">jQuery(function($) { $(document).on("click", ".pseudo-link", function(){ window.open($(this).data("uri")); } );} );</script><link rel='stylesheet' id='yarppRelatedCss-css' href='/assets/related.css' type='text/css' media='all' /> <link rel='stylesheet' id='metaslider-flex-slider-css' href='/assets/flexslider.css' type='text/css' media='all' property='stylesheet' /> <link rel='stylesheet' id='metaslider-public-css' href='/assets/public.css' type='text/css' media='all' property='stylesheet' /> <link rel='stylesheet' id='su-box-shortcodes-css' href='/assets/box-shortcodes.css' type='text/css' media='all' /> <link rel='stylesheet' id='su-media-shortcodes-css' href='/assets/media-shortcodes.css' type='text/css' media='all' /> <script type='text/javascript'> /* <![CDATA[ */ var wpcf7 = { "apiSettings":{ "root":"http:\/\/plodovie.ru\/wp-json\/contact-form-7\/v1","namespace":"contact-form-7\/v1"} ,"recaptcha":{ "messages":{ "empty":"\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435, \u0447\u0442\u043e \u0432\u044b \u043d\u0435 \u0440\u043e\u0431\u043e\u0442."} },"cached":"1"} ; /* ]]> */ </script> <script type='text/javascript' src='/assets/scripts.js'></script> <script type='text/javascript'> /* <![CDATA[ */ var es_widget_notices = { "es_email_notice":"Please enter email address","es_incorrect_email":"Please provide a valid email address","es_load_more":"loading...","es_ajax_error":"Cannot create XMLHTTP instance","es_success_message":"Successfully Subscribed.","es_success_notice":"Your subscription was successful! Within a few minutes, kindly check the mail in your mailbox and confirm your subscription. If you can't see the mail in your mailbox, please check your spam folder.","es_email_exists":"Email Address already exists!","es_error":"Oops.. Unexpected error occurred.","es_invalid_email":"Invalid email address","es_try_later":"Please try after some time","es_problem_request":"There was a problem with the request"} ; /* ]]> */ </script> <script type='text/javascript' src='/assets/es-widget.js'></script> <script type='text/javascript'> /* <![CDATA[ */ var es_widget_page_notices = { "es_email_notice":"Please enter email address","es_incorrect_email":"Please provide a valid email address","es_load_more":"loading...","es_ajax_error":"Cannot create XMLHTTP instance","es_success_message":"Successfully Subscribed.","es_success_notice":"Your subscription was successful! Within a few minutes, kindly check the mail in your mailbox and confirm your subscription. If you can't see the mail in your mailbox, please check your spam folder.","es_email_exists":"Email Address already exists!","es_error":"Oops.. Unexpected error occurred.","es_invalid_email":"Invalid email address","es_try_later":"Please try after some time","es_problem_request":"There was a problem with the request"} ; /* ]]> */ </script> <script type='text/javascript' src='/assets/es-widget-page.js'></script> <script type='text/javascript'> /* <![CDATA[ */ var supertoc = { "smooth_scroll":"1"} ; /* ]]> */ </script> <script type='text/javascript' src='/assets/front.js'></script> <script type='text/javascript' src='/assets/polls-js.js'></script> <script type='text/javascript' src='/assets/postratings-js.js'></script> <script type='text/javascript'> var q2w3_sidebar_options = new Array(); q2w3_sidebar_options[0] = { "sidebar" : "sidebar-1", "margin_top" : 20, "margin_bottom" : 360, "stop_id" : "", "screen_max_width" : 800, "screen_max_height" : 0, "width_inherit" : false, "refresh_interval" : 1500, "window_load_hook" : false, "disable_mo_api" : false, "widgets" : ['enhancedtextwidget-10'] } ; </script> <script type='text/javascript' src='/assets/q2w3-fixed-widget.min.js'></script> <script type='text/javascript' src='/assets/wp-embed.min.js'></script> <script type='text/javascript' src='/assets/jquery.flexslider-min.js'></script> <script type='text/javascript' src='/assets/jquery.fancybox-1.3.8.min.js'></script> <script type='text/javascript' src='/assets/jquery.easing.min.js'></script> <script type='text/javascript' src='/assets/jquery.mousewheel.min.js'></script> <script type="text/javascript"> jQuery(document).on('ready post-load', function(){ jQuery('.nofancybox,a.pin-it-button,a[href*="pinterest.com/pin/create/button"]').addClass('nolightbox'); } ); jQuery(document).on('ready post-load',easy_fancybox_handler); jQuery(document).on('ready',easy_fancybox_auto);</script> <script type="text/javascript"> $(function(){ $('aside .menu > li a').click(function(e){ //e.preventDefault(); $('aside .menu > li a').removeClass('active'); $(this).addClass('active'); var submenu = $(this).next().css('display'); if($(this).next().css('display') == 'none'){ $(this).next('.sub-menu').fadeIn(300); } else { $(this).next('.sub-menu').fadeOut(300); } } ); $("aside .menu > li a").one("click", false); $('.menu_block .fa').click(function(){ $(this).next().fadeToggle(300); } ); $('.tab_module .tab_link span').click(function(){ $('.tab_module .tab_link span').removeClass('active'); $(this).addClass('active'); var data_href = $(this).attr('data-href'); var data_id = $('.tab_module .tab_block > div').attr('data-id'); //alert(data_id); $('.tab_module .tab_block > div').fadeOut(100); $('.tab_module .tab_block div[data-id='+data_href+']').fadeIn(500); } ); } ); </script> <script type="text/javascript"> (function($) { $('.without-link a:first-child').removeAttr('href'); } (jQuery)); </script> <script type="text/javascript"> $(document).ready(function(e) { // мои скрипты $('aside #content4 .wp-polls a[title="Результаты голосования"]').text('Результат'); $('#tab4').attr("checked", "checked"); $('#enhancedtextwidget-7 #tab1').click(function(){ $('#enhancedtextwidget-7 #tab2,#enhancedtextwidget-7 #tab3').attr("checked", ""); } ); $('footer .form_block input[type=text]').val('Введите Ваш e-mail...'); $('footer .form_block input[type=text]').focus(function(){ if($(this).val()=='Введите Ваш e-mail...'){ $(this).val(''); } } ); $('footer .form_block input[type=text]').blur(function(){ if($(this).val()==''){ $(this).val('Введите Ваш e-mail...'); } } ); $('.category_page .box-descr h2 span').text($('#archive-title span').text()); $('.menu_block .fa').click(function(){ $(this).next().fadeToggle(300); } ); // обрамление картинок в <span class="images clear"> var html = document.documentElement; if(html.clientWidth <=1024){ var block_img = $('.page_post .cont p img'); block_img.wrap('<span class="images clear"></span>'); $('.tab_module .tab_link span').click(function(){ $('.tab_module .tab_link span').removeClass('active'); $(this).addClass('active'); var data_href = $(this).attr('data-href'); var data_id = $('.tab_module .tab_block > div').attr('data-id'); //alert(data_id); $('.tab_module .tab_block > div').fadeOut(100); $('.tab_module .tab_block div[data-id='+data_href+']').fadeIn(500); } ); $('.menu_block #dropdown_nav div > ul > li').click(function(){ var l_link = $(this).children('a').attr('href'); //alert(l_link); location.href = l_link; } ); } ); </script> </body> </html> <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>