2012-11-21 31 views
3

我正在尝试在域中查找下一个可用的计算机名称。我们的计算机使用的命名格式 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)) 

回答

2

试试这个,它得到的所有计算机的名称以“DEPARTMENTNAME”,去掉所有的AZ字符,只留下数字,数字转换为整数,对它们进行排序,找到最大的一个:

$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} } 
+0

感谢您的建议,但它不完成任务。具体来说,它移动到最大值,在那里可能有一个较小的值(例如,计算机1,3,4,5,6,7,8,9,它将使用10,而不是2)。 更重要的是,它不会填充{0:d3}所做的前导零000。因此,如果您使用'Finance'并且没有'Finance *'机器,它将以Finance1开始而不是Finance001开始,如果您使用销售名称为Sales07的名称Sales,则它将选择名称Sales48(不含前导0) – idarryl

+0

@idarryl看我的编辑 –

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 
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 
相关问题