#powershell
#powershell
Вопрос:
Я пытался получить сведения о конфигурации IP для моего физического сетевого адаптера, исключая все виртуальные сетевые адаптеры. Мой сценарий выглядит следующим образом:
$NetAdaptIndex = Get-NetAdapter -Physical | Select -Property InterfaceIndex -ExpandProperty InterfaceIndex
## Get Ip address, Gateway and DNS details as per configuration
$IPAddressConfig = foreach ($II in $NetAdaptIndex) {
Write-Host $II -ForegroundColor Yellow
Get-NetIPConfiguration |
Where-Object { $_.InterfaceIndex -eq $II} |
Select-Object InterfaceAlias, InterfaceDescription, InterfaceIndex, Ipv4Address, IPv4DefaultGateway, DNSServer
}
Когда я вызываю переменную, я получаю следующие результаты, в которых IPv4address, IPv4DefaultGateway и DNSServer не возвращаются в строковом формате.
PS C:WINDOWSsystem32> $IPAddressConfig
InterfaceAlias : WiFi 2
InterfaceDescription : D-Link DWA-171 Wireless AC Dual Band Adapter
InterfaceIndex : 46
IPv4Address : {192.168.0.103}
IPv4DefaultGateway : {MSFT_NetRoute (InstanceID = ":8:8:8:9:55?@55;C?8;@B8:8;55;")}
DNSServer : {MSFT_DNSClientServerAddress (Name = "46", CreationClassName = "", SystemCreationClassName = "", SystemName = "23"), MSFT_DNSClientServerAddress (Name = "46", CreationClassName = "", SystemCreationClassName = "", SystemName = "2")}
InterfaceAlias : Ethernet
InterfaceDescription : Broadcom NetLink (TM) Gigabit Ethernet
InterfaceIndex : 10
IPv4Address : {169.254.149.208}
IPv4DefaultGateway :
DNSServer : {MSFT_DNSClientServerAddress (Name = "10", CreationClassName = "", SystemCreationClassName = "", SystemName = "23"), MSFT_DNSClientServerAddress (Name = "10", CreationClassName = "", SystemCreationClassName = "", SystemName = "2")}
Но если бы я вручную удалил код Select-Object, он возвращает результаты в правильном формате.
Get-NetIPConfiguration |
Where-Object { $_.InterfaceIndex -eq 46}
Обратите внимание, как IPv4address, IPv4DefaultGateway и DNSServer вернули правильно отформатированный результат.
InterfaceAlias : WiFi 2
InterfaceIndex : 46
InterfaceDescription : D-Link DWA-171 Wireless AC Dual Band Adapter
NetProfile.Name : <removed>
IPv6Address : <removed>
IPv4Address : 192.168.0.103
IPv6DefaultGateway : <removed>
IPv4DefaultGateway : 192.168.0.1
DNSServer : 2001:f40:0:3::12:68
2001:4860:4860::8888
1.1.1.1
8.8.8.8
Мой вопрос в том, почему это происходит? И есть ли какой-либо метод, который я могу использовать для преобразования их в правильный формат? Последний формат — тот, который я хочу.
Комментарии:
1. Select-object изменяет тип с netipconfiguration на pscustomobject, но нет такого типа, чтобы привести его обратно?
2. @js2010 Ну, этот быстрый и грязный взлом не сработал:
(Get-NetIPConfiguration | Select-Object ComputerName, DNSServer) | %{$_.PSTypeNames.Insert(0, 'NetIPConfiguration') ; $_}
3. @beatcracker или это
Get-NetIPConfiguration | % { [pscustomobject]@{ipv4address = $_.ipv4address;dnsserver=$_.dnsserver;ipv4defaultgateway=$_.ipv4defaultgateway;pstypename='netipconfiguration'}}
4. Я добавил псевдоответ ниже, чтобы объяснить, какие дальнейшие шаги я предпринял для достижения окончательного решения. ответ @beatcracker является правильным ответом.
Ответ №1:
Все в PowerShell является объектом. Объекты могут быть довольно сложными с несколькими вложенными свойствами.
PS > (Get-NetIPConfiguration | Select-Object DNSServer)[0]
DNSServer
---------
{MSFT_DNSClientServerAddress (Name = "11", CreationClassName = "", SystemCreationClassName = "", SystemName = "23"), MSFT_DNSClientServerAddress (Name = "11", CreationClassName = "", Syste...
PS > (Get-NetIPConfiguration | Select-Object -ExpandProperty DNSServer)[0]
InterfaceAlias Interface Address ServerAddresses
Index Family
-------------- --------- ------- ---------------
LAN 11 IPv6 {}
Чтобы упростить вашу жизнь, PowerShell форматирует объекты, когда они отображаются на экране. Правила форматирования хранятся в xml
файлах: Обзор файлов форматирования. Для NetTCPIP
модуля файл будет C:WindowsSystem32WindowsPowerShellv1.0ModulesNetTCPIPTcpip.Format.ps1xml
. Вот DNSServer
код форматирования элемента:
<ListItem>
<Label>DNSServer</Label>
<ItemSelectionCondition>
<ScriptBlock>
($_.DNSServer.Count -ne 0) -and
(($_.NetIPv4Interface.ConnectionState -eq "Connected") -or
($_.NetIPv6Interface.ConnectionState -eq "Connected"))
</ScriptBlock>
</ItemSelectionCondition>
<ScriptBlock>
$output = "";
foreach($Server in $_.DNSServer) {
foreach($Address in $Server.ServerAddresses) {
$output = $Address "`n";
}
};
$output.Trim("`n");
</ScriptBlock>
</ListItem>
Применяемое форматирование контролируется PSTypeNames
свойством, которое существует для каждого объекта:
PS > (Get-NetIPConfiguration)[0].PSTypeNames
NetIPConfiguration
System.Object
При использовании Select-Object
это свойство изменяется, поэтому результирующий объект теряет свое форматирование:
PS > (Get-NetIPConfiguration | Select-Object DNSServer)[0].PSTypeNames
Selected.NetIPConfiguration
System.Management.Automation.PSCustomObject
System.Object
Увы, простая установка его обратно не сработает (у объекта нет правильной структуры для этого), но вы можете эмулировать его, используя вычисляемое свойство:
Get-NetIPConfiguration | Select-Object InterfaceAlias, InterfaceDescription, InterfaceIndex, Ipv4Address, IPv4DefaultGateway, @{ n='DNSServer' ; e={$_.DNSServer.ServerAddresses -join "`n"}}
Это приведет к сжатию DNSServer
в строку, поэтому вы не сможете использовать его должным образом позже. Возможно, просто вывод ServerAddresses
коллекции был бы удобнее, и она выглядела бы так же:
Get-NetIPConfiguration | Select-Object InterfaceAlias, InterfaceDescription, InterfaceIndex, Ipv4Address, IPv4DefaultGateway, @{ n='DNSServer' ; e={@($_.DNSServer.ServerAddresses)}}
Комментарии:
1. Спасибо за дальнейшее чтение. Это решение, которое я использую прямо сейчас, и только сервер DNSServer выглядит немного странно, поскольку все находится в одной строке. Я подключаюсь к DNSServer с помощью «`n «, чтобы он, по крайней мере, имел лучшую читаемость.
Ответ №2:
Я не стал указывать, что я передаю весь вывод в командлет ConvertTo-HTML, чтобы не выводить вопрос за рамки. Но поскольку я конвертирую выходные данные в HTML, это означает, что существует более 1 способа скинуть cat. Мне не нужно принудительно возвращать объект DNSServer к его предыдущему форматированию.
Итак, вместо того, чтобы присоединяться к DNSServer с помощью ‘, ‘, я присоединил к нему <br>
тег вместо этого.
Select-Object InterfaceAlias, InterfaceDescription, InterfaceIndex, @{n='IPv4 Address';e={$_.IPv4Address.IPAddress}}, @{n='IPv4 Default Gateway';e={$_.IPv4DefaultGateway.NextHop}}, @{n='DNS Server';e={$_.DNSServer.ServerAddresses -split " " -join "<br>"}}
Поскольку ConvertTo-HTML перевел символ <> в amp;<
и amp;>
соответственно, я добавил следующий код для перевода amp;<
и amp;>
обратно в <>.
$IPAddressConfigTemp = $IPAddressConfig | ConvertTo-Html -fragment -As List -PreContent "<h2>IP Address Configuration Details</h2>"
$IPAddressConfigHTML = $IPAddressConfigTemp -replace "amp;<", "<" -replace "amp;>", ">" -replace "amp;#39;", "'"
Частичный результат кода выглядит примерно так:
<table>
<tr><td>DNS Server:</td><td>2001:f40:0:3::12:68<br>2001:4860:4860::8888<br>1.1.1.1<br>8.8.8.8</td></tr>
</table>
Это не самое элегантное решение, но оно, по крайней мере, соответствует тому, чего я хотел бы достичь. Итак, поскольку я использую вычисляемое свойство для достижения окончательного решения, я выбрал ответ @beatcracker в качестве правильного ответа. Помогает то, что его ответ ответил на вопрос «почему» и помог мне учиться дальше.
Ответ №3:
Использование Select-Object с параметром -Property приводит к созданию нового объекта с новым типом (Выбран.NetIPConfiguration, передайте в Get-Member, чтобы увидеть это).
Форматирование в PowerShell основано на типах, поэтому форматирование заключается в том, чтобы видеть новый тип, а не применять форматирование из старого типа.
Предположительно, вы могли бы применить новое имя типа (используя свойство PSTypeNames) и скопировать инструкции по форматированию из старого имени типа (NetIPConfiguration) в новое.
Обратите внимание, что разница в форматировании не подразумевает никакой разницы в значениях свойств, это чисто косметическое.
Комментарии:
1. Спасибо. Мне не нужно выполнять дальнейшую обработку значений свойств, так что косметика достаточно хороша и именно то, что я хочу. Я попробую позже, чтобы посмотреть, смогу ли я скопировать старое форматирование из старого typename.
2. Я извинился, сказав, что мне не нужно выполнять дальнейшую обработку значений свойств. Поскольку я передаю выходные данные в ConvertTo-HTML, поэтому приведенное выше не является точным. Извините за неверную информацию и спасибо за вашу помощь.