PowerShell: Get-ADComputer – получение информации о компьютерах Active Directory. Powershell имя компьютера


PowerShell: Получение информации о компьютерах в домене и TimeZone

В ночь с 29 на 30 октября 2011 в России должен был быть переход на зимнее время, однако волевым решение президента переходы на летнее и зимнее время были отменены, и Россия остается на летнем времени.  Значит многие IT специалисты столкнулись с задачей обновления всех систем и в частности, необходимо обновить все клиентские и все серверные операционные системы. Компания Microsoft выпустила очередное обновление для исправления временных зон, учитывающее последние изменения  KB2570791. Это обновление необходимо установить на все Windows машины, «для гладкого» прохождения ночи с 29 на 30 октября, без возможных последствий из-за внесенных изменений.

В случае если в текущей инфраструктуре большое количество серверов и машин, то бегать ногами к каждой машине и устанавливать обновление KB2570791 займет массу времени и сил. Поэтому, те кто привык работать головой, а не ногами (руками), давно уже имеют равернутый Microsoft Windows Server Update Services (WSUS), а то и не один.

Однако, что делать с компьютерами, которые в силы каких либо причин, находятся в домене, но не зарегистрировались на WSUS, либо из-за все возможных причин давно к нему не обращались. Один из вариантов, опросить все доступные в сети компьютеры и проверить корректность установки данного обновления. В этом нам может помочь Powershell, Vbs, AutoIT и другие подобные инструменты.

Далее предлагается один из вариантов решения задачи поиска машин в доменной сети с неустановленным обновлением KB2570791.

В качестве исходных данных, требуется только список машин в домене, его легко получить из оснастки Active Directory Users and Computers (dsa.msc), используя Saved Query. В итоге полученный список серверов и компьютеров в домене  экспортируется в csv-файл, и этот файл является источником информации о компьютерах в сети. Основная  информация, которая нам необходима в этом файле, это имя машины (поле Name).

Далее этот файл обрабатывается следующим образом:

  1. Проверяется, пингуется и ли машина
  2. Если машина пингуется, то проверяется:
    1. Текущая настройка TimeZone
    2. IP адрес
    3. Версию ОС
    4. Текущий пользователь
    5. Установлено ли обновление KB2570791
  3. На основании данных п. 2 принимается решение о статусе обновления машины.

На выходе, получим следующую информацию:

  1. Список машин, которые не пингуются
  2. Список не обновленных машин
  3. Список обновленных машин
  4. Список машин, с настройками других временных зон

Чтобы реализовать выше описанное, потребуется:

  1. функция проверки отвечает ли хост на ping
  2. функция сбора информации о хосте
  1. Чтобы проверить пингуется ли удаленная машина, используется следующий набор команд:
$ping = New-Object System.Net.NetworkInformation.Ping $ping.Send($CompName)

Где $CompName – это имя машины

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

############################################################ ##### Функция проверки доступности компьютера ##### ############################################################ Function IsReply($CompName) { $ping = New-Object System.Net.NetworkInformation.Ping try { $Reply = $ping.Send($CompName) } catch { Write-host "Для машины " $CompName "не удалось выполнить ping" } return $Reply.status }

 

  1. Чтобы собрать необходимую информацию для данной задачи о удаленной машине, понадобится несколько командлетов.2.1 Для получения информации о удаленной машине будет использоваться функция Get-WmiObject, и классы WMI, так как это не накладывает дополнительных требований на удаленные машины.

Командлет Get-WmiObject отображает экземпляры классов WMI или сведения о доступных классах WMI. Параметр ComputerName всегда можно использовать для указания удаленного компьютера. При задании параметра List этот командлет извлекает сведения о классах WMI, доступных в заданном пространстве имен. При указании параметра Query командлет запускает инструкцию языка запросов WMI (WQL).

Командлет Get-WmiObject не использует инфраструктуру удаленного взаимодействия Windows PowerShell для выполнения удаленных операций. Параметр ComputerName командлета Get-WmiObject можно использовать, даже если компьютер не соответствует требованиям для удаленного взаимодействия Windows PowerShell и не настроен на удаленное взаимодействие в Windows PowerShell.

Для сбора информации о машине, будут использоваться следующие WMI-классы:

  • Win32_TimeZone – для определения временной зоны
  • Win32_NetworkAdapterConfiguration – для определения настроенных IP адресов
  • Win32_OperatingSystem —  для определения версии операционной системы и Service Pack
  • Win32_ComputerSystem – для определения пользователя компьютера

Для получение полного списка доступных WMI-классов, можно использовать команду:

Get-WmiObject -List

При определении TimeZone, одно из самых наглядных параметров класса Win32_TimeZone, является свойство Caption. Его значение на обновленной машине выглядит следующим образом:

(UTC+04:00) Moscow, St. Petersburg, Volgograd

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

2.2 Для получения информации о том, есть ли на удаленной машине обновление KB2570791, будет использоваться командлет Get-Hotfix.

Командлет Get-Hotfix возвращает исправления, примененные на локальном компьютере или на удаленных компьютерах с помощью компонентной модели CBS.

Но так как, получать полный список установленных обновлений, для решения данной задачи, нет необходимости, то полученные результаты отфильтруем по обновлению KB2570791:

Get-Hotfix -ComputerName $CompName | where-Object {($_.HotFixID -Like "*KB2570791*")}

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

############################################################ ##### Функция получения информации о компьютере ##### ############################################################ Function Get-Info ($CompName) { # Получаем информация о текущих настройках TimeZone $TZ = Get-WmiObject -Class "Win32_TimeZone" -namespace "root\\CIMV2" -computername $CompName -ErrorAction SilentlyContinue # Получаем информацию о IP адресе $IP = Get-WmiObject -Class "Win32_NetworkAdapterConfiguration" -namespace "root\\CIMV2" -computername $CompName -ErrorAction SilentlyContinue| Select-Object IPAddress |Where-Object { $_.IPAddress -ne $null } # Получаем информацию о версии операционной системы $OS = Get-WmiObject -Class "Win32_operatingSystem" -namespace "root\\CIMV2" -computername $CompName -ErrorAction SilentlyContinue #Получаем информацию о пользователе на компьютере $USER = Get-WmiObject -Class "Win32_ComputerSystem" -namespace "root\\CIMV2" -computername $CompName -ErrorAction SilentlyContinue if ((!$TZ) -or (!$IP) -or (!$OS) -or (!$USER)) { # Если ничего не удалось определить, то считаем что с компьютером не все в порядке return "Failed" } else { # Проверяем: установлен ли Update KB2570791 $UpdateForTZ = Get-Hotfix -ComputerName $CompName | where-Object {($_.HotFixID -Like "*KB2570791*")} #Полученная информация сохраняется для поиска возможных проблем If ($UpdateForTZ.HotFixID -ne $null) { $IsHostFix = "There is update " + $UpdateForTZ.HotFixID } else { $IsHostFix = "There is not update KB2570791" } #Собирается вся информация в общую переменную $FullInfo = $CompName + ";" + $User.UserName + ";" + $IP.IPAddress + ";" + $IsHostFix + ";" + $OS.Caption + $OS.OSArchitecture + " " + $OS.CSDVersion + ";" + $OS.Version + ";" + $TZ.Bias #На основе собранной информации распределяются машины по разным файлам #1. Машина доступна, но не обновлена #2. Машина доступна и обновлена успешно #3. Настройки часового пояса отличаются от искомых (+3 или +4) #Проверяется параметр BIAS (Смещение от абсолютного времени) if ($TZ.Bias -eq 180) { $FullInfo| Out-File -Append “D:\\powershell\\Log\\NotUpdated.txt” } elseif ($TZ.Bias -eq 240) { $FullInfo| Out-File -Append “D:\\powershell\\Log\\Updated.txt” } else { $FullInfo| Out-File -Append “D:\\powershell\\Log\\Other.txt” } #Возвращаем успех return "Success" } }

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

############################################################ ##### Начало скрипта ##### ############################################################ #Если необходимо останавливать скрипт при возникновении ошибок в процессе выполнения #(например при отладке), то следующую строку надо раскомментировать #$ErrorActionPreference = "Stop" # Обнуляем файлы, в которые записываем результаты и создаем шапку #Файл для машин, на которых часовой пояс не изменился ("Name;User;IP_Address;Update;OS;OS_Version;Bias")| Out-File “D:\\powershell\\Log\\NotUpdated.txt” #Файл для машин, на которых обновление прошло успешно ("Name;User;IP_Address;Update;OS;OS_Version;Bias")| Out-File “D:\\powershell\\Log\\Updated.txt” #Файл для машин, на которых часовой пояс отличается и от старого и от нового ("Name;User;IP_Address;Update;OS;OS_Version;Bias")| Out-File “D:\\powershell\\Log\\Other.txt” #Файл для машин, которые в настоящий момент недоступны ("Name;User;IP_Address;Update;OS;OS_Version;Bias")| Out-File “D:\\powershell\\Log\\NotAvailable.txt” # Загружаем исходный список машин $List= Import-Csv "D:\\powershell\\listcomp.csv" -delimiter ';' #Обнуляем счетчик машин $cnt=0 # Начинаем обработку каждой машины foreach ( $arr in $List) { #Увеличиваем счетчик и выводим имя машины $cnt=$cnt+1 Write-Host $cnt, $arr.name # Проверяем доступен ли компьютер $IsPing = IsReply($arr.name) #Если доступен, то собираем информацию, #Если не доступен, то записываем его в список недоступных машин if ($IsPing –eq "Success") { # Собираем информацию $Result = Get-Info($arr.name) #Если сбор информации неуспешен, то записываем его в список недоступных машин if ($Result –ne "Success") { $arr.name| Out-File -Append “D:\\powershell\\Log\\NotAvailable.txt” } } else { $arr.name| Out-File -Append “D:\\powershell\\Log\\NotAvailable.txt” } } ############################################################ ##### Конец скрипта ##### ############################################################

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

Поделиться ссылкой:

Понравилось это:

Нравится Загрузка...

Похожее

exchange2010.ru

PowerShell: Get-ADComputer – получение информации о компьютерах Active Directory

Продолжаем знакомиться с полезными командлетами PowerShell для работы с Active Directory. В прошлой статье мы поговорили о командлете Get-ADUser, позволяющем получать любую информацию об учетных записях пользователей AD. Сегодня речь пойдет о командлете Get-ADComputer и его использовании для получения различных данных об учётных записях компьютеров (серверах и рабочих станциях) в домене Active Directory.

  • Особенности синтаксиса командлета Get-ADComputer
  • Get-ADComputer: практические примеры использования

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

Прежде чем приступить к работе с командлетом Get-ADComputer, необходимо подключить модуль Active Directory Module for Windows PowerShell.

Import-Module activedirectory

Совет. В PowerShell 3.0 (представлен в Windows Server 2012) и выше этот модуль подключается по умолчанию при установке компонента Remote Server Administration Tools -> Role Administration Tools -> AD DS and AD LDS Tools -> Active Directory module для Windows PowerShell. Чтобы использовать командлет Get-ADComputer в клиенстких Windows 10,8.1 и Windows 7 нужно скачать и установить RSAT для вашей версии ОС и включить модуль AD-Powershell из панели управления или командой:Enable-WindowsOptionalFeature -Online -FeatureName RSATClient-Roles-AD-Powershell

Особенности синтаксиса командлета Get-ADComputer

Справка о параметрах командлета Get-ADComputer вызывается стандартно с помощью Get-Help:

Get-Help Get-ADComputer

Для получения информации из AD с помощью командлетов модуля AD for Powershell не обязательно иметь права администратора домена, достаточно чтобы учетная запись под которой запускается командлет входила в группу пользователей домена (Authenticated Users / Domain Users).

Чтобы получить информацию о конкретном компьютере в домене укажите его имя с параметром —Identity:

Get-ADComputer -Identity SRV-DB01

Нас интересует время последней регистрации компьютера в домене AD, но этой информация в выводе команды нет. Выведем все доступные свойства компьютера в Active Directory:

Get-ADComputer -Identity SRV-DB01 -Properties *

Как вы видите, время последнего входа данного компьютера в сеть указано в атрибуте LastLogonDate – 21.09.2015 0:20:17.

Уберем всю лишнюю информацию, оставив только значение полей Name и LastLogonDate.

Get-ADComputer -identity SRV-DB01 -Properties * | FT Name, LastLogonDate -Autosize

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

Get-ADComputer -Filter * -Properties * | FT Name, LastLogonDate -Autosize

Чтобы вывести данные о компьютерах в определенном контейнере домена (OU), воспользуйтесь параметром SearchBase:Get-ADComputer -SearchBase ‘OU=Moscow,DC=winitpro,DC=loc’ -Filter * -Properties * | FT Name, LastLogonDate -Autosize

Отсортируем результаты запроса по времени последнего логина в сеть (поле LastLogonDate) с помощью команды Sort:

Get-ADComputer -Filter * -Properties *  | Sort LastLogonDate | FT Name, LastLogonDate -Autosize

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

С помощью Get-Date получим в переменной значение текущей даты и вычтем из текущей даты 120 дней:

$date_with_offset= (Get-Date).AddDays(-120)

Полученную переменную с датой можно использовать в качестве фильтра запроса Get-ADComputer по полю LastLogonDate

Get-ADComputer  -Properties LastLogonDate -Filter {LastLogonDate -lt $date_with_offset } | Sort LastLogonDate | FT Name, LastLogonDate -Autosize

Таким образом, мы получили список неактивных компьютеров, не регистрировавшихся в сети более 120 дней. С помощью команды Disable-ADAccount отключим их.

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

Get-ADComputer -Properties LastLogonDate -Filter {LastLogonData -lt $date_with_offset } | Set-ADComputer -Enabled $false -whatif

Теперь можно заблокировать все полученные учетные записи компьютеров:

Get-ADComputer -Properties LastLogonDate -Filter {LastLogonData -lt $datecutoff} | Set-ADComputer -Enabled $false

Совет. Список заблокированных, отключенных и неактивных компьютеров и пользователей домена можно получить также с помощью отдельного командлета Search-ADAccount.

Get-ADComputer: практические примеры использования

Ниже представлены еще несколько полезных примеров команд с использованием командлета Get-ADComputer.

Получить количество компьютеров в Active Directory:

Get-ADComputer -Filter {SamAccountName -like "*"} | Measure-Object

Список компьютеров, чьи имена начинаются с BuhPC:

Get-ADComputer -Filter 'Name -like "BuhPC*"' -Properties IPv4Address | Format-table Name,DNSHostName,IPv4Address -A

Выбрать все рабочие станции с ОС Windows XP:

Get-ADComputer -Filter {OperatingSystem -like '*XP*'}

Выбрать только серверные системы:

Get-ADComputer -Filter { OperatingSystem -Like '*Windows Server*' } -Properties OperatingSystem | Select Name, OperatingSystem | Format-Table –AutoSize

Получить список серверов в домена с версией ОС и установленным Service Pack:Get-ADComputer -Filter {OperatingSystem -Like '*Windows Server*' } -Property * | Format-Table Name,OperatingSystem,OperatingSystemServicePack -Wrap -Auto

Чтобы удалить все аккаунты компьютеров в домене, не входившие в домене более 6 месяцев, можете воспользоваться командой:

get-adcomputer -properties lastLogonDate -filter * | where { $_.lastLogonDate -lt (get-date).addmonths(-6) } | Remove-ADComputer

Выбрать отключенные компьютеры в определенном OU:

Get-ADComputer -filter * -SearchBase «OU=Computers, dc=winitpro,dc=loc» | Where-Object {$_.enabled -eq $False}

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

Get-ADComputer -Filter { OperatingSystem -Like '*Windows Server*' } -Properties OperatingSystem | Select Name, OperatingSystem | Format-Table -AutoSize C:\Script\server_system.txt

Или CSV файл:

Get-ADComputer -Filter * -Property * | Select-Object Name,OperatingSystem,OperatingSystemServicePack | Export-CSV All-Windows.csv -NoTypeInformation -Encoding UTF8

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

$Computers = Get-ADComputer -Filter {OperatingSystem -Like '*Windows Server*'}Foreach ($Computer in $Computers){$Hostname = $Computer.Name$ComputerInfo = (Get-WmiObject -Computername $Hostname Win32_ComputerSystem)$Manufacturer = $Computer.Manufacturer$Model = $Computer.ModelWrite-Host "Name: $Hostname"Write-Host "Manufacturer: $Manufacturer"Write-Host "Model: $Model"Write-Host " "$Content = "$Hostname;$Manufacturer;$Model"Add-Content -Value $Content -Path "C:\PS\ServersInfo.txt"}

Либо можно использовать более короткий синтаксис цикла. Допустим нам нужно выполнить определенную команду на всех компьютерах в определенном OU (в этом примере мы хотим запустить на всех серверах команду обновления групповых политик):

get-adcomputer -SearchBase "OU=Servers,DC=winitpro,DC=loc" -Filter * | %{ Invoke-Command -Computer $_.Name -ScriptBlock {gpupdate /force} }

winitpro.ru

Получение системной информации с помощью PowerShell

Получение информации о системе с помощью PowerShell

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

Systeminfo

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

$systeminfo = systeminfo /FO csv | ConvertFrom-Csv

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

$systeminfo.’System Boot Time’

А так информацию об установленной на нем операционной системе:

$systeminfo | fl OS*

 

Для получения данных с удаленного компьютера у systeminfo имеется ключ /S, также при необходимости можно указать имя пользователя (/U) и пароль (/P). Для примера выведем данные о потреблении памяти на компьютере testdc2:

$systeminfo = systeminfo /FO csv /S testdc2 /U administrator /P ′p@$$w0rd′  | ConvertFrom-Csv$systeminfo | fl *memory

 

Примечание. Если пароль содержит служебные символы (например знак $), то его необходимо заключать в одинарные кавычки. При использовании двойных кавычек будет выдана ошибка.

WMI

Windows Instrumentation Instrumentation (WMI) позволяет узнать практически любую информацию о компьютере. Базовую информацию о системе можно получить с помощью WMI-класса Win32_OperatingSystem (CIM_OperatingSystem). Для примера уточним данные об операционной системе:

$systeminfo = Get-CimInstance -ClassName Win32_OperatingSystem$systeminfo | fl Caption, Version, BuildType, BuildNumber, InstallDate

 

Если требуется подробная информация об одном из компонентов системы, то можно использовать другие классы WMI. Перечисление и подробное описание классов WMI и CIM можно найти на MSDN, а мы для примера выведем свойства процессора с помощью класса Win32_Processor (CIM_Processor):

$cpuinfo = Get-CimInstance -ClassName CIM_Processor$cpuinfo | fl Name, Description, Version

 

Для получения данных с удаленных систем можно в команде указать имя компьютера. Если компьютеров несколько, то имена указываются через запятую. Например:

$systeminfo = Get-CimInstance -ClassName CIM_OperatingSystem -ComputerName testdc1, testdc2 $systeminfo | ft PSComputerName, Caption, MUILanguages -a

 

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

$session = New-CimSession -ComputerName testdc1,testdc2 -Credential $(Get-Credential)

А затем используем созданные сессии для получения системной информации:

$systeminfo = Get-CimInstance -ClassName CIM_OperatingSystem -CimSession $session $systeminfo | ft PSComputerName, Caption, MUILanguages -a

windowsnotes.ru

powershell - Переименуйте компьютер и присоединитесь к домену за один шаг с помощью PowerShell

Существует несколько причин, по которым вам необходимо перезагрузить компьютер после переименования компьютера или при подключении к домену (который в основном является той же операцией с проверкой AD). Один из них заключается в том, что на компьютерах, работающих на NT (я думаю, что это началось с Windows 2000), службы приложений и сети считывают имя компьютера при запуске. Это единственный раз, когда они читают имя компьютера, поэтому, если вы переименуете компьютер без перезагрузки, сетевые службы и приложения не будут реагировать на новое имя компьютера. Это особенно важно, когда вы сначала переименовываете компьютер, а затем пытаетесь присоединиться к домену, поскольку рукопожатие kerberos не может быть завершено без сетевого стека, отвечающего на правильное имя компьютера.

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

Вы можете использовать раздел реестра RunOnce (msdn.microsoft.com/en-us/library/aa376977%28v=vs .85%29.aspx) для автоматического запуска вашего домена script при перезагрузке, re все равно придется перезагружаться для обеих операций.

Если вы действительно хотите получить сложную задачу, вы можете добавить код в свой rename script, который установил бы раздел реестра RunOnce для запуска соединения домена script при перезагрузке. Имейте в виду, что если вы сделаете это, то script, который будет записывать в улей HKLM, должен запускаться как администратор (особенно важно, если вы включили UAC).

Если вы хотите сделать это, вы должны использовать что-то вроде этого в конце своей функции Rename-Computer:

Set-Location -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce' Set-ItemProperty -Path . -Name joinDomain -Value "C:\scripts\joinDomain.ps1" Restart-Computer

Это создаст подраздел в разделе реестра RunOnce (при условии, что вы используете Vista/7/2008) с именем "joinDomain" со значением "C:\scripts\joinDomain.ps1"

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

Set-ItemProperty -Path . -Name joinDomain -Value 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe "C:\scripts\joinDomain.ps1"'

Сообщите мне, есть ли у вас проблемы.

qaru.site

Заполняем описание (description) компьютера в AD именами пользователей

Некоторое время назад я писАл о расширении оболочки ADUC для получении имени зарегистрированного на компьютере пользователя. На этот раз публикую скрипт на PowerShell 2.0 для задания описаний компьютеров в AD на основании имени текущегозарегистрированного на нём пользователя и его номера телефона. Для снижения таймаута WMI взята и немного доработана конструкция Test-Host, благодаря чему достигается достаточно высокая скорость работы.

Для использования измените выделенное красным (OU и домен) для своего окружения.

Import-Module ActiveDirectory foreach ($comp in (Get-ADComputer -filter * -SearchBase "CN=Computers,DC=domain,DC=corp" | foreach {$_.name} )) { $ping = new-object System.Net.NetworkInformation.Ping trap {Write-Verbose "Ошибка пинга"; $False; continue} if ($ping.send($comp,50).Status -eq "Success" ) { $useroncomp = (Get-WmiObject -Class Win32_ComputerSystem -ComputerName $comp).username $lastuser = Get-ADUser ($useroncomp.split("\")[1]) -properties displayname, telephonenumber Set-ADComputer $comp -Description (($lastuser.DisplayName) + " (" + ($lastuser.telephonenumber) + ")") } else {Write-Host $comp "- недоступен"} }

Import-Module ActiveDirectory

 

foreach ($comp in (Get-ADComputer -filter * -SearchBase "CN=Computers,DC=domain,DC=corp" | foreach {$_.name} ))

    {   $ping = new-object System.Net.NetworkInformation.Ping

        trap {Write-Verbose "Ошибка пинга"; $False; continue}

        if ($ping.send($comp,50).Status -eq "Success" )

        {

        $useroncomp = (Get-WmiObject -Class Win32_ComputerSystem -ComputerName $comp).username

        $lastuser = Get-ADUser ($useroncomp.split("\")[1]) -properties displayname, telephonenumber

        Set-ADComputer $comp -Description (($lastuser.DisplayName) + " (" + ($lastuser.telephonenumber) + ")")

        }

        else {Write-Host $comp "- недоступен"}

    }

Внимание! Скрипт работает только на Windows Server 2008 R2 и Windows 7, то есть там, где есть модуль Active Directory для PowerShell

Поделиться ссылкой:

Похожее

mcp.su

Windows PowerShell: The Power of Filtering

  • 08/19/2016
  • Время чтения: 7 мин

В этой статье

Windows PowerShellВозможности фильтрации

Дон Джонс (Don Jones)

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

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

Чаще всего я пишу в Windows PowerShell™ сценарии, работающие для множества удаленных компьютеров, как правило, через Windows® Management Instrumentation (WMI). Как и в любой задаче, связанной с удаленными компьютерами, всегда существует возможность того, что один или более компьютеров не будут доступны при запуске сценария. Следовательно, нужно, чтобы мои сценарии могли с этим работать.

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

Парадигма Windows PowerShell

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

Тем не менее, Windows PowerShell лучше подходит для групповых операций благодаря тому, что основана на объектах, а также возможности работы непосредственно с группами или коллекциями объектов. Парадигма в Windows PowerShell не предназначена для работы с единичными объектами или частями данных, она работает, скорее, с группами в целом, проходя группу бит за битом до тех пор, пока не выполнена поставленная задача.. Например, вместо получения за один раз имени одного компьютера из моего списка я сразу прочту всю коллекцию имен, а вместо проверки каждого из компьютеров в цикле я напишу одну процедуру, которая принимает коллекцию имен, проверяет их, а затем выводит имена тех компьютеров, к которым можно подключиться. Следующим шагом будет создать подключение WMI к остальным компьютерам — тем, которые можно достать с помощью команды ping.

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

Get-Service | Where-Object { $_.Status –eq "Running" }

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

Рис. 1** Получение списка компьютеров, отвечающих на команду ping **(Щелкните изображение, чтобы увеличить его)

Функции фильтрации

Я не хочу писать для этого собственный командлет, хотя мог бы. Для написания командлета требуется Visual Basic® или C# и достаточный опыт разработки для Microsoft® .NET Framework. И, что более важно, требуется больше труда, чем я собираюсь вложить в эту задачу. К счастью, Windows PowerShell дает мне возможность написания специального вида функции, называемой фильтром, которая замечательно действует в рамках конвейера. Основной набросок функции фильтрации выглядит примерно так:

function <name> { BEGIN { #<code> } PROCESS { #<code> } END { #<code> } }

Как вы видите, эта функция содержит три независимых блока сценариев, которые называются BEGIN, PROCESS и END. Функция фильтрации – это, таким образом, функция, предназначенная для фильтрации объектов в конвейере – можно иметь любую комбинацию из этих трех блоков сценариев в зависимости от того, что необходимо сделать. Они работают следующим образом:

  • Блок BEGIN выполняется при первом вызове функции. При необходимости его можно использовать для настройки.
  • Блок PROCESS выполняется единожды для каждого из объектов контейнера, передаваемого в функцию. Переменная $_ представляет текущий входной объект конвейера. Блок PROCESS необходим в функции фильтрации.
  • Блок END выполняется после обработки всех объектов контейнера. Его можно использовать для выполнения любой работы по финализации, если это необходимо.

В моем примере мне нужно создать функцию фильтрации, которая примет коллекцию имен как объекты фильтрации, а затем попытается выдать команду ping для каждого из них. Каждое из имен, успешно ответивших на команду ping, будет выведено на конвейер, а системы, которые не ответили на ping, будут опущены. Поскольку функция ping не требует каких либо специальных настроек или финализации, я просто использую блок сценариев PROCESS. Код на рис. 2 содержит полный сценарий.

Figure 2 Ping-Address и Restart-Computer.

1 function Ping-Address { 2 PROCESS { 3 $ping = $false 4 $results = Get-WmiObject -query ` 5 "SELECT * FROM Win32_PingStatus WHERE Address = '$_'" 6 foreach ($result in $results) { 7 if ($results.StatusCode -eq 0) { 8 $ping = $true 9 } 10 } 11 if ($ping -eq $true) { 12 Write-Output $_ 13 } 14 } 15 } 16 17 function Restart-Computer { 18 PROCESS { 19 $computer = Get-WmiObject Win32_OperatingSystem -computer $_ 20 $computer.Reboot() 21 } 22 } 23 24 Get-Content c:\computers.txt | Ping-Address | Restart-Computer

Обратите внимание на то, что я определил две функции: Ping-Address и Restart-Computer. В Windows PowerShell функции должны быть определены перед вызовом. В результате первой исполняемой строкой моего сценария является строка 24, которая использует командлет Get-Content для получения списка имен компьютеров из файла (один компьютер на строку). Этот список — в техническом плане коллекция объектов-строк — передается по конвейеру в функцию Ping-Address, которая отфильтровывает компьютеры, которые не отвечвают на ping. Результаты передаются по конвейеру в Restart-Computer, который использует WMI для удаленного перезапуска тех компьютеров, которые не отвечают на ping.

Функция Ping-Address реализует блок сценария PROCESS, это значит, что функция ожидает ввод коллекции объектов. Блок сценария PROCESS автоматически работает со введенными данными — мне не пришлось определять какие-либо входные аргументы для них. Я начинаю процесс в строке 3, присвоив переменной $ping значение $false, которое является встроенной переменной Windows PowerShell, представляющей логическое значение «ложь».

Затем я использую локальный класс WMI Win32_PingStatus для выдачи команды ping для конкретного компьютера. Обратите внимание в строке 5 на то, что переменная $_, представляющая текущий объект конвейера, входит в строку запроса WMI. Если строка содержится в двойных кавычках, Windows PowerShell всегда будет выполнять попытку заменить переменные наподобие $_ их содержимым, поэтому вам не придется возиться с построением строк. Я использую эту возможность в строке 5.

Строка 6 – это цикл, проверяющий результаты моей проверки. Если любой из этих результатов возвращается успешно (то есть StatusCode равен нулю), я устанавливаю значение $ping равным $true, что означает успешность. В строке 11 я проверяю, установлено ли для $ping значение $true. Если да, я вывожу исходный входной объект в поток выходных данных по умолчанию. Windows PowerShell автоматически управляет потоком выходных данных. Если эта функция находится в конце конвейера, то потом выходных данных преобразуется в текстовое представление. Если в конвейере больше команд, чем объектов выходного потока данных, то объекты-строки, содержащие имена компьютеров, передаются в следующую команду конвейера.

Функция Restart-Computer несколько проще, но она также использует блок PROCESS, поэтому тоже может без проблем входить в конвейер. В строке 19 функция подключается к указанному компьютеру и получает его класс WMI Win32_OperatingSystem. Строка 20 выполняет метод Reboot этого класса для перезагрузки удаленного компьютера.

И снова строка 24 – это место, где все в действительности выполняется. При запуске этого сценария, разумеется следует быть очень осторожным — он предназначен для перезагрузки любого компьютера, указанного в файле c:\computers.txt, что может иметь разрушительные последствия, если вы не обращаете внимания на имена в этом текстовом файле!

Следующие этапы

Этот сценарий не полностью неуязвим. Следует упомянуть также о возможности возникновения ошибки WMI, не связанной с основной связью, например блокировки брандмауэром необходимых портов на удаленном компьютере или ошибки безопасности WMI. С этими проблемами можно справиться с помощью обработчика ловушек – похоже, это идеальная тема для следующей статьи.

Кроме того, этот сценарий выполняет очень серьезное действие — перезапуск удаленного компьютера. Любой сценарий, выполняющие такие потенциально опасные действия, должен иметь два распространенных параметра Windows PowerShell: Confirm и WhatIf. Чтобы объяснить, как это сделать, требуется больше места, чем у меня есть в этой статье, и это станет еще одной отличной темой для будущей публикации. А до тех пор почитайте блог отдела Windows PowerShell; архитектор Джеффри Сновер (Jeffrey Snover) рассказывает об этом.

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

Дон Джонс (Don Jones) — ведущий специалист по написанию сценариев в компании SAPIEN Technologies, соавтор книги Windows PowerShell: TFM (SAPIEN Press, 2007). С ним можно связаться по адресу www.ScriptingAnswers.com.

© 2008 Корпорация Майкрософт и компания CMP Media, LLC. Все права защищены; полное или частичное воспроизведение без разрешения запрещено.

msdn.microsoft.com

windows - Как получить текущее имя пользователя в Windows Powershell?

Я подумал, что было бы полезно обобщить и сравнить приведенные ответы.

Если вы хотите получить доступ к переменной среды :

(более простой/короткий/незабываемый вариант)

  • [Environment]::UserName - @ThomasBratt
  • $env:username - @Eoin
  • whoami - @galaktor

Если вы хотите получить доступ к токену доступа :

(более надежный вариант)

  • [System.Security.Principal.WindowsIdentity]::GetCurrent().Name - @MarkSeemann

Если вы хотите, чтобы имя зарегистрированного пользователя

(а не имя пользователя, запускающего экземпляр PowerShell)

Сравнение

@Kevin Panko комментирует @Mark Seemann ответ на вопрос о выборе одной из категорий над другой:

[Подход к токенам доступа к окну] - самый безопасный ответ, потому что пользователь может использовать переменную $env: USERNAME, но это не обманет, сделав это.

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

Мне пришлось использовать подход к токенам доступа к окну @Mark Seemann в PowerShell script, который я запускал из приложения С# с олицетворением. Приложение С# запускается с моей учетной записью пользователя и запускает powershell script в качестве учетной записи службы. Из-за ограничения того, как я запускаю PowerShell script из С#, экземпляр PowerShell использует переменные среды моей учетной записи пользователя, даже если он запущен как пользователь учетной записи службы. В этой настройке параметры переменной среды возвращают мое имя учетной записи, а параметр токена доступа к окну возвращает имя учетной записи службы (именно это я и хотел), а параметр входа в систему возвращает мое имя учетной записи.

Тестирование

Кроме того, если вы хотите сравнить параметры самостоятельно, вот script, который вы можете использовать для запуска script в качестве другого пользователя. Вам нужно использовать командлет Get-Credential для получения объекта учетных данных, а затем запустить этот script с помощью script для запуска в качестве другого пользователя в качестве аргумента 1, а объект учетных данных - как аргумент 2.

Применение:

$cred = Get-Credential UserTo.RunAs Run-AsUser.ps1 "whoami; pause" $cred Run-AsUser.ps1 "[System.Security.Principal.WindowsIdentity]::GetCurrent().Name; pause" $cred

Содержание Run-AsUser.ps1 script:

param( [Parameter(Mandatory=$true)] [string]$script, [Parameter(Mandatory=$true)] [System.Management.Automation.PsCredential]$cred ) Start-Process -Credential $cred -FilePath 'powershell.exe' -ArgumentList 'noprofile','-Command',"$script"

qaru.site