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).
Далее этот файл обрабатывается следующим образом:
- Проверяется, пингуется и ли машина
- Если машина пингуется, то проверяется:
- Текущая настройка TimeZone
- IP адрес
- Версию ОС
- Текущий пользователь
- Установлено ли обновление KB2570791
- На основании данных п. 2 принимается решение о статусе обновления машины.
На выходе, получим следующую информацию:
- Список машин, которые не пингуются
- Список не обновленных машин
- Список обновленных машин
- Список машин, с настройками других временных зон
Чтобы реализовать выше описанное, потребуется:
- функция проверки отвечает ли хост на ping
- функция сбора информации о хосте
- Чтобы проверить пингуется ли удаленная машина, используется следующий набор команд:
Где $CompName – это имя машины
Полностью функция будет выглядеть следующим образом:
############################################################ ##### Функция проверки доступности компьютера ##### ############################################################ Function IsReply($CompName) { $ping = New-Object System.Net.NetworkInformation.Ping try { $Reply = $ping.Send($CompName) } catch { Write-host "Для машины " $CompName "не удалось выполнить ping" } return $Reply.status }- Чтобы собрать необходимую информацию для данной задачи о удаленной машине, понадобится несколько командлетов.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" } }Поделиться ссылкой:
Понравилось это:
Нравится Загрузка...
Похожее
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