查找下一个可用计算机名称

时间:2012-11-21 11:49:51

标签: powershell

我正在尝试在外域中找到下一个可用的计算机名称。我们的计算机使用命名格式 departmentName001

departmentName003

departmentName004

...

departmentName999

我可以找到现有的计算机帐户并添加1但我无法让它开始查看001,我知道使用"{0:d3}" -f但我没有使用它正确。有人可以帮忙吗?

function GetComputerList($ComputerName)
{
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = “LDAP://dc=domain,dc=local”
$objSearcher.Filter = ("(&(objectCategory=computer)(name=$ComputerName))")
$colProplist = "name"
$objSearcher.PageSize = 1000
    foreach ($i in $colPropList){[void]$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
    {$objComputer = $objResult.Properties; $objComputer.name}
}


$HostName = Finance
$unit="{0:d3}" -f $_

$num = GetComputerList("$HostName*") | Foreach {[int]($_.Name)} | Sort-Object | Select-Object -Last 1 
$name = $HostName+($unit+($num+1))

3 个答案:

答案 0 :(得分:2)

试试这个,它获取名称以'departmentName'开头的所有计算机,删除所有a-z字符,只留下数字,将数字转换为整数并对它们进行排序以找到最大的数字:

$searcher = [ADSISearcher]'(&(objectCategory=computer)(name=departmentName*))'
$searcher.PageSize = 1000
$last = $searcher.FindAll() | Foreach-Object { [int]($_.Properties.name -replace '\D').Trim() } | Sort-Object | Select-Object -Last 1
$digitLength = "$last".Length
$NewComputerName = "{0}{1:D$digitLength}" -f 'departmentName',($last+1)
$NewComputerName 

编辑:

# get next available number in a range of numbers. returns 5 for 1,2,3,4,6,7,9
$number = $searcher.FindAll() | Foreach-Object { [int]($_.Properties.name -replace '\D').Trim() } | Sort-Object    

for($i=0; $i -lt $number.length; $i++) {if( $number[$i+1]-$number[$i] -gt 1) {$number[$i]+1; break} }

答案 1 :(得分:1)

试试这个:

$searcher = [ADSISearcher]'(&(objectCategory=computer)(name=Finance*))'
$searcher.PageSize = 1000
$last = $searcher.FindAll() | Foreach-Object {
[string]($_.Properties.name -replace '\D')  }  | Sort-Object     
$i = 0
$last | % { if ($i -ne [int]$_ ) { $new = $i.tostring().padleft(3,'0'); break } 
else 
{ $i++ }}

$newComputerName = "finance" + $new 

答案 2 :(得分:0)

基于这篇文章中的信息,我对我的环境代码进行了一些更改和调整,以检查不仅仅是AD ..还修复了它在一个范围的开头没有填空。我有在此博客:AutoGeneratingServer Names

这里的代码副本,我知道它可以重构很多!

[CmdletBinding()]
param()

# ********************************************************
$startOfName = "xxxYYYZZWEB"
# ********************************************************

# VMWare Details
$ADVIServers = @("vsphere1.blah.local","vsphere2.blah.local","vsphere3.blah.local","vsphere4.blah.local")
$StandAloneHosts = @()

# DNS Details
$DNSServer = "xxxxxx.blah.local"

# SCCM 2012 Details
$SCCM2012SiteServer = "sccm2012.blah.local"
$SCCM2012SiteCode = 'SiteCode' 

# SCCM 2007 Details
$SCCM2007SiteServer = "sccm2007.blah.local"
$SCCM2007SiteCode = 'SiteCode2' 

# SCOM 2007 Details
$SCOMServer = "scom.blah.local"

# Create Empty Arrays
$VMNumbers = @()
$ADnumbers = @()
$DNSNumbers = @()
$SCCM2012Numbers = @()
$SCCM2007Numbers = @()
$SCOM2007Numbers = @()


# VMWare

    Write-Verbose "Processing VMware"
    Add-PSSnapin vmware.vimautomation.core -ErrorAction SilentlyContinue

    # Set options for certificates and connecting to multiple enviroments
    $null = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$False
    $null = Set-PowerCLIConfiguration -DefaultVIServerMode Multiple -Scope User -Confirm:$False

    # Connect to each AD Authenticated viServer
    foreach ($VIServer in $ADVIServers){$null = Connect-VIServer $VIServer -verbose:$false} 

    # Connect to standalone host
    foreach ($Host in $StandAloneHosts){$null = Connect-VIServer $Host -User 'usernamehere' -Password 'passwordhere' -verbose:$false} 

    # get next available number in a range of numbers.
    $VMNames = Get-VM -Name "$($startOfName)*" -verbose:$false |select Name
    $VMNames |select Name | Foreach-Object {Write-Verbose $_.Name} | Sort-Object
    $VMNumbers = $VMNames |select Name | Foreach-Object {[int]($_.Name -replace '\D').Trim() } | Sort-Object
    Write-Verbose "$($VMNumbers.Count) Matching entries found"

# Active Directory

    Write-Verbose "Processing Active Directory"

    # Issue Query
    $searcher = [ADSISearcher]"(&(objectCategory=computer)(name=$($StartOfName)*))"
    $searcher.PageSize = 1000

    # get next available number in a range of numbers. returns 5 for 1,2,3,4,6,7,9 From AD
    $ADNames = $searcher.FindAll() | Foreach-Object {[string]$_.Properties.name} | Sort-Object
    $ADNames | Foreach-Object {Write-Verbose $_} | Sort-Object  
    $ADnumbers = $ADNames | Foreach-Object {[int]($_ -replace '\D').Trim() } | Sort-Object  
    Write-Verbose "$($ADnumbers.Count) Matching entries found"

# Search DNS

    Write-Verbose "Processing DNS"

    # Import DNS module
    Import-Module dnsShell -Verbose:$false
    $DNSNames = get-dnsRecord -server $DNSServer -RecordType A -Zone blah.local | select Name |where {$_.Name -like "$($startOfName)*"} 
    $DNSNames | Foreach-Object {Write-Verbose $_.Name} | Sort-Object -Unique
    $DNSNumbers = $DNSNames | Foreach-Object {[int]($_.Name -replace '\D').Trim() } | Sort-Object -Unique
    Write-Verbose "$($DNSNumbers.Count) Matching entries found"

# Search SCCM

    Write-Verbose "Processing SCCM 2012"

    # Query SCCM2012 Env
    $SCCM2012Members = Get-WmiObject -ComputerName $SCCM2012SiteServer -Namespace  "ROOT\SMS\site_$SCCM2012SiteCode" -Query "SELECT * FROM SMS_FullCollectionMembership WHERE CollectionID='SMS00001' AND Name LIKE '$($startOfName)%' order by name" | select Name -Unique
    $SCCM2012Members |select Name | Foreach-Object {Write-Verbose $_.Name} | Sort-Object
    $SCCM2012Numbers = $SCCM2012Members |select Name | Foreach-Object {[int]($_.Name -replace '\D').Trim() } | Sort-Object
    Write-Verbose "$($SCCM2012Numbers.Count) Matching entries found"

    Write-Verbose "Processing SCCM 2007"

    # Query SCCM2007 Env
    $SCCM2007Names = Get-WMIObject -ComputerName $SCCM2007SiteServer -Namespace "root\sms\site_$SCCM2007SiteCode" -class "SMS_R_System" -filter "Name LIKE `"$startOfName%`"" |select Name | Sort-Object -Property Name -Unique
    $SCCM2007Names |select Name | Foreach-Object {Write-Verbose $_.Name} | Sort-Object
    $SCCM2007Numbers = $SCCM2007Names |select Name | Foreach-Object {[int]($_.Name -replace '\D').Trim() } | Sort-Object
    Write-Verbose "$($SCCM2007Numbers.Count) Matching entries found"

# Search Production SCOM 2007

    Write-Verbose "Processing SCOM 2007"

    #Initialize SCOM SnapIn
    Add-PSSnapin Microsoft.EnterpriseManagement.OperationsManager.Client -ErrorAction SilentlyContinue -verbose:$false

    #Connect to Production SCOM 2007 Env.
    $null = New-ManagementGroupConnection -ConnectionString $SCOMServer

    #Connect to SCOM Provider
    Push-Location 'OperationsManagerMonitoring::'

    # Get Agents Matching Name
    $SCOM2007Names = Get-ManagementServer |Get-Agent |Where {$_.Name -like "$($startOfName)*"}
    $SCOM2007Names | Foreach-Object {Write-Verbose $_.Name} | Sort-Object
    $SCOM2007Numbers = $SCOM2007Names | Foreach-Object {[int]($_.Name -replace '\D').Trim() } | Sort-Object
    Write-Verbose "$($SCOM2007Numbers.Count) Matching entries found"

    # Return to previous location
    Pop-Location

# Merge arrays adding a zero so we allways start issuing numbers from the beginning (ie 001)
$list = @(0) + $VMNumbers + $ADnumbers + $DNSNumbers + $SCCM2012Numbers + $SCCM2007Numbers + $SCOM2007Numbers

# Remove Duplicates numbers from the array and sort into numerical order
$list = $list | Sort-Object -Unique

Write-Verbose "Used numbers after sorting: $($list)"

# Determine if next server name is a gap in the sequence in the array
for($i=0; $i -lt $list.length; $i++) {
    if( $list[$i+1]-$list[$i] -gt 1) {
        # The gap between the current server number and the next element in the array is greater than 1
        # So we have an available number we can use.
        # TODO: - Add support for consecutive numbers IE build 6 servers with consecutive numbers.
        $num = "{0:000}" -f ($list[$i]+1)
        break
    }
}

# If no gap found in the sequence then use the next number from the sequence in the array
if ($num -eq $null) {
    $num = "{0:000}" -f (($list[-1]+1))
}

# Construct new name
$NewComputerName = "{0}{1}" -f $startOfName,$num

# Create DNS Record to 'reserve / mark the name as in use'
Write-Verbose "Creating DNS Reservation"
New-DnsRecord -Name $NewComputerName -IPAddress "127.0.0.1" -Zone blah.local -Type A -Server $DNSServer

write-output $NewComputerName