В статье рассмотрим несколько способов инвентаризации версии и билдов Windows (особенно актуально это для Windows 10) в домене Active Directory. Если у вас средств автоматизации сбора конфигураций компьютеров, например SCCM, GLPI c FusionInventory, или хотя бы сервер обновлений WSUS (он также позволяет показать версию Windows на обнаруженных компьютерах), вы можете использовать PowerShell скрипт для получения билдов Windows на компьютерах.
На отдельно-стоящем компьютере Windows можно получить номер билда из реестра или из SystemInfo:
Get-ItemProperty 'HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion' | Select-Object ProductName, ReleaseID, CurrentBuild
Get-ComputerInfo | select WindowsProductName, WindowsVersion, OsHardwareAbstractionLayer
Для получения списка активных компьютеров в домене Active Directory и версий (билдов) Windows на них можно использовать командлет Get-ADComputers.
Убедитесь, что на вашем компьютере установлен модуль Active Directory PowerShell и выполните команду:
Get-ADComputer -Filter {(Enabled -eq $True)} -Property * | Select-Object Name,OperatingSystem,OperatingSystemVersion
Чтобы преобразовать номер билда Windows 10 и 11 в более привычный формат (21H1, 21H2 и т.д.), нужно использовать дополнительную функцию.
function ConvertWindowsBuild{
[CmdletBinding()]
param(
[string] $OperatingSystem,
[string] $OperatingSystemVersion
)
if (($OperatingSystem -like '*Windows 10*') –or ($OperatingSystem -like 'Windows 11*')) {
$WinBuilds= @{
'10.0 (22000)' = "Windows 11 21H2"
'10.0 (19044)' = "Windows 10 21H2"
'10.0 (19043)' = "Windows 10 21H1"
'10.0 (19042)' = "Windows 10 20H2"
'10.0 (18362)' = "Windows 10 1903"
'10.0 (17763)' = "Windows 10 1809"
'10.0 (17134)' = "Windows 10 1803"
'10.0 (16299)' = "Windows 10 1709"
'10.0 (15063)' = "Windows 10 1703"
'10.0 (14393)' = "Windows 10 1607"
'10.0 (10586)' = "Windows 10 1511"
'10.0 (10240)' = "Windows 10 1507"
'10.0 (18898)' = 'Windows 10 Insider Preview'
}
$WinBuild= $WinBuilds[$OperatingSystemVersion]
}
else {$WinBuild = $OperatingSystem}
if ($WinBuild) {
$WinBuild
} else {
'Unknown'
}
}
Теперь, чтобы получить список версий Windows с названиями билдов, IP адресами, и датой последнего входа (регистрации) компьютера в домене, выполните следующий PowerShell скрипт:
$Comps= Get-ADComputer -Filter {(Enabled -eq $True)} -properties *
$CompList = foreach ($Comp in $Comps) {
[PSCustomObject] @{
Name = $Comp.Name
IPv4Address = $Comp.IPv4Address
OperatingSystem = $Comp.OperatingSystem
Build = ConvertWindowsBuild -OperatingSystem $Comp.OperatingSystem -OperatingSystemVersion $Comp.OperatingSystemVersion
LastLogonDate = $Comp.LastLogonDate
}
}
$CompList | Out-GridView
Результат предоставлен в виде таблицы Out-Gridview либо экспортировать в CSV (
Export-Csv -Path .\win_builds_report.csv -NoTypeInformation
).
Чтобы вывести суммарную статистику по количеству компьютеров с разными версиями Windows в домене:
$CompList | Group-Object -Property Build | Format-Table -Property Name, Count
Также можно удаленно опрашивать компьютеры и получить версию Windows на них через PowerShell Remoting. Этот метод намного более медленный, но позволить получить версию Windows на компьютерах, которые находятся в рабочей группе (как через PSRemoting удаленно подключиться к компьютеру в рабочей группе). Для получения информации с удаленных компьютеров можно использовать командлет Invoke-Command:
Invoke-Command -ScriptBlock {Get-ItemProperty 'HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion' | Select-Object ProductName, ReleaseID, CurrentBuild} -ComputerName wsk-w10BO1| Select-Object PSComputerName,ProductName, ReleaseID, CurrentBuild
Можно получить версию Windows на нескольких компьютеров по списку из txt файла:
Invoke-Command –ComputerName (Get-Content c:\ps\comps.txt) -ScriptBlock {Get-ItemProperty 'HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion' | Select-Object ProductName, ReleaseID, CurrentBuild}|Select-Object PSComputerName,ProductName, ReleaseID, CurrentBuild
С помощью рассмотренных PowerShell скриптов вы сможете определить версии и билды Windows на компьютерах домена, найти компьютеры с устаревшими билдами Windows 10 и обновить их (пример обновления билда Windows 10 из командной строки).
Unfortunately the Get-ADComputer version doesn’t give OPs desired results as you will get 10.0 (18363) for example.
1507 build 10.0.10240
1511 build 10.0.10586
1607 build 10.0.14393
1703 build 10.0.15063
1709 build 10.0.16299
1803 build 10.0.17134
1809 build 10.0.17763
1903 build 10.0.18362
1909 build 10.0.18363
That being said, this would be the fastest way to gather the info. Just make a conversion table with a switch command (For some reason it’s moving my comments up a line in the code below despite looking fine in the editor)
Powershell
$List = Get-ADComputer -SearchBase "Ou=xxx,ou=xxx,dc=domnain,dc=com" -filter {enabled -eq $true} -properties OperatingSystemVersion foreach ($System in $List} { $Result = switch ($System.OperatingSystemVersion) { "10.0 (10240)" {1507} "10.0 {10586)" {1511}# ... and so on down the list }#do stuff here with that result you just got}
1 found this helpful
thumb_up
thumb_down
Время на прочтение
5 мин
Количество просмотров 17K
Как же определить версию Windows, работающую в корпоративном окружении?
Вопрос кажется простым, правда?
Microsoft позволяет определить номер версии Windows различными способами:
- Существуют значения в реестре, которым отчаянно не хватает документации.
- Есть множество командлетов PowerShell, вызовов Windows API и т. п.
- Также есть варианты для конечного пользователя, например, команда
winver
, которая вызывает всплывающее окно с версией Windows. - И много других способов…
Разобраться во всём этом вам поможет наш пост.
Существует множество инструментов, позволяющих определить, какая версия Windows запущена у ваших клиентов, например, SCCM и PDQ. В этом посте мы рассмотрим встроенные способы определения версии Windows.
▍ Реестр
Для определения запущенной в системе версии Windows можно использовать следующие значения реестра:
Примечание: перечисленные в таблице значения официально не задокументированы Microsoft (см. ниже).
Предупреждение
Microsoft не сообщала об изменениях в этих значениях реестра, не документировала их официальную поддержку и не гарантировала, что в будущем не появится критических изменений. Из-за этого описанными выше ключами реестра пользоваться бывает иногда неудобно, учитывая непостоянство изменений этих ключей, вносимых Microsoft в прошлом. Примеры:
- ReleaseID не рекомендуется к использованию, начиная с версии 21H1. ReleaseID для 21H1 остаётся равным 2009.
- Server 2012R2 не имеет ReleaseID и DisplayVersion (они пока не были добавлены в Windows)
- Server 2016 имеет ReleaseID (1607), но не имеет DisplayVersion
- Server 2019 имеет ReleaseID (1809), но не имеет DisplayVersion
▍ PowerShell
Ниже приведено несколько примеров того, как можно использовать PowerShell, чтобы определить версию Windows, которая работает в системе:
# При помощи класса System.Environment
[System.Environment]::OSVersion
# При помощи класса CIM Win32_OperatingSystem
Get-CimInstance Win32_OperatingSystem
# При помощи исполняемого файла systeminfo
systeminfo.exe /fo csv | ConvertFrom-Csv
# При помощи командлета Get-ComputerInfo
# ПРИМЕЧАНИЕ: начиная с 21H1 OsHardwareAbstractionLayer не рекомендуется к использованию
Get-ComputerInfo | Select WindowsProductName, WindowsVersion, OsHardwareAbstractionLayer
▍ Windows API Call
Единственный поддерживаемый (задокументированный) систематический способ определения версии Windows — при помощи вызова Windows API класса AnalyticsInfo. Это можно сделать через PowerShell:
<#
Класс AnalyticsInfo - задокументированный способ отслеживания версии ОС. Он возвращает
строковое значение. Формат этой строки не задокументирован, и нельзя полагаться
на определённое значение. Эти значения можно использовать только чтобы отличать
одну версию ОС от другой.
https://docs.microsoft.com/uwp/api
/windows.system.profile.analyticsversioninfo.devicefamilyversion
Этот API недоступен на Server Core
#>
$AnalyticsInfo = [Windows.System.Profile.AnalyticsInfo,Windows.System.Profile,ContentType=WindowsRuntime]
$VersionInfo = $AnalyticsInfo.GetMember( 'get_VersionInfo' )
$AnalyticsVersionInfo = $VersionInfo.Invoke( $Null, $Null )
# На моей тестовой машине этот код возвращает `2814751015109593`
$AnalyticsVersionInfo.DeviceFamilyVersion
<#
Строго говоря, строку *можно* парсить, если вам любопытно, что в ней,
хотя этого делать *нельзя*
https://stackoverflow.com/questions/31783604/windows-10-get-devicefamilyversion
#>
$v = [System.Int64]::Parse( $AnalyticsVersionInfo.DeviceFamilyVersion )
$v1 = ( $v -band 0xFFFF000000000000l ) -shr 48
$v2 = ( $v -band 0x0000FFFF00000000l ) -shr 32
$v3 = ( $v -band 0x00000000FFFF0000l ) -shr 16
$v4 = $v -band 0x000000000000FFFFl
# На моей тестовой машине этот код возвращает `10.0.19043.985`
[System.Version]::Parse( "$v1.$v2.$v3.$v4" )
<#
Не опубликовано *никакого* способа декодирования, позволяющего преобразовать
какое-то из приведённых выше значений в удобную для отображения версию,
например `21H1`
Показанная ниже альтернатива доступна только в последних версиях ОС,
начиная с Azure Stack HCI, версии 20H2
#>
Get-ComputerInfo -Property 'osDisplayVersion'
▍ Варианты для конечного пользователя
В документации Microsoft перечислено несколько команд, которые конечные пользователи могут применять для определения запущенной версии Windows. Например, чтобы выяснить версию Windows, можно использовать команду winver
или меню Параметров Windows. Эти способы предназначаются больше для конечных пользователей, чем для масштабного определения версии системы. Ниже показаны примеры:
▍ Почему это важно
После определения запущенной в системе версии Windows можно использовать эту информацию выполнения детерминированных действий: обновлений Windows, установки патчей и т. п. Например:
Можно запросить значение реестра DisplayVersion
(см. раздел «Реестр» выше), чтобы определить запущенную версию Windows. Затем можно задать перечисленные ниже значения реестра, чтобы сообщить Windows, какая версия должна быть запущена в системе. При помощи трёх ключей реестра вы полностью контролируете то, до какой версии Windows ваши системы будут пытаться обновиться!
Эти значения реестра можно задавать или напрямую, или через групповую политику.
▍ Куда двигаться дальше
Хотя вам необязательно управлять версиями Windows, запущенными на компьютерах компании, ей было бы ценно знать, какие это версии Windows. По крайней мере, потому, что Microsoft регулярно прекращает поддержку разных версий Windows.
Стоит также заметить, что показанные выше примеры — это неполный список способов определения версии Windows, однако он полезен для людей, управляющих окружением Windows. Эти способы оказались полезными для меня при устранении проблем, задании политик и т. п. Надеюсь, вам они тоже пригодятся.
Кроме того, ситуация с управлением версиями Windows постоянно меняется, поэтому я напишу ещё один пост, когда Microsoft перестанет рекомендовать перечисленные здесь способы.
Дополнительные ссылки
- Microsoft nixes update deferral settings, but gives us a TargetReleaseVersionInfo
- Windows 10 Version History
- Windows Server Versions.
Всем привет.
В связи с модой на обновления не только ОС, но и самих ядер Windows понадобилась выборка реальной ситуации по всем рабочим станциям в домене. Тут имеет смысл делать выборку значения атрибута OperatingSystemVersion. Это номер сборки ОС. Ему в соответствие надо поставить номер версии ОС, так как это делает команда winver.
Поэтому возможные пары значений сборка+версия предварительно заносим в отдельный файлик Cores.csv, и далее пишем скрипт запроса в Powershell:
$cores = Import-CSV -Encoding UTF8 -path «d:\ps\Cores.csv» -Delimiter «;»
#Type of output file: CSV or TXT
$TypeOfFile = ‘txt’
foreach($core in $cores){
$core.name
$corename = ‘*(‘ + $core.Name + ‘)’
if ($typeoffile -eq ‘csv’){
$filename = ‘d:\’+ $core.CoreV +’.csv’
}
else { $filename = ‘d:\Cores.txt’
«Version of core: «+$core.coreV | Out-File $filename -Append -Force -Encoding UTF8
}
$str1 = Get-ADComputer -filter {(OperatingSystemVersion -like $corename) -and (Enabled -eq ‘True’) -and (OperatingSystem -notlike ‘*Server*’)} -properties CanonicalName,Description | Select Name,CanonicalName,Description
if ($str1) {$str1 | Out-File $filename -Append -Force -Encoding UTF8} else {«No hosts.» | Out-File $filename -Append -Force -Encoding UTF8}
Где файл Cores.csv имеет следующее содержание:
Name;CoreV;
19043;21H1;
19042;20H2;
19041;2004;
18363;1909;
18362;1903;
17763;1809;
17134;1803;
16299;1709;
15063;1703;
14393;1607;
10568;1511
Успехов.
you can query Active Directory:
#Get OS info from AD
$data = get-adcomputer -ldapfilter "(samaccountname=*)" -property operatingSystemVersion
#Export data
$osInfo | select-object -Property samaccountname,operatingSystemVersion | export-csv C:\tmp\osInfo.csv -NoClobber -NoTypeInformation -Delimiter ";"
If you need more infos CIM/WMI is your friend, e.g.:
#get all computers that have logged on to domain within the last 50 days, and ping machines to ensure they are available
$lastLogon = (Get-Date).AddDays(-50).ToFileTime()
$computers = Get-ADComputer -LDAPFilter (lastlogontimestamp<=$lastLogon) -Properties dnshostname
$computers = $computers | ?{Test-connection $_.dnshostname -Quiet}
#get os info from machines
$osInfo = get-cimInstance -query "Select version,buildnumber from win32_operatingsystem" -ComputerName $computers
#export data
$osInfo | select-object -Property psComputerName,version,buildnumber | export-csv C:\tmp\osInfo.csv -NoClobber -NoTypeInformation -Delimiter ";"
If WinRM is not configured on the target machines get-cimInstance won’t work, you may then try the good old wmi:
$osInfo = Get-WmiObject -query "Select version,buildnumber from win32_operatingsystem" -ComputerName $computers