Function 如何更改脚本以使主机名';s IP检查作用域的范围,而不是它是否与scopeID匹配?

Function 如何更改脚本以使主机名';s IP检查作用域的范围,而不是它是否与scopeID匹配?,function,powershell,range,ip-address,dhcp,Function,Powershell,Range,Ip Address,Dhcp,我想通过使用来自DHCP的数据来查找主机名的IP在哪个范围内。找到正确的范围后,在PScustomObject中输出范围名称 这里我从DHCP中提取所需的数据 $DHServers = Get-DhcpServerInDC foreach ($Server in $DHServers) { $scopes = Get-DHCPServerv4Scope -ComputerName $Server.DnsName | Select-Object Name, ScopeID, StartRange

我想通过使用来自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

检查范围后,如何获取主机所在的作用域名称?

要记住几点:

  • 好的代码是自我记录的。注释应该告诉您一组命令的作用或原因。注释“从csv获取名称”,然后编写
    $computerNames=Import csv
    ,这是多余的,因为代码行使您的操作同样清晰
  • 请记住,您还可以通过匹配主机名从DHCP获取计算机的作用域。尝试以下操作:
    foreach($scopes中的scope){if($scope | Get-DhcpServerV4Lease-ComputerName$server | Where Object HostName-like“$HostName*”){return$scope}}

  • 我看到你在我写这篇文章时更新了这个问题,所以我会检查是否有任何变化…

    我不清楚你在寻求什么帮助。这是第一个功能吗?你能不能把帖子限制在一个特定的问题上,并删除任何与这个问题不相关的代码?谢谢你的回复。我重新格式化了我的问题,希望能更简洁明了。感谢您的建议和代码中的所有注释,我非常感谢您提供的这些信息对学习PowerShell的帮助。第二条建议似乎更简单。再次非常感谢您提供的代码中的所有注释,这是我开始学习Powershell以来得到的最有用的东西。
    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