Сбор информации о компьютерах

Как с помощью PowerShell загрузить файл на компьютер?

В данном примере, нам понадобится вот такая команда:

$client = new-object $ ( “Ссылка для скачивания”, “Путь к файлу”)

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

Таким образом, мы получаем в пример следующую команду:

$client = new-object $(“”,”C:\Users\Andrey\Desktop\”)

Если вы хотите загрузить файл в Dropbox или какой-то другой подобный сервис, то в эту службу, конечно, нужно будет войти, для этого, мы между уже данными командами вставим еще одну:

$ = Get-Credential

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

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

$client = new-object $ = Get-Credential $(“”,”C:\Users\Andrey\Desktop\”)

Команды PowerShell для автоматизации Office 365

автоматизации Office 365:

1. Подключение к приложению Office 365 с помощью PowerShell

Windows PowerShell

  • Cкачайте и установите Помощник по входу в Microsoft Online Services для ИТ-специалистов, RTW.
  • Импортируйте модуль PowerShell Online Services для Microsoft Azure Active Directory и Office 365, используя следующие команды в PowerShell:
  • Введите свои учетные данные администратора Office 365:

    Теперь вам нужно создать сеанс PowerShell от имени удаленного пользователя. Это можно сделать с помощью следующей команды:

  • Теперь импортируйте команды сеанса в локальный сеанс Windows PowerShell:
  • Наконец, подключите сеанс ко всем своим службам Office 365 с помощью этой команды:

    Это подключит PowerShell для Office 365 к вашему инстансу Office 365 и позволит управлять им.

2. Подключение к Exchange Online и SharePoint Online с помощью PowerShell

  • Подключение к Exchange Online, по сути, происходит так же, как и подключение к Office 365. Вот соответствующие команды:
  • Подключение к SharePoint Online немного сложнее, и вам потребуется установить дополнительное программное обеспечение.
    Сначала установите компонент командной консоли SharePoint Online.
    Затем запустите из PowerShell следующую команду:

3. Cписок доступных командлетов PowerShell для Office 365

  • Чтобы получить список всех доступных командлетов для MSOnline, выполните следующую команду:
  • Вы также можете запустить ту же команду, чтобы увидеть список всех доступных командлетов для Azure Active Directory, просто заменив переменную -module:

4. Cписок всех пользователей Office 365

Get-msoluser

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

Создаем разделы на диске

Чтобы создать новый раздел на диске используется командлет New-Partition. Создадим раздел размером 10 Гб и назначим ему букву диска L:

New-Partition –DiskNumber 1 -Size 10gb -DriveLetter L

Если раздел должен занимать все доступное место на диске, используйте атрибут UseMaximumSize. Для автоматического назначения буквы диска используется параметр AssignDriveLetter (иногда буква диска может автоматически на назначаться).

New-Partition –DiskNumber 1 -AssignDriveLetter –UseMaximumSize

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

Set-Partition –DriveLetter L -NewDriveLetter U

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

Get-PartitionSupportedSize -DriveLetter L | Format-List

Потом можно увеличить размер раздела до максимального:

$MaxSize = (Get-PartitionSupportedSize -DriveLetter L).SizeMaxResize-Partition -DriveLetter L -Size $MaxSize

Если нужно сделать конкретный раздел активным используется команда:

Set-Partition -DriveLetter T -IsActive $true

Выбор отображаемых свойств

Командлеты: Format-List, Format-Table и Sort-Object

Выполнение любого командлета без параметров позволяет увидеть лишь некоторые свойства. Их полный список можно вывести, перенаправив вывод в командлет Format-List.

Get-PhysicalDisk | fl *

Любое свойство можно вывести в таблице с помощью командлета Format-Table, выровняв столбцы по ширине содержимого. Давайте отобразим нужное и уберем лишнее:

Get-PhysicalDisk | ft -AutoSize DeviceId,Model,MediaType,BusType,Size

В PowerShell Windows 8 обнаружилось решение задачи, которое я безуспешно искал со времен Windows 7 для утилиты CheckBootSpeed. Теперь с помощью командлета Get-PhysicalDisk можно определить тип накопителя – SSD или HDD!

DeviceId Model                      MediaType   BusType         Size
-------- -----                      ---------   -------         ----
2        TOSHIBA MK7559GSXP         HDD         SATA    750156374016
0        Samsung SSD 840 PRO Series SSD         SATA    256060514304
1        KINGSTON SH103S3120G       SSD         SATA    120034123776
4         Transcend                 UnSpecified USB     319169757184
3        SNA-DC/U                   UnSpecified USB     249376538624
Get-PhysicalDisk | sort DeviceId | ft -AutoSize DeviceId,Model,MediaType,BusType,Size

Я не случайно вывел в результатах BusType — тип шины! Основным диском в моем планшете служит eMMC SSD, и по сути – это карта памяти (вторая вставлена в слот для увеличения дискового пространства).

DeviceId Model  MediaType BusType        Size
-------- -----  --------- -------        ----
0        MBG4GA SSD       SD      31226593280
1        SD     SSD       SD      31611420672

Я уже писал об этом в обзоре платформы Clover Trail и даже показывал там, что . Любопытно, что в Windows 8.1 он уже показывает модель диска, что более конкретно, но в то же время скрывает истинную натуру SSD. PowerShell же срывает покровы :)

Кстати, размер дисков получился в байтах, но к этому я вернусь чуть позже. Аналогичные команды для Get-Disk и Get-Partition попробуйте самостоятельно или смотрите, какие свойства выбрал я.

Обработка собранных статистических данных

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

Система, вероятно, установлена на SSD (скорость случайного чтения - 210.92000 MB/s)

Из-за бага бета-версии, упомянутого в начале записи, у нескольких людей скорость не определилась, но это не суть важно

Задача

Я изначально складывал отчеты по четырем папкам, в зависимости от ОС и типа накопителя. Поэтому проблема формулировалась так:

  1. Обработать все файлы в папках
  2. Найти в каждом файле строку с измеренной скоростью
  3. Извлечь значение скорости
  4. Вывести все значения

PowerShell эта задача вполне по плечу, причем дальше вы увидите два варианта решения.

Извлечение фрагмента строки из набора файлов с помощью PowerShell

Я слабо владею PowerShell, поэтому применил подход, который сработает, наверное, в любом языке. Сначала я создал переменную и объявил новый массив.

$Path = "$env:userprofile\Documents\Scripts\CBS-Results\"
$myArray = @()

Затем с помощью командлета Get-ChildItem я организовал рекурсивную обработку папки. Полученные данные передаются по конвейеру командлету Select-String, который выбирает строки, совпадающие с заданным шаблоном. Каждая найденная строка добавляется в массив оператором “+=”.

$myArray += get-childitem $Path -recurse | select-string -pattern "чтения -"

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

foreach ($element in $myArray){
$element.line -match "- (.{6})" | out-null
$matches}

В результате получается аккуратный столбик данных.

Дело было сделано, но я решил показать решение эксперту. Вадимс сразу сказал, что мой код коричневый и дурно пахнет :) Он также отметил, что сам бы сделал «ванлайнер» (решение в одну строку), но это будет выглядеть сложно.

После таких заявлений от «ванлайнера» ему уже было не отвертеться, и вот что я получил в Skype через несколько минут:

dir -rec | select-string -pattern "чтения -" | %{$_ -replace ".+я" -replace ""}

Здесь dir — это просто алиас командлета Get-ChildItem. Становится ясно, что можно обойтись и без массива. Но в любом случае мне не по зубам регулярные выражения, которыми Вадимс решил задачу. Однако мораль в том, что даже новичок в PowerShell может решить задачу, пользуясь подсказками гуглояндекса при необходимости.

Диаграммы в Excel

Дальше данные в наглядном виде представляет уже Excel. Запись была запланирована заранее, поэтому не все отчеты покрыты, но картина будет ясна и так. Напомню, что это оценка winsat:

winsat disk -ran -read -drive %SystemDrive:~0,1%

При этом выполняется случайное чтение блоков 16KB.

Как видите, лишь один жесткий диск перевалил через 3MB/s. Таким образом, можно считать корректным барьер в 8MB/s, который использует утилита для определения типа накопителя.

Для SSD это семечки, и даже самые посредственные SSD здесь в разы быстрее жестких дисков.

Ваши отчеты очень помогли мне собрать еще кое-какие данные, но они будут фигурировать в одной из будущих записей блога, примерно через пару недель. Не пропустите сие тайное знание :)

Подключение дисков под другим пользователем

Обе команды позволяют выполнять подключение используя других пользователей. Для каждой из команд этот подход отличается.

В случае команды ‘New-PSDrive’ вам нужно будет выполнить ‘Get-Credential’ и поместить в него учетные данные. Традиционный способ поместить эти данные в переменную:

Эта переменная будет хранить ссылку на объект в памяти, который нельзя будет экспортировать на другой компьютер. Как упростить процесс, если вы планируете использовать учетные данные на разных компьютерах, рассмотрено в другой статье.

После этого мы передаем переменную в параметр ‘-Credential’:

В случае с ‘New-SMBMapping’ эта операция выполняется проще. У вас есть 3 параметра, которые нужно заполнить:

  • UserName — логин;
  • Password — пароль;
  • SaveCredential — нужно ли сохранять учетные данные.

Пример подключения с сохранением учетных данных:

Проблема, которую не получилось решить на разных версиях Powershell, связана с параметром ‘-SaveCredentials’. Его указание приводит к ошибке «New-SmbMapping : The parameter is incorrect.». Его отсутствие — не сохраняет введенные учетные данные и после перезагрузки связь с диском может пропасть если не добавить соответствующую запись в ‘Credential Manager’. 

Количество файлов в папках и размер папок

PowerShell скрипт выводит на экран и в файл D:\CountFiles.csv информацию о том, сколько содержит файлов каждая папка и подпапки в директории D:\Photos, а также размер этих папок и подпапок. csv файл можно импортировать в exel или гугл-таблицы и отсортировать столбцы по возрастанию или спаданию. Скрипт может пригодиться при оптимизации файлового хранилища.

$source="D:\Photos"
Get-ChildItem $source -recurse -force | where {$_.psIscontainer} | foreach {
   $count = Get-ChildItem $_.fullname -recurse | where {$_.length} | Measure-Object -property length -Sum
   Write-Host($_.FullName)
   $FilesSize = '{0:F}' -f ((($count.Sum)/1024)/1024)
   Write-Host("Files: " + $count.count )
   Write-Host("Size: " + $FilesSize + " MB")
   '"' + $_.FullName + '","' + $count.count + '","' + $FilesSize + '"' | Out-File D:\CountFiles.csv -Append
}

Создание сценария с использованием интегрированной среды сценариев (ISE)

Кроме того, вы можете использовать консоль PowerShell ISE для написания сценариев в Windows 10.

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

  1. Откройте Пуск.
  2. Найдите Windows PowerShell ISE, щелкните правой кнопкой мыши и выберите параметр «Запуск от имени администратора».
  3. Среда запустится с пустым файлом .ps1, где вы можете создать или вставить скрипт, который хотите запустить. Например: Write-Host «Congratulations! Your first script executed successfully»
  4. Нажмите меню Файл.
  5. Нажмите «Сохранить».
  6. Введите имя для сценария. Например, first_
  7. Нажмите кнопку Сохранить.

Информация об обновлениях WSUS

Этот Powershell скрипт получает информацию со WSUS и показывает:

  • количество обновлений по заданных критериям
  • краткую сводную информацию об обновлениях
  • имена обновлений
  • отображает список обновлений по заданным критериям для каждого компьютера по отдельности
$WSUSServer = 'SERVER_NAME' #WSUS-сервер
$PortNumber = 8530 #http порт wsus
::LoadWithPartialName("Microsoft.UpdateServices.Administration")
$wsus = ::getUpdateServer($WSUSServer,$False,$PortNumber)
$UpdateScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
#$UpdateScope.ApprovedStates = 'NotApproved' #указываем критерии апдейтов: не одобренные
#$UpdateScope.IncludedInstallationStates = 'NotInstalled' #указываем критерии апдейтов: не проинсталированные
$UpdateScope.IncludedInstallationStates = 'Installed' #указываем критерии апдейтов: проинсталированные
$UpdateScope #просматриваем сформированные критерии апдейтов
$wsus.GetUpdateCount($updatescope) #получаем и выводим количество апдейтов
$wsus.GetUpdateStatus($updatescope,$False) #получаем и выводим краткую информацию об обновлениях
$wsus.GetUpdates($updatescope).Title #выводим имена апдейтов

$computers = $wsus.GetComputerTargets() #все компьютеры со wsus
ForEach ($computer in $computers){ #для каждого компьютера
 $Computername = $computer.fulldomainname #получаем его имя 
 $updates = $computer.GetUpdateInstallationInfoPerUpdate($updateScope) #получаем апдейты по указаным критериям
 $UpdateCount = $updates.Count #количество апдейтов для текущего компьютера
 write-host $Computername $UpdateCount #выводим имя компьютера и количество апдейтов
 $i = 0
 ForEach ($update in $updates) { #для каждого апдейта выводим подробную информацию 
 $i++
 $update_info = $update.GetUpdate() #запрашиваем инфо об апдейте
 $UpdateTitle = $update_info.Title #имя апдейта
 $IsApproved = $update_info.IsApproved #является ли он одобренным 
 write-host $Computername $i "of" $UpdateCount $IsApproved $UpdateTitle 
 }
}

Шаг 2. Создание виртуального диска

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

  1. Если мастер создания виртуального диска еще не открыт, на странице Пулы носителей в диспетчере серверов в разделе ПУЛЫ НОСИТЕЛЕЙ выберите нужный пул носителей.

  2. В разделе Виртуальные диски выберите список задачи , а затем выберите новый виртуальный диск. Откроется мастер создания виртуальных дисков.

  3. На странице перед началом выполнения нажмите кнопку Далее.

  4. На странице Выбор пула носителей выберите нужный пул носителей и нажмите кнопку Далее.

  5. На странице Указание имени виртуального диска введите имя и описание (необязательно), а затем нажмите кнопку Далее.

  6. На странице Выбор макета хранилища выберите нужный макет, а затем нажмите кнопку Далее.

    Примечание

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

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

    • Двухстороннее зеркало
    • Трехстороннее зеркало
  8. На странице Укажите тип подготовки выберите один из следующих параметров, а затем нажмите кнопку Далее.

    • Тонкая

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

    • Фиксированный формат

      При фиксированной подготовке емкость хранилища выделяется немедленно в момент создания виртуального диска. Таким образом, при фиксированной подготовке используется пространство из пула носителей, эквивалентное размеру виртуального диска.

      Совет

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

  9. На странице Указание размера виртуального диска выполните следующие действия.

    Если на предыдущем шаге вы выбрали фиксированную подготовку, выберите один из следующих элементов:

    • Задать размер

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

    • Максимальный размер

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

  10. На странице Подтверждение выбора Проверьте правильность параметров и нажмите кнопку создать.

  11. На странице Просмотр результатов убедитесь, что все задачи завершены, а затем нажмите кнопку Закрыть.

    Совет

    По умолчанию флажок Создать том при закрытии мастера установлен. После этого вы перейдете сразу же к следующему шагу.

Windows PowerShell эквивалентные команды для создания виртуальных дисков

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

В следующем примере создается виртуальный диск 50 ГБ с именем VirtualDisk1 в пуле носителей с именем StoragePool1.

В следующем примере создается зеркальный виртуальный диск с именем VirtualDisk1 в пуле носителей с именем StoragePool1. Диск использует максимальный объем хранилища для пула носителей.

В следующем примере создается виртуальный диск 50 ГБ с именем VirtualDisk1 в пуле носителей с именем StoragePool1. Для диска используется тонкая подготовка.

В следующем примере создается виртуальный диск с именем VirtualDisk1 в пуле носителей с именем StoragePool1. Для диска используется трехстороннее зеркальное отображение, а его размер фиксирован и равен 20 ГБ.

Примечание

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

Настройка текущего расположения (Set-Location)

Команда используется с командой . Команда позволяет вам указать расположение текущего каталога.

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

Чтобы проверить успешность внесения изменения в каталог при вводе команды , включите параметр -PassThru при вводе команды :

Параметр PassThru можно использовать с некоторыми командами Set в Windows PowerShell для возврата сведений о результате, когда отсутствуют выходные данные по умолчанию.

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

Например, если вы находитесь в папке , точка () представляет , а две точки () представляют . Текущее расположение можно изменить на корень диска C: путем ввода следующей команды:

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

После этого можно изменить расположение каталога на родительский каталог, который является корнем диска Windows PowerShell HKLM: с помощью относительного пути:

Вы можете ввести или использовать любой из встроенных псевдонимов Windows PowerShell для (cd, chdir, sl). Пример:

Определение версии операционной системы

Класс .NET: | Тип данных:

Windows 7 и Windows 8 – это маркетинговые версии ОС, а «техническую» можно посмотреть, набрав в консоли winver.

В PowerShell ее можно извлечь массой способов, и самый распространенный:

(Get-WmiObject Win32_OperatingSystem).Version

Задача сводится к превращению текстовой строки 6.3.9600 в дробное число вида 6.3. Я понятия не имел, как это сделать, и нагуглил решение, показывать которое я не буду :) Да, оно работало, но Вадимс посоветовал не использовать WMI для таких задач, а обратиться к классу Environment в .NET Framework, на котором построен PowerShell.

::osversion.Version

Major  Minor  Build  Revision
-----  -----  -----  --------
6      3      9600   0

Вадимс объяснил, что такой подход значительно ускоряет запрос, потому что при запуске PowerShell эти классы уже загружены. В подтверждение тезиса он сравнил время выполнения команд с помощью командлета Measure-Command. Получилось в сто раз быстрее!

PS C:\> 1..5 | %{(measure-command {(Get-WmiObject Win32_OperatingSystem).OSVersion}).TotalMilliseconds}
45,5833
35,9619
25,5198
35,6166
16,0488
PS C:\> 1..5 | %{(measure-command {::osversion.version}).TotalMilliseconds}
0,7387
0,0717
0,0675
0,064
0,0354

В десятичную дробь с одним знаком после запятой (6.3) это превращается так:

::osversion.version.tostring(2) 

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

Получение серверов

Основой сценария, который мы создаем, являются сами серверы. Вы можете записать их по отдельности в текстовом файле, который читается, или в массиве внутри самого скрипта, но используя PowerShell, мы можем сделать это лучше. Чтобы сделать сценарий более динамичным и не требовать от нас его изменения при каждом добавлении нового сервера, мы можем использовать Active Directory (AD), чтобы получить список объектов компьютера в данной организационной единице (OU).

Ниже мы используем модуль, доступный в Инструментарий RSAT, чтобы запросить OU и получить все объекты компьютера через ,

На этом этапе мы могли бы отфильтровать только свойство name, чтобы заполнить переменная, но часто очень полезно иметь весь возвращаемый объект для последующего использования.

Вывод производителя и модели компьютера

Сведения о модели компьютера также доступны в Win32_ComputerSystem. Чтобы получить данные поставщика вычислительной техники (OEM), стандартные отображаемые выходные данные фильтровать не нужно:

Get-CimInstance -ClassName Win32_ComputerSystem
Name PrimaryOwnerName Domain    TotalPhysicalMemory Model                   Manufacturer
---- ---------------- ------    ------------------- -----                   ------------
MyPC Jane Doe         WORKGROUP 804765696           DA243A-ABA 6415cl NA910 Compaq Presario 06

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

Итоги тестирования

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

  • улучшена логика определения скорости накопителя: если winsat не отрабатывает, делается попытка извлечь скорость диска из недавней формальной оценки
  • добавлены сведения о дате установки ОС (я забыл это включить в бету, хотя по косвенным признакам отчета можно было определить, что система «свежая»)
  • добавлено исправление одного из параметров ReadyBoot в реестре, предложенное двумя читателями в комментариях
  • ускорено выполнение некоторых команд за счет оптимизации кода (спасибо за советы Вадимсу Подансу, MVP PowerShell)

Вывод установленных исправлений

Список всех установленных исправлений можно получить с помощью Win32_QuickFixEngineering:

Этот класс возвращает список исправлений в следующем виде:

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

Дополнительные данные выводятся, так как параметр Property в ограничивает свойства, возвращаемые из экземпляров класса WMI, но не объекты, возвращаемые оболочке PowerShell. Командлет позволяет сократить возвращаемые выходные данные:

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Ваша ОС
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: