如何更改我的脚本以便主机名的 IP 检查范围的范围而不是它是否与 scopeID 匹配?
How to I change my script so the hostname's IP checks the range of the scope rather than if it matches the scopeID?
我想通过使用来自 DHCP 的数据找到主机名的 IP 在哪个作用域范围内。找到正确的作用域范围后,在我的 PScustomObject
中输出作用域名称
这里我从DHCP中拉取我需要的数据
$DHServers = Get-DhcpServerInDC
foreach ($Server in $DHServers)
{
$scopes = Get-DHCPServerv4Scope -ComputerName $Server.DnsName | Select-Object Name, ScopeID, StartRange, EndRange
ForEach ($Address in $scopes)
{
$Address | Export-Csv "C:\script\Results\ServerScopes.csv" -Append -NoTypeInformation
}
}
这里我导入主机名,然后获取它的IP和详细信息。
$list = Get-Content C:\script\HostNames.txt
$Output = foreach ($hostname in $list)
{
if (test-connection -count 1 -computername $hostname -quiet)
{
$System = Get-WmiObject Win32_ComputerSystem -ComputerName $hostname | Select-Object -Property Name,Model
$BIOS = Get-WmiObject Win32_BIOS -ComputerName $hostname | Select-Object -Property SerialNumber
$User = get-childitem "\$hostname\c$\Users" | Sort-Object LastWriteTime -Descending | Select-Object -first 1
$mac = invoke-command -computername $hostname {(gwmi -class win32_networkadapterconfiguration).MacAddress | select -first 1}
$IpV = (test-connection -ComputerName $hostname -count 1 | select -expandproperty IPV4Address).IPaddresstostring
[PSCustomObject]@{ #Rename varibles in data pull for output file
ComputerName = $hostname
Model = $System.Model
SerialNumber = $BIOS.SerialNumber
LastUser = $User
MacAddress = $mac
IpAddress = $Ip
NameOfScopeHostIsIn = ??????????
}
}
else #statement if hostname is not online
{
$Output
$Output | Export-Csv -Path C:\script\Result.csv -No
如何在检查范围后获取主机所在的范围名称?
有几点要记住:
- 好的代码是自我记录的。注释应该告诉您 组命令 的作用,或者 为什么 。注释“getting names from csv”然后写
$computerNames = Import-Csv
是多余的,因为这行代码让你清楚地知道你在做什么。
- 请记住,您还可以通过匹配主机名从 DHCP 获取计算机的范围。试试这个:
foreach ($scope in $scopes) { if($scope | Get-DhcpServerV4Lease -ComputerName $server | Where-Object HostName -like "$hostName*") { return $scope } }
function Test-IPIsInRange {
[CmdletBinding()]
# allow parameters to be piped in
param(
[Parameter(Mandatory, Position = 0, ValueFromPipelineByPropertyName)]
[System.Net.IPAddress]$IPAddress,
[Parameter(Mandatory, Position = 1, ValueFromPipelineByPropertyName)]
[System.Net.IPAddress]$StartRange,
[Parameter(Mandatory, Position = 2, ValueFromPipelineByPropertyName)]
[System.Net.IPAddress]$EndRange
)
# begin defines initialization work for a pipeline-enabled function (has ValueFromPipeline... in
# any parameter attribute). This scriptblock is run once at the beginning of the function.
begin {
# define a helper function to convert an IP address to a numeric value
function Convert-IPv4ToNumber {
[CmdletBinding()]
param(
[Parameter(Mandatory, Position = 0, ValueFromPipeline)]
[System.Net.IPAddress]$IPAddress
)
process {
$bytes = $IPAddress.GetAddressBytes()
[long]$addressNumber = 0
[long]$factor = 1;
for($i = $bytes.Length; $i -gt 0; $i--) {
$addressNumber += $bytes[$i - 1] * $factor
$factor *= 256
}
return $addressNumber
}
}
}
# accepting piped parameters means we have to put the main function logic in process{}
# This script block is run once for each item piped into the function.
process {
# get numeric values of the IP addresses
$RangeMin = $StartRange | Convert-IPv4ToNumber
$RangeMax = $EndRange | Convert-IPv4ToNumber
$Value = $IPAddress | Convert-IPv4ToNumber
# return whether the address is within the given range
return ($RangeMin -le $Value -and $Value -le $RangeMax)
}
}
$DHServers = Get-DhcpServerInDC
foreach ($Server in $DHServers)
{
$scopes = Get-DHCPServerv4Scope -ComputerName $Server.DnsName | Select-Object Name, ScopeID, StartRange, EndRange
# -> note that this line will add scopes repeatedly to the file even if they are already defined
# -> it would be better IMO to import the script, merge the current values, and export it.
$Scopes | Export-Csv "C:\script\Results\ServerScopes.csv" -Append -NoTypeInformation
# -> also, no reason to enumerate and append individually if we're piping
# -> the data into the Export-Csv command with the '|' symbol
}
$hostnames = Get-Content C:\script\HostNames.txt
$Output = foreach ($hostname in $hostnames)
{
# -> It's better to run your commands all in a single script sent to the computer,
# -> especially since you're using invoke-command at all. (If all commands were
# -> `get-wmiobject -computername $hostname` I could see a reason not to).
try {
$InvokeCommandParams = @{
ErrorAction = 'Stop' # set ErrorAction to Stop to allow an error to trigger the catch block
ComputerName = $hostname
ScriptBlock = {
# -> Ignore all errors once we're remoted into the computer.
# -> This prevents an error from tricking the script into thinking the computer is offline.
trap {continue}
# -> Consider using Get-CimInstance instead of Get-WmiObject. It's basically the modern version of the same command.
$Network = Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object IPAddress -ne $null
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
Model = Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty Model
SerialNumber = Get-WmiObject -Class Win32_Bios | Select-Object -ExpandProperty SerialNumber
LastUser = Get-ChildItem "C:\users" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 -ExpandProperty Name
MacAddress = $Network.MacAddress
# -> I include the following line to select the IPv4 address, otherwise you'll get IPv4 and IPv6.
# -> I don't know enough about IP addresses to know if this is a bad way to do it.
IPAddress = $Network.IPAddress | Where-Object { ([ipaddress]$_).AddressFamily -eq 'InterNetwork' }
}
}
}
# -> Splatting can be used to pair parameter names from keys, and values from the values of a hashtable.
# -> It's prettier :)
$retrieved = Invoke-Command @InvokeCommandParams
$LocationMember = @{
MemberType = 'NoteProperty'
Name = 'Location'
Value = $scopes | Where-Object {$_ | Test-IPIsInRange -IPAddress $retrieved.IPAddress } | Select-Object -ExpandProperty Name
PassThru = $true
}
$retrieved | Add-Member @LocationMember
}
# -> If the remote command fails, we know the computer's not online (or at last can't be reached)
catch {
# -> I'd recommend using Write-Error or pretty much anything but Write-Host in most cases,
# -> but at least try using this instead of the string concatenation that was being used.
Write-Host "$hostname Is not online, can't pull data for offline assets. $hostname was not added to the output file." -BackgroundColor DarkRed
}
}
# -> because Invoke-Command returns extra details, we'll narrow our selection
# -> before adding it to the CSV file.
$Properties = @('ComputerName', 'Model', 'SerialNumber', 'Location', 'LastUser', 'MacAddress', 'IPAddress')
$Output | Select-Object $Properties
$Output | Select-Object $Properties | Export-Csv -Path C:\script\Result.csv -NoTypeInformation
我看到你在我写这篇文章时更新了问题,所以我会检查是否有任何变化...
我想通过使用来自 DHCP 的数据找到主机名的 IP 在哪个作用域范围内。找到正确的作用域范围后,在我的 PScustomObject
中输出作用域名称这里我从DHCP中拉取我需要的数据
$DHServers = Get-DhcpServerInDC
foreach ($Server in $DHServers)
{
$scopes = Get-DHCPServerv4Scope -ComputerName $Server.DnsName | Select-Object Name, ScopeID, StartRange, EndRange
ForEach ($Address in $scopes)
{
$Address | Export-Csv "C:\script\Results\ServerScopes.csv" -Append -NoTypeInformation
}
}
这里我导入主机名,然后获取它的IP和详细信息。
$list = Get-Content C:\script\HostNames.txt
$Output = foreach ($hostname in $list)
{
if (test-connection -count 1 -computername $hostname -quiet)
{
$System = Get-WmiObject Win32_ComputerSystem -ComputerName $hostname | Select-Object -Property Name,Model
$BIOS = Get-WmiObject Win32_BIOS -ComputerName $hostname | Select-Object -Property SerialNumber
$User = get-childitem "\$hostname\c$\Users" | Sort-Object LastWriteTime -Descending | Select-Object -first 1
$mac = invoke-command -computername $hostname {(gwmi -class win32_networkadapterconfiguration).MacAddress | select -first 1}
$IpV = (test-connection -ComputerName $hostname -count 1 | select -expandproperty IPV4Address).IPaddresstostring
[PSCustomObject]@{ #Rename varibles in data pull for output file
ComputerName = $hostname
Model = $System.Model
SerialNumber = $BIOS.SerialNumber
LastUser = $User
MacAddress = $mac
IpAddress = $Ip
NameOfScopeHostIsIn = ??????????
}
}
else #statement if hostname is not online
{
$Output
$Output | Export-Csv -Path C:\script\Result.csv -No
如何在检查范围后获取主机所在的范围名称?
有几点要记住:
- 好的代码是自我记录的。注释应该告诉您 组命令 的作用,或者 为什么 。注释“getting names from csv”然后写
$computerNames = Import-Csv
是多余的,因为这行代码让你清楚地知道你在做什么。 - 请记住,您还可以通过匹配主机名从 DHCP 获取计算机的范围。试试这个:
foreach ($scope in $scopes) { if($scope | Get-DhcpServerV4Lease -ComputerName $server | Where-Object HostName -like "$hostName*") { return $scope } }
function Test-IPIsInRange {
[CmdletBinding()]
# allow parameters to be piped in
param(
[Parameter(Mandatory, Position = 0, ValueFromPipelineByPropertyName)]
[System.Net.IPAddress]$IPAddress,
[Parameter(Mandatory, Position = 1, ValueFromPipelineByPropertyName)]
[System.Net.IPAddress]$StartRange,
[Parameter(Mandatory, Position = 2, ValueFromPipelineByPropertyName)]
[System.Net.IPAddress]$EndRange
)
# begin defines initialization work for a pipeline-enabled function (has ValueFromPipeline... in
# any parameter attribute). This scriptblock is run once at the beginning of the function.
begin {
# define a helper function to convert an IP address to a numeric value
function Convert-IPv4ToNumber {
[CmdletBinding()]
param(
[Parameter(Mandatory, Position = 0, ValueFromPipeline)]
[System.Net.IPAddress]$IPAddress
)
process {
$bytes = $IPAddress.GetAddressBytes()
[long]$addressNumber = 0
[long]$factor = 1;
for($i = $bytes.Length; $i -gt 0; $i--) {
$addressNumber += $bytes[$i - 1] * $factor
$factor *= 256
}
return $addressNumber
}
}
}
# accepting piped parameters means we have to put the main function logic in process{}
# This script block is run once for each item piped into the function.
process {
# get numeric values of the IP addresses
$RangeMin = $StartRange | Convert-IPv4ToNumber
$RangeMax = $EndRange | Convert-IPv4ToNumber
$Value = $IPAddress | Convert-IPv4ToNumber
# return whether the address is within the given range
return ($RangeMin -le $Value -and $Value -le $RangeMax)
}
}
$DHServers = Get-DhcpServerInDC
foreach ($Server in $DHServers)
{
$scopes = Get-DHCPServerv4Scope -ComputerName $Server.DnsName | Select-Object Name, ScopeID, StartRange, EndRange
# -> note that this line will add scopes repeatedly to the file even if they are already defined
# -> it would be better IMO to import the script, merge the current values, and export it.
$Scopes | Export-Csv "C:\script\Results\ServerScopes.csv" -Append -NoTypeInformation
# -> also, no reason to enumerate and append individually if we're piping
# -> the data into the Export-Csv command with the '|' symbol
}
$hostnames = Get-Content C:\script\HostNames.txt
$Output = foreach ($hostname in $hostnames)
{
# -> It's better to run your commands all in a single script sent to the computer,
# -> especially since you're using invoke-command at all. (If all commands were
# -> `get-wmiobject -computername $hostname` I could see a reason not to).
try {
$InvokeCommandParams = @{
ErrorAction = 'Stop' # set ErrorAction to Stop to allow an error to trigger the catch block
ComputerName = $hostname
ScriptBlock = {
# -> Ignore all errors once we're remoted into the computer.
# -> This prevents an error from tricking the script into thinking the computer is offline.
trap {continue}
# -> Consider using Get-CimInstance instead of Get-WmiObject. It's basically the modern version of the same command.
$Network = Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object IPAddress -ne $null
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
Model = Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty Model
SerialNumber = Get-WmiObject -Class Win32_Bios | Select-Object -ExpandProperty SerialNumber
LastUser = Get-ChildItem "C:\users" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 -ExpandProperty Name
MacAddress = $Network.MacAddress
# -> I include the following line to select the IPv4 address, otherwise you'll get IPv4 and IPv6.
# -> I don't know enough about IP addresses to know if this is a bad way to do it.
IPAddress = $Network.IPAddress | Where-Object { ([ipaddress]$_).AddressFamily -eq 'InterNetwork' }
}
}
}
# -> Splatting can be used to pair parameter names from keys, and values from the values of a hashtable.
# -> It's prettier :)
$retrieved = Invoke-Command @InvokeCommandParams
$LocationMember = @{
MemberType = 'NoteProperty'
Name = 'Location'
Value = $scopes | Where-Object {$_ | Test-IPIsInRange -IPAddress $retrieved.IPAddress } | Select-Object -ExpandProperty Name
PassThru = $true
}
$retrieved | Add-Member @LocationMember
}
# -> If the remote command fails, we know the computer's not online (or at last can't be reached)
catch {
# -> I'd recommend using Write-Error or pretty much anything but Write-Host in most cases,
# -> but at least try using this instead of the string concatenation that was being used.
Write-Host "$hostname Is not online, can't pull data for offline assets. $hostname was not added to the output file." -BackgroundColor DarkRed
}
}
# -> because Invoke-Command returns extra details, we'll narrow our selection
# -> before adding it to the CSV file.
$Properties = @('ComputerName', 'Model', 'SerialNumber', 'Location', 'LastUser', 'MacAddress', 'IPAddress')
$Output | Select-Object $Properties
$Output | Select-Object $Properties | Export-Csv -Path C:\script\Result.csv -NoTypeInformation
我看到你在我写这篇文章时更新了问题,所以我会检查是否有任何变化...