获取静态的接口及其 DNS 服务器(未分配 dhcp)
Getting interfaces and their DNS servers that are STATIC (not dhcp allocated)
我正在尝试通过静态(由用户放置)的 WMI 获取网络接口的 DNS 服务器。我有这个有效的脚本,当然除了静态部分:
Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DNSServerSearchOrder -ne $null} | Select DnsServerSearchOrder,Index,InterfaceIndex
这会导致如下输出:
DnsServerSearchOrder Index InterfaceIndex
-------------------- ----- --------------
{192.168.122.1} 1 6
{1.1.1.1} 2 10
与 192.168.122.1
的接口将其 DNS 设置为 DHCP,因此该值对我不利。如何过滤掉 dns 不是静态的接口?有什么想法吗?
netsh interface ip show config
:
Configuration for interface "Ethernet"
DHCP enabled: Yes
IP Address: 192.168.122.130
Subnet Prefix: 192.168.122.0/24 (mask 255.255.255.0)
Default Gateway: 192.168.122.1
Gateway Metric: 0
InterfaceMetric: 35
DNS servers configured through DHCP: 192.168.122.1
Register with which suffix: Primary only
WINS servers configured through DHCP: None
Configuration for interface "Ethernet 2"
DHCP enabled: Yes
IP Address: 10.0.0.17
Subnet Prefix: 10.0.0.0/24 (mask 255.255.255.0)
Default Gateway: 10.0.0.1
Gateway Metric: 0
InterfaceMetric: 35
Statically Configured DNS Servers: 1.1.1.1
Register with which suffix: Primary only
WINS servers configured through DHCP: None
请注意 Statically Configured DNS Servers
和 DNS servers configured through DHCP
之间的差异。我想我可能会解析这个输出,但我不确定如果 windows language/locale 被更改我是否可以依赖这个文本,如果可能的话我宁愿使用 WMI 接口。
经过充分的抨击后,我找到了解决方案,但我并不是 100% 肯定这是正确的方法。在所有 DHCP DNS 服务器上,DNS 值都包含一个 IP 地址,并且该 IP 地址等于 Default Gateway
值。当这些值匹配时,我们处理的是 DHCP DNS 服务器,而不是静态配置的。
我认为这可能在 netsh.exe
上的 System.Net.NetworkInformation
namespace, but evidently not. I looked through a few lower-level Windows networking APIs thinking certainly it must exist somewhere in there, but no such luck. After running dumpbin
中可用,以查看它消耗的 libraries/functions 类型,我确实想到了另一个可以查看的地方:注册表。
碰巧,如果您在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\
键下查看注册表,您会看到每个网络接口的键都具有 GUID 格式的名称。在接口的键中,您会发现两个感兴趣的值:DhcpNameServer
和 NameServer
。在我的 DNS 服务器由 DHCP 设置的客户端系统上,DhcpNameServer
包含该 DNS 服务器的 IP 地址,而 NameServer
包含一个空的 [String]
。如果我手动设置 DNS 服务器,同时保留接口本身的自动分配地址,NameServer
将包含手动设置的 DNS 服务器地址,而 DhcpNameServer
仍包含由 DHCP 指定的相同 DNS 服务器。
根据这些观察,似乎...
DhcpNameServer
值始终包含 DHCP 指定的 DNS 服务器。
NameServer
值始终包含手动指定的 DNS 服务器。
- 当您查询系统的名称服务器时(例如通过
Win32_NetworkAdapterConfiguration.DNSServerSearchOrder
属性),如果提供,结果将包含 NameServer
的值,否则 DhcpNameServer
,如果提供的话。换句话说,系统会告诉您哪些 DNS 服务器当前正在使用,但不会告诉您它们的地址是如何指定的。
- 要确定接口是否具有手动分配的 DNS 服务器,请检查
NameServer
是否具有非空值。
因此,给定 ID 为 $interfaceID
的接口,您可以像这样构建其注册表项的路径...
$interfaceKeyPath = "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces$interfaceID"
...然后像这样检索动态分配和手动分配的名称服务器值...
Get-ItemProperty -Path $interfaceKeyPath -Name 'DhcpNameServer', 'NameServer'
剩下的问题就是你从哪里得到 $interfaceID
的值,而且有很多来源,尽管技巧将排除不需要的接口(例如,在我的 Windows 10 系统上我有一个数据包捕获环回适配器和一个管理程序适配器,我想将其排除在此类查询之外)。最兼容的方式(可追溯到 .NET 2.0)是 Id
property of the NetworkInterface
class...
[System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() `
| Select-Object -ExpandProperty 'Id'
...虽然唯一有用的properties on which to filter are Name
and NetworkInterfaceType
.
在 Windows Vista 和更高版本上 Win32_NetworkAdapter
class 提供 GUID
属性...
Get-WmiObject -Class 'Win32_NetworkAdapter' -Property 'GUID' -Filter 'PhysicalAdapter = true'
...尽管即使在 PhysicalAdapter
上进行过滤,它仍然是 return 环回和管理程序适配器,我没有看到任何确定的 属性 或 class只能用于 select 硬件适配器的关系。
Win32_NetworkAdapterConfiguration
class 大同小异...
Get-WmiObject -Class 'Win32_NetworkAdapterConfiguration' -Property 'SettingID'
...没有过滤掉非硬件甚至非物理适配器的属性。
在(我认为)Windows 8 及以上有 Get-NetConnectionProfile
cmdlet...
Get-NetConnectionProfile | Select-Object -ExpandProperty 'InstanceID'
记录为 "a connection profile associated with one or more physical network adapters",在我的系统上,它只 return 我的物理适配器。
Get-NetAdapter -Physical `
| Where-Object -Property 'EndPointInterface' -NE -Value $true `
| Select-Object -ExpandProperty 'InterfaceGuid'
我发现传递 -Physical
参数排除了管理程序适配器而不是环回适配器,因此有必要过滤掉 EndPointInterface
是 $true
的地方以消除它。 HardwareInterface
和 Virtual
属性可能也很有趣。
另一种选择是调用 Get-NetAdapterHardwareInfo
cmdlet,它似乎知道如何区分真正的硬件适配器,并让它确定哪些适配器由 Get-NetAdapter
...
Get-NetAdapterHardwareInfo `
| Get-NetAdapter `
| Select-Object -ExpandProperty 'InterfaceGuid'
return CIM 实例上方的 Get-Net*
cmdlet,因此,例如,您可以使用诸如...
之类的东西来代替 Get-NetAdapter -Physical
Get-WmiObject -Namespace 'Root\StandardCimv2' -Class 'MSFT_NetAdapter' `
-Property 'InterfaceGuid' -Filter 'HardwareInterface = true AND EndPointInterface = false'
以相同的方式检索 MSFT_NetAdapter
个实例。我不太确定关于使用一个与另一个的指导是什么。看起来人们应该更喜欢 cmdlet,但是,与 WMI/CIM 不同,它们提供 limited/no 参数来有效地过滤输出或指定所需的属性,因此您必须在管道中执行此操作。不过,我认为值得注意的是,我无法找到这些 MSFT_*
class 的任何 current 文档;他们都说他们不再更新,除了 MSFT_NetConnectionProfile
class 我根本找不到任何文档页面。这对我说微软不希望你依赖这些 classes 的任何明确结构,但如果 cmdlet 只是传递那些 class 实例......我不确定你怎么能如果没有任何记录,则与他们进行有意义且可靠的交互。
此外,请记住,如果可能,您会 want to prefer Get-CimInstance
and its ilk over Get-WmiObject
。我认为我还没有遇到过比将 Get-WmiObject
更改为 Get-CimInstance
更复杂的实例,尽管有比名称更多的差异(不一定是坏的)。
我正在尝试通过静态(由用户放置)的 WMI 获取网络接口的 DNS 服务器。我有这个有效的脚本,当然除了静态部分:
Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DNSServerSearchOrder -ne $null} | Select DnsServerSearchOrder,Index,InterfaceIndex
这会导致如下输出:
DnsServerSearchOrder Index InterfaceIndex
-------------------- ----- --------------
{192.168.122.1} 1 6
{1.1.1.1} 2 10
与 192.168.122.1
的接口将其 DNS 设置为 DHCP,因此该值对我不利。如何过滤掉 dns 不是静态的接口?有什么想法吗?
netsh interface ip show config
:
Configuration for interface "Ethernet"
DHCP enabled: Yes
IP Address: 192.168.122.130
Subnet Prefix: 192.168.122.0/24 (mask 255.255.255.0)
Default Gateway: 192.168.122.1
Gateway Metric: 0
InterfaceMetric: 35
DNS servers configured through DHCP: 192.168.122.1
Register with which suffix: Primary only
WINS servers configured through DHCP: None
Configuration for interface "Ethernet 2"
DHCP enabled: Yes
IP Address: 10.0.0.17
Subnet Prefix: 10.0.0.0/24 (mask 255.255.255.0)
Default Gateway: 10.0.0.1
Gateway Metric: 0
InterfaceMetric: 35
Statically Configured DNS Servers: 1.1.1.1
Register with which suffix: Primary only
WINS servers configured through DHCP: None
请注意 Statically Configured DNS Servers
和 DNS servers configured through DHCP
之间的差异。我想我可能会解析这个输出,但我不确定如果 windows language/locale 被更改我是否可以依赖这个文本,如果可能的话我宁愿使用 WMI 接口。
经过充分的抨击后,我找到了解决方案,但我并不是 100% 肯定这是正确的方法。在所有 DHCP DNS 服务器上,DNS 值都包含一个 IP 地址,并且该 IP 地址等于 Default Gateway
值。当这些值匹配时,我们处理的是 DHCP DNS 服务器,而不是静态配置的。
我认为这可能在 netsh.exe
上的 System.Net.NetworkInformation
namespace, but evidently not. I looked through a few lower-level Windows networking APIs thinking certainly it must exist somewhere in there, but no such luck. After running dumpbin
中可用,以查看它消耗的 libraries/functions 类型,我确实想到了另一个可以查看的地方:注册表。
碰巧,如果您在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\
键下查看注册表,您会看到每个网络接口的键都具有 GUID 格式的名称。在接口的键中,您会发现两个感兴趣的值:DhcpNameServer
和 NameServer
。在我的 DNS 服务器由 DHCP 设置的客户端系统上,DhcpNameServer
包含该 DNS 服务器的 IP 地址,而 NameServer
包含一个空的 [String]
。如果我手动设置 DNS 服务器,同时保留接口本身的自动分配地址,NameServer
将包含手动设置的 DNS 服务器地址,而 DhcpNameServer
仍包含由 DHCP 指定的相同 DNS 服务器。
根据这些观察,似乎...
DhcpNameServer
值始终包含 DHCP 指定的 DNS 服务器。NameServer
值始终包含手动指定的 DNS 服务器。- 当您查询系统的名称服务器时(例如通过
Win32_NetworkAdapterConfiguration.DNSServerSearchOrder
属性),如果提供,结果将包含NameServer
的值,否则DhcpNameServer
,如果提供的话。换句话说,系统会告诉您哪些 DNS 服务器当前正在使用,但不会告诉您它们的地址是如何指定的。 - 要确定接口是否具有手动分配的 DNS 服务器,请检查
NameServer
是否具有非空值。
因此,给定 ID 为 $interfaceID
的接口,您可以像这样构建其注册表项的路径...
$interfaceKeyPath = "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces$interfaceID"
...然后像这样检索动态分配和手动分配的名称服务器值...
Get-ItemProperty -Path $interfaceKeyPath -Name 'DhcpNameServer', 'NameServer'
剩下的问题就是你从哪里得到 $interfaceID
的值,而且有很多来源,尽管技巧将排除不需要的接口(例如,在我的 Windows 10 系统上我有一个数据包捕获环回适配器和一个管理程序适配器,我想将其排除在此类查询之外)。最兼容的方式(可追溯到 .NET 2.0)是 Id
property of the NetworkInterface
class...
[System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() `
| Select-Object -ExpandProperty 'Id'
...虽然唯一有用的properties on which to filter are Name
and NetworkInterfaceType
.
在 Windows Vista 和更高版本上 Win32_NetworkAdapter
class 提供 GUID
属性...
Get-WmiObject -Class 'Win32_NetworkAdapter' -Property 'GUID' -Filter 'PhysicalAdapter = true'
...尽管即使在 PhysicalAdapter
上进行过滤,它仍然是 return 环回和管理程序适配器,我没有看到任何确定的 属性 或 class只能用于 select 硬件适配器的关系。
Win32_NetworkAdapterConfiguration
class 大同小异...
Get-WmiObject -Class 'Win32_NetworkAdapterConfiguration' -Property 'SettingID'
...没有过滤掉非硬件甚至非物理适配器的属性。
在(我认为)Windows 8 及以上有 Get-NetConnectionProfile
cmdlet...
Get-NetConnectionProfile | Select-Object -ExpandProperty 'InstanceID'
记录为 "a connection profile associated with one or more physical network adapters",在我的系统上,它只 return 我的物理适配器。
Get-NetAdapter -Physical `
| Where-Object -Property 'EndPointInterface' -NE -Value $true `
| Select-Object -ExpandProperty 'InterfaceGuid'
我发现传递 -Physical
参数排除了管理程序适配器而不是环回适配器,因此有必要过滤掉 EndPointInterface
是 $true
的地方以消除它。 HardwareInterface
和 Virtual
属性可能也很有趣。
另一种选择是调用 Get-NetAdapterHardwareInfo
cmdlet,它似乎知道如何区分真正的硬件适配器,并让它确定哪些适配器由 Get-NetAdapter
...
Get-NetAdapterHardwareInfo `
| Get-NetAdapter `
| Select-Object -ExpandProperty 'InterfaceGuid'
return CIM 实例上方的 Get-Net*
cmdlet,因此,例如,您可以使用诸如...
Get-NetAdapter -Physical
Get-WmiObject -Namespace 'Root\StandardCimv2' -Class 'MSFT_NetAdapter' `
-Property 'InterfaceGuid' -Filter 'HardwareInterface = true AND EndPointInterface = false'
以相同的方式检索 MSFT_NetAdapter
个实例。我不太确定关于使用一个与另一个的指导是什么。看起来人们应该更喜欢 cmdlet,但是,与 WMI/CIM 不同,它们提供 limited/no 参数来有效地过滤输出或指定所需的属性,因此您必须在管道中执行此操作。不过,我认为值得注意的是,我无法找到这些 MSFT_*
class 的任何 current 文档;他们都说他们不再更新,除了 MSFT_NetConnectionProfile
class 我根本找不到任何文档页面。这对我说微软不希望你依赖这些 classes 的任何明确结构,但如果 cmdlet 只是传递那些 class 实例......我不确定你怎么能如果没有任何记录,则与他们进行有意义且可靠的交互。
此外,请记住,如果可能,您会 want to prefer Get-CimInstance
and its ilk over Get-WmiObject
。我认为我还没有遇到过比将 Get-WmiObject
更改为 Get-CimInstance
更复杂的实例,尽管有比名称更多的差异(不一定是坏的)。