PowerShell

PowerShell — расширяемое средство автоматизации от Microsoft с открытым исходным кодом[2], состоящее из оболочки с интерфейсом командной строки и сопутствующего языка сценариев. Впервые публично язык был продемонстрирован на Профессиональной конференции разработчиков (англ. Professional Developers Conference, PDC) в сентябре 2003 года под кодовым названием Monad. Изначально средство выпущено как компонент Windows под названием Windows PowerShell. Открытый исходный код был выпущен с началом разработки PowerShell Core в августе 2016 года.

Windows PowerShell

Сессия в Windows PowerShell
Тип Оболочка операционной системы
Разработчик Microsoft
Написана на C#[1]
Операционная система Windows XP
Windows Server 2003
Windows Vista
Windows Server 2008/2008 R2
Windows 7
Windows 8
Windows 8.1
Windows RT
Windows RT 8.1
Windows Server 2012/2012 R2
Windows 10
Windows Server 2016
Windows Server 2019
Windows 11
Windows Server 2022
Linux
macOS
Первый выпуск 14 ноября, 2006 года
Аппаратная платформа x86, x86-64, Itanium, ARM
Последняя версия 7.2.0 (8 ноября 2021 года)
Тестовая версия 7.2.0-preview.10 (28 сентября 2021 года)
Читаемые форматы файлов Windows PowerShell types (UTF-8)[d], Windows PowerShell types[d], Windows PowerShell formatting[d], Windows PowerShell formatting (UTF-8)[d], PowerShell Cmdlet Definition XML (UTF-8)[d] и PowerShell Cmdlet Definition XML[d]
Создаваемые форматы файлов Windows PowerShell types (UTF-8)[d], Windows PowerShell types[d], Windows PowerShell formatting[d], Windows PowerShell formatting (UTF-8)[d], PowerShell Cmdlet Definition XML (UTF-8)[d] и PowerShell Cmdlet Definition XML[d]
Лицензия Лицензия MIT
Сайт docs.microsoft.com/ru-ru…
 Медиафайлы на Викискладе

Windows PowerShell 2.0 был выпущен в составе Windows 7, Windows 8 и Windows Server 2008 R2, а также Windows Server 2012 R2 как неотъемлемый компонент системы. Кроме того, вторая версия доступна и для других систем, таких, как Windows XP SP3, Windows Server 2003 SP2, Windows Vista SP1, Windows Vista SP2, Windows Server 2008[3] и Windows Server 2012.

Изначально PowerShell построен на базе Microsoft .NET Framework, а позднее — на .NET, и интегрирован с ними. Дополнительно PowerShell предоставляет удобный доступ к COM, WMI и ADSI, равно как и позволяет выполнять обычные команды командной строки, чтобы создать единое окружение, в котором администраторы смогли бы выполнять различные задачи на локальных и удалённых системах.

Эти административные задачи обычно выполняются с помощью командлетов (в оригинале — „cmdlets“), которые являются специализированными классами .NET. Пользователь может комбинировать их в скриптах (сценариях), используя различные конструкции, утилиты командной строки и обращения к обычным классам .NET, объектам WMI или COM. Кроме того, можно использовать различные хранилища данных, такие, как файловая система или реестр Windows, которые предоставляются PowerShell посредством поставщиков (англ. providers).

PowerShell также предоставляет механизм встраивания, благодаря которому исполняемые компоненты PowerShell могут быть встроены в другие приложения. Эти приложения затем могут использовать функциональность PowerShell для реализации различных операций, включая предоставляемые через графический интерфейс. Этот подход применён в Microsoft Exchange Server 2007 для реализации управляющей функциональности в виде командлетов PowerShell и графических утилит управления в виде оболочек PowerShell, которые вызывают необходимые командлеты. Таким образом, графический интерфейс управления находится поверх промежуточного слоя — PowerShell. Другие приложения Microsoft, включая Microsoft SQL Server 2008, System Center Operations Manager и System Center Data Protection Manager, так же предоставляют доступ к своим интерфейсам управления через командлеты PowerShell.

PowerShell имеет свою собственную расширяемую справку, доступную (в том числе из командной строки) через командлет Get-Help.

Предыстория

Каждая выпущенная версия MS-DOS и Microsoft Windows для персональных компьютеров содержала утилиту, предоставляющую интерфейс командной строки. Это были COMMAND.COM (в системах, основанных на MS-DOS, включая Windows 9x) и cmd.exe (в системах семейства Windows NT). Это были обычные интерпретаторы командной строки, имевшие лишь несколько базовых команд. Для других задач требовались отдельные консольные приложения, которые вызывались из этих оболочек. Они также имели язык сценариев (пакетные файлы), при помощи которого можно было автоматизировать различные задачи. Однако эти интерпретаторы не годились для полноценной автоматизации — частично потому, что в них отсутствовали эквиваленты многих операций графического интерфейса, а также из-за слабой функциональности языка сценариев, не позволявшего описывать достаточно сложные алгоритмы. В Windows Server 2003 ситуация была улучшена, однако поддержка сценариев всё ещё считалась недостаточной.

Microsoft пыталась решить некоторые из этих недостатков с помощью Windows Script Host, вышедшего в 1998 году в составе Windows 98, и утилиты для работы с ним из командной строки cscript.exe. Он интегрируется с Active Script и позволяет писать сценарии на совместимых языках, таких, как JScript и VBScript, используя API, предоставляемое приложениями через Component Object Model (COM). Однако у этого решения свои недочёты. Windows Script Host не интегрирован с оболочкой, отсутствует встроенная документация. Различные версии Windows также предоставляют командные интерпретаторы специального назначения (такие, как netsh.exe и WMIC) со своими собственными наборами команд. Они не интегрированы с командной оболочкой и не дают возможностей для взаимодействия.

В 2003 Microsoft начала разработку новой оболочки, называемой Monad (также известной как Microsoft Shell или MSH). Monad должен был стать новой расширяемой оболочкой командой строки, со свежим дизайном, который позволял бы автоматизировать весь спектр административных задач. Microsoft опубликовала первую публичную бета-версию Monad 17 июня 2005 года. Вторая и третья бета-версии были выпущены 11 сентября 2005 и 10 января 2006 соответственно. 25 апреля 2006 года было объявлено, что Monad переименован в Windows PowerShell для позиционирования его в качестве значительной части их технологий управления. В это же время была выпущена версия Release Candidate 1 («кандидат на выпуск»). Release Candidate 2 последовал 26 сентября 2006 года. Финальная версия (Release to Web, RTW) была выпущена 14 ноября 2006 года для Windows XP SP2 и Windows 2003. Финальная версия для Windows Vista стала доступна только 30 января 2007 года.

Последний community technology preview выпуск Windows PowerShell версии 2.0 был выпущен в декабре 2008 года. Финальная версия второй версии PowerShell была выпущена в составе систем Windows 7 и Windows Server 2008 R2 одновременно с их выпуском. Для остальных систем (Windows XP, Windows Server 2003, Windows Vista, Windows Server 2008), вторая версия PowerShell стала доступна в составе комплекта Windows Management Framework 27 октября 2009 года. Кроме Windows PowerShell второй версии, в этот комплект также входят WinRM версии 2.0 и BITS 4.0 (последний доступен только для Windows Vista и Windows 2008; в Windows 7 и Windows Server 2008 R2 он встроен).

Обзор

Команды, исполняемые в Windows PowerShell, могут быть в форме командлетов, которые являются специализированными классами .NET, созданными с целью предоставления функциональности в PowerShell в виде сценариев PowerShell (.PS1) или являются обычными исполняемыми файлами. Если команда является исполняемым файлом, то PowerShell запускает её в отдельном процессе; если это команда, то он исполняется внутри процесса PowerShell. PowerShell предоставляет интерфейс командной строки, в котором можно вводить команды и отображать выводимые ими данные в текстовом виде. Этот пользовательский интерфейс, базирующийся на стандартном механизме консоли Windows, предоставляет настраиваемый механизм автозавершения команд, но не обладает возможностью подсветки синтаксиса, хотя при желании её можно обеспечить[4]. В PowerShell также можно создавать псевдонимы (англ. alias) для командлетов, которые при вызове преобразуются в оригинальные команды. Кроме того, поддерживаются позиционные и именованные параметры для командлетов. При выполнении командлета работа по привязке значений аргументов к параметрам выполняется самим PowerShell, но при вызове внешних исполняемых файлов аргументы передаются им для самостоятельного разбора.

Другое понятие, используемое в PowerShell, — это конвейер (англ. pipeline). Подобно конвейерам в UNIX, они предназначены для объединения нескольких команд путём передачи выходных данных одной команды во входные данные второй команды, используя оператор |. Но, в отличие от аналога в UNIX, конвейер PowerShell является полностью объектным, то есть данные между командлетами передаются в виде полноценных объектов соответствующих типов, а не как поток байтов. Когда данные передаются как объекты, содержащиеся в них элементы сохраняют свою структуру и типы между командлетами, без необходимости использования какой-либо сериализации или посимвольного разбора данных. Объект также может содержать некоторые функции, предназначенные для работы с данными. Они также становятся доступными для получающего их командлета. Вывод последнего командлета в конвейере PowerShell автоматически передаёт на командлет Write-Host, который создаёт текстовое представление объектов и содержащихся в них данных и выводит его на экран.

Так как все объекты PowerShell являются объектами .NET, они содержат метод .ToString(), возвращающий текстовое представление данных объекта. PowerShell использует этот метод для преобразования объекта в текст. Кроме того, он позволяет указать правила форматирования, так что текстовое представление объектов может быть настроено. Однако с целью поддержания совместимости, если в конвейере используется внешний исполняемый файл, то он получает текстовый поток, представляющий объект, и не интегрируется с системой типов PowerShell.

Расширенная система типов (англ. Extended Type System, ETS) PowerShell базируется на системе типов .NET, но реализует некоторые дополнения. Например, она позволяет создавать различные представления объектов, отображая лишь некоторые из их свойств и методов, а также применять специальное форматирование и механизмы сортировки. Эти представления привязываются к оригинальным объектам с помощью конфигурационных файлов в формате XML.

Командлеты

Командлеты (англ. cmdlets) — это специализированные команды PowerShell, которые реализуют различную функциональность. Это встроенные в PowerShell команды. Командлеты именуются по правилу Глагол-Существительное, например, Get-ChildItem, благодаря чему их предназначение понятно из названия. Командлеты выводят результаты в виде объектов или их коллекций. Дополнительно командлеты могут получать входные данные в такой же форме и, соответственно, использоваться как получатели в конвейере. Хотя PowerShell позволяет передавать по конвейеру массивы и другие коллекции, командлеты всегда обрабатывают объекты поочередно. Для коллекции объектов обработчик командлета вызывается для каждого объекта в коллекции по очереди.

Экземпляры объектов создаются в PowerShell и запускаются им при вызове. Командлеты наследуются от Cmdlet или от PSCmdlet, причём последний используется тогда, когда командлету необходимо взаимодействовать с исполняемой частью PowerShell (англ. PowerShell runtime). В этих базовых классах оговорены некоторые методы — BeginProcessing(), ProcessRecord() и EndProcessing(), как минимум один из которых реализация командлета должна перезаписать для предоставления своей функциональности. Каждый раз при запуске командлета эти методы вызываются PowerShell по очереди. Сначала вызывается BeginProcessing(), затем, если командлету передаются данные по конвейеру, ProcessRecord() для каждого элемента, и в самом конце — EndProcessing(). Класс, реализующий Cmdlet, должен иметь один атрибут .NET — CmdletAttribute, в котором указываются глагол и существительное, составляющие имя командлета. Популярные глаголы представлены в виде перечисления (англ. enum).

Реализации командлетов могут вызывать любые доступные .NET API и могут быть написаны на любом языке .NET. PowerShell также предоставляет некоторые дополнительные API, такие, как WriteObject(), которые необходимы для доступа к специфичной для PowerShell функциональности, например, для вывода результирующих объектов в конвейер. Командлеты могут использовать API для доступа к данным напрямую или воспользоваться инфраструктурой поставщиков (англ. provider) PowerShell, которые позволяют обращаться к хранилищам данных через уникальные пути. Хранилища данных представляются через буквы дисков и иерархическую структуру каталогов внутри них. Windows PowerShell поставляется с поставщиками для файловой системы, реестра Windows, хранилища сертификатов, а также для псевдонимов команд, переменных и функций. Другие приложения могут добавлять свои командлеты и поставщики для доступа к своим хранилищам данных.

В PowerShell 2.0 была добавлена возможность создания командлетов на самом PowerShell, без использования .NET-языков.

Конвейер

В PowerShell, как и в оболочках UNIX/Linux, присутствует конвейер. Этот конвейер служит для передачи выходных данных одного командлета во входные данные другого командлета. В частности, пользователь может вывести результаты командлета Get-Process в командлет Sort-Object (например, для сортировки процессов по дескрипторам), затем — в Where-Object, чтобы отфильтровать процессы, которые, например, занимают меньше 1 МБ страничной памяти, и, в конце концов, передать результаты в командлет Select-Object, чтобы выбрать только первые 10 процессов (по количеству дескрипторов). Концепция конвейера изначально используется в UNIX-подобных системах (см. Конвейер (UNIX)), концепция PowerShell отличается от данного. В UNIX-подобных системах вывод одной команды передаётся на следующий этап конвейера в бинарной форме, то есть являет собой фактически поток данных. Пример: dd if=/dev/zero bs=1M count=1M | bzip2 -z9 -c > ex.bz2, где поток «нулей» блоками по 1 МБ в количестве 1 миллиона раз (из устройства /dev/zero) командой dd (копирования специальных файлов) передаётся на ввод команды Bzip2, которая их сжимает максимально возможно (с точки зрения алгоритма сжатия bzip2, опция -z9) и результирующий поток передаёт на stdout (опция ), который, в свою очередь, перенаправляется в файл ex.bz2. Результатом выполнения такой относительно короткой команды станет создание архива, внутри которого будет поток нулевых байтов размером 1 терабайт. Сам процесс создания такого архива применяет в данном случае 2 последовательных конвейера.

Сценарии

PowerShell включает в себя язык сценариев с динамическими типами, на котором можно реализовывать сложные операции с использованием командлетов. Язык сценариев поддерживает переменные, функции, конструкции ветвления (if-then-else) циклы (while, do, for и foreach), структурированную обработку ошибок и множество других возможностей, включая интеграцию с .NET. Переменные в PowerShell обозначаются префиксом $ перед именем; им может быть присвоено любое значение, включая вывод командлетов. Хотя сам язык не строго типизирован, внутри переменные сохраняются со своими типами, которые могут быть базовыми типами (англ. primitive types) или объектами. Строки могут быть заключены в одиночные кавычки или в двойные кавычки: при использовании двойных кавычек переменные, содержащиеся в строке, будут заменены их значениями. В соответствии с синтаксисом переменных, если путь к файлу помещен в фигурные скобки с предшествующим знаком доллара (то есть ${C:\foo.txt}), то это будет ссылкой на содержимое файла. Всё, что будет назначено такой переменной, будет записано в файл, и наоборот — при обращении к её содержимому будет выдано содержимое файла.

К свойствам и методам объекта можно обращаться, используя точку (.), как в синтаксисе C#. PowerShell предоставляет специальные переменные, такие, как $args, содержащую массив всех неименованных аргументов командной строки, переданных функции, или $_, ссылающуюся на текущий объект в конвейере и других конструкциях. В PowerShell также присутствуют массивы и ассоциативные массивы. Кроме того, PowerShell автоматически вычисляет арифметические выражения, введённые в командной строке, и понимает популярные аббревиатуры, такие, как GB (ГБ), MB (МБ) и KB (КБ).

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

  1. <function> <param1> <param2>: Вызывает функцию с двумя аргументами.

Эти аргументы могут быть привязаны к параметрам, указанным в объявлении функции. Также к ним можно обратиться через массив $args.

  1. <function>(<param1>, <param2>): вызывает функцию с одним аргументом, который является массивом из двух элементов.

PowerShell позволяет вызывать любые методы .NET, заключив их пространство имён в квадратные скобки ([]), и затем используя пару двоеточий (::) для указания статического метода. Например, [System.Console]::WriteLine("PowerShell"). Объекты создаются с помощью командлета New-Object, добавлять к ним новые свойства можно, используя командлет Add-Member.

Для обработки ошибок PowerShell предоставляет механизм, основанный на .NET. В случае ошибки выдаются объекты, содержащие информацию об ошибке (объект Exception), которые перехватываются ключевым словом trap. Однако поведение при возникновении ошибок настраивается. Так, можно настроить PowerShell, чтобы в случае ошибки он молча продолжал выполнение без перехвата ошибки. Во второй версии PowerShell также была добавлена конструкция Try Catch Finally.

Сценарии, написанные в PowerShell, можно сохранять между сессиями в файлах .PS1. Затем можно использовать весь сценарий или индивидуальные функции из него. Сценарии и функции используются подобно командлетам, то есть они могут быть командами в конвейере, им можно передавать параметры. Объекты могут прозрачно передаваться между сценариями, функциями и командлетами в конвейере. Однако выполнение сценариев PowerShell по умолчанию запрещено, и его надо включить с помощью командлета Set-ExecutionPolicy. Сценарии PowerShell могут быть подписаны цифровой подписью для проверки их целостности.

PowerShell 2.0

Microsoft выпустила PowerShell 2.0 в составе Windows 7 и Windows Server 2008 R2. Windows PowerShell 2.0 предустановлен в этих системах. Исключением является режим установки Windows Server 2008 R2 в режиме Core, где PowerShell 2.0 можно доустановить вручную. Для более старых платформ он доступен в составе Windows Management Framework. PowerShell 2.0 вносит некоторые изменения в язык сценариев и API для встраивания, в дополнение к новым 240 командлетам.

Неполный список новых возможностей, включённых в PowerShell 2.0:

  • Удаленный вызов PowerShell (PowerShell Remoting). Используя WS-Management, PowerShell 2.0 позволяет вызывать сценарии и командлеты на удалённых машинах (в том числе и на нескольких одновременно), отслеживать состояние их выполнения и получать результаты в виде объектов (через сериализацию-десериализацию). Также возможно устанавливать интерактивные сессии и сессии с ограниченной функциональностью.
  • Фоновые задания (Background jobs). Возможность вызывать последовательности команд асинхронно. Работы можно запускать на локальной машине или на нескольких удалённых машинах. Работы не могут использовать интерактивные командлеты.
  • Транзакции (Transactions). Позволяют разработчикам командлетов и поставщиков реализовывать транзакционные операции. PowerShell 2.0 включает командлеты для инициализации, подтверждения и отката транзакций и возможности для управления транзакциями и использования их в командлетах и поставщиках.
  • Расширенные функции (Advanced Functions). Возможность разрабатывать полноценные командлеты, используя только сам PowerShell.
  • Пошаговый конвейер (SteppablePipelines). Позволяет пользователю контролировать вызов функций BeginProcessing(), ProcessRecord() и EndProcessing() при вызове командлета.
  • Модули (Modules). Позволяют авторам сценариев и администраторам организовывать сценарии PowerShell и помещать их в самодостаточные модули. Код из модуля выполняется в своем собственном, независимом контексте и не влияет на окружение вне модуля. Используя сценарий, модули могут объявлять ограниченное окружение. Модули могут содержать публичные и приватные функции и переменные.
  • Язык данных (Data language). Подмножество языка PowerShell, которое позволяет отделять определения данных от исполняемого кода сценариев и даёт возможность импортировать в сценарий локализованные строки в процессе выполнения.
  • Отладка сценариев (Script debugging). Возможность устанавливать точки прерывания (англ. breakpoints) в сценариях или функциях PowerShell. Точки прерывания могут быть установлены на строки, столбцы, команды или операции чтения и/или записи переменных. Присутствуют командлеты для установки и контроля точек прерывания в сценариях.
  • Обработка событий (Eventing). Эта возможность позволяет слушать, перенаправлять, и выполнять действия при возникновении событий управления или системы. Благодаря событиям хосты PowerShell могут быть оповещены о изменениях состояния в управляемых объектах. Также позволяет сценариям подписываться на ObjectEvents, PSEvents и WmiEvents и обрабатывать их синхронно и асинхронно.
  • Интегрированная среда скриптов Windows PowerShell (Windows PowerShell Integrated Scripting Environment (ISE)). PowerShell 2.0 включает графическую оболочку для языка, в которую входят встроенный отладчик, подсветка синтаксиса, автозавершение команд. Оболочка позволяет запускать несколько независимых консолей PowerShell с полной поддержкой Юникода в интерфейсе с закладками. Благодаря поддержке удалённого выполнения некоторые консоли могут выполняться и на других компьютерах. Кроме того, ISE позволяет выполнять только выделенные части сценариев, содержит встроенный редактор и позволяет расширять и дополнять свой интерфейс с помощью PowerShell.
  • Передача файлов по сети — встроенная поддержка передачи файлов по сети с приоритизацией, многопоточностью, возобновлением и асинхронной работой на основе технологии Background Intelligent Transfer Service.
  • Новые командлеты — множество новых командлетов, включая, например, Out-GridView, позволяющий вывести результаты конвейера в графическую таблицу (на основе WPF), с возможностями сортировки и мгновенного поиска.
  • Новые операторы -Split, -Join и оператор подстановки (@).
  • Обработка ошибок с Try-Catch-Finally. В отличие от других .NET языков, в PowerShell можно указывать несколько типов исключений для одного блока catch.
  • Блочные комментарии. PowerShell 2.0 поддерживает блочные комментарии (плюс к уже имеющимся построчным #) с использованием <# и #> в качестве ограничителей.
  • Новые API: добавили разные возможности, от большего контроля над парсером PowerShell до способности создавать ограниченные сессии (англ. restricted runspace), в которых можно выполнять лишь ограниченный набор инструкций и команд PowerShell.

Сравнение командлетов с аналогичными командами

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

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

Windows PowerShell
(Cmdlet)
Windows PowerShell
(Alias)
cmd.exe / COMMAND.COM
(MS-DOS, Windows, OS/2, etc.)
Bash
(Unix, BSD, Linux, Mac OS X и т. п.)
Описание
Get-Location gl, pwd cd[5] pwd Отображает текущий рабочий каталог
Set-Location sl, cd, chdir cd, chdir cd Меняет текущий каталог
Clear-Host cls, clear cls clear Очищает экран[6]
Copy-Item cpi, copy, cp copy cp Копирует один или несколько файлов или дерево каталогов (в PowerShell также можно копировать объекты других поставщиков данных)
Get-Help help, man help man Справка по командам
Remove-Item ri, del, erase, rmdir, rd, rm del, erase, rmdir, rd rm, rmdir Удаляет файл/каталог (или другой элемент в поставщиках данных PowerShell).
Rename-Item rni, ren ren, rename mv Переименовывает файл/каталог
Move-Item mi, move, mv move mv Перемещает файл/каталог в новое местоположение
Get-ChildItem gci, dir, ls dir ls Выводит все файлы/каталоги в текущем каталоге
Write-Output echo, write echo echo Выводит строки, переменные на стандартный вывод
Pop-Location popd popd popd Изменяет текущий каталог на тот, который был последним помещён в стек
Push-Location pushd pushd pushd Помещает текущий каталог в стек
Set-Variable sv, set set set Установка значения переменной/создание переменной
Get-Content gc, type, cat type cat Получает содержимое файла
Select-String sls find, findstr grep Выводит строки, подходящие под условие
Get-Process gps, ps tlist,[7] tasklist[8] ps Выводит все запущенные процессы
Stop-Process spps, kill kill,[7] taskkill[8] kill Останавливает запущенный процесс
Tee-Object tee n/a tee Передаёт входные данные в файл или переменную, затем передаёт их дальше по конвейеру

См. также

  • Сравнение командных оболочек
  • PowerShell ISE

Примечания

  1. The powershell Open Source Project on Open Hub: Languages Page — 2006.
  2. PowerShell/PowerShell. GitHub. Дата обращения: 20 августа 2016.
  3. Описание Windows Management Framework
  4. Realtime Syntax Highlighting in PowerShell Console " PowerShell и другие скрипты
  5. cd без параметров выводит текущий каталог.
  6. Clear-Host реализован как предопределённая функция PowerShell.
  7. Available in Windows NT4, Windows 98 Resource Kit, Windows 2000 Support Tools
  8. Available in Windows XP Professional Edition and later

Литература

  • Попов А.В. Введение в Windows PowerShell. СПб.: БХВ-Петербург, 2009. — С. 464. — ISBN 978-5-9775-0283-2.

Ссылки

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.