Burnout
 New Member Posts:7

 |
| 18 Mar 2010 03:21 AM |
|
Hi Guys,
i'm trying to create a script da finds a free computername in the AD. For example the Computernames got a location info and a upcounting number. (DUB0001, DUB0002, DUB0005) In this sample the next available Computername would be DUB0003.
May anyone here has an idea how to set up a powershell script wich finds the next free computername ?
I wrote sth. wich brings me up all Computes wich are already in use. (Maybe this is the wrong start for my needs, but i'm new in powershell) Get-QADComputer -SearchRoot 'domain.com/Computers' | where {$_.computername -like "*DUB*"} | Sort-Object Computername | format-table -property computername
This already takes a couple of seconds (amount of pcs), maybe there is a better way ?
Thanks for your help!
|
|
|
|
|
cameronove
 Basic Member Posts:332

 |
| 18 Mar 2010 07:20 AM |
|
Here is a script that should return the next available name out of a list of names you provide in an array.
function Get-NextName($names){ $prev = 0 $namenums = $names | %{[int]([string]$_ -replace "\D","")} | sort foreach($num in $namenums){ if(($num - 1) -gt $prev){ $newnum = $prev + 1 return "DUB{0:0000}" -f $newnum }else{ $prev = $num } } } $computernames = Get-QADComputer -SearchRoot 'domain.com/computers' | %{$_.name} Get-NextName $computernames
|
|
|
|
|
cameronove
 Basic Member Posts:332

 |
| 18 Mar 2010 07:26 AM |
|
Hold up. My previous script didn't account for the scenario where all names have become consecutive (i.e. you used all the available names up in between all current names). This new function now accounts for that:
function Get-NextName($names){ $prev = 0 $namenums = $names | %{[int]([string]$_ -replace "\D","")} | sort foreach($num in $namenums){ if(($num - 1) -gt $prev){ $newnum = $prev + 1 return "DUB{0:0000}" -f $newnum }else{ $prev = $num } } return "DUB{0:0000}" -f ($prev+1) } $computernames = Get-QADComputer -SearchRoot 'domain.com/computers' | %{$_.name} Get-NextName $computernames
|
|
|
|
|
Burnout
 New Member Posts:7

 |
| 18 Mar 2010 08:14 AM |
|
Thanks for the quick reply, but I tested it and i got everytime the DUBPC0050 as first available, but this isn't true. (its already taken) I put sth. new together: $count = 1001 do { $comp =DUB + $count; $file = Get-QADComputer -Name $comp; $count += 1 } while ( $file -ne $null ) $comp (Like this it only works, starting at 1000 (If I make $count = 0001 it would be only 1 not 0001)) Also the performance of my script is not as good :-( |
|
|
|
|
cameronove
 Basic Member Posts:332

 |
| 18 Mar 2010 09:20 AM |
|
The logic in the function is not flawed. I think the problem is that there may be multiple naming conventions using numbers in each convention. The function itself doesn't know or care about the naming convention, it's just going to accumulate the numbers out of all the name in AD. From your posts it looks to me like these multiple naming conventions are stepping on each other. I.E. DUB0001-DUB0050 and DUBPC00035-DUBPC0051 then the two naming protocols would step on each other. It makes sense then that when getting your computers in the domain narrow the search down to the naming scheme in questions. This will speed up the script as well. I've included the ldapfilter switch in the Get-QADComputer command to narrow the search. That should fix your problem. If you have other naming conventions then replace *DUBPC* with the other naming convention (i.e. *DUB0* -I put the zero in this example so that the search won't pick up DUBPC; *DUB* would catch *DUBPC* as well).
function Get-NextName($names){ $prev = 0 $namenums = $names | %{[int]([string]$_ -replace "\D","")} | sort foreach($num in $namenums){ if(($num - 1) -gt $prev){ $newnum = $prev + 1 return "DUB{0:0000}" -f $newnum }else{ $prev = $num } } return "DUB{0:0000}" -f ($prev+1) } $computernames = Get-QADComputer -LdapFilter "(name=*dubpc*)" -SearchRoot 'domain.com/computers' | %{$_.name} Get-NextName $computernames
|
|
|
|
|
cameronove
 Basic Member Posts:332

 |
| 18 Mar 2010 09:31 AM |
|
Actually now that we are concerned about the naming convention DUB vs DUBPC or for that matter an other prefix to the numbering you will either need to edit the function or pass the naming scheme to the function. I've provided the function that passes the naming scheme along to the function and shows how to call it now:
function Get-NextName($names,$nameconvention){ $prev = 0 $namenums = $names | %{[int]([string]$_ -replace "\D","")} | sort foreach($num in $namenums){ if(($num - 1) -gt $prev){ $newnum = $prev + 1 return "$nameconvention{0:0000}" -f $newnum }else{ $prev = $num } } return "$nameconvention{0:0000}" -f ($prev+1) } $computernames = Get-QADComputer -LdapFilter "(name=*dubpc*)" -SearchRoot 'domain.com/computers' | %{$_.name} Get-NextName $computernames "DUBPC"
|
|
|
|
|
Burnout
 New Member Posts:7

 |
| 19 Mar 2010 06:37 AM |
|
Thanks, i will check this on monday. And no, i forgot to add the PC in the first script. the name is only different in DUBPC / DUBSRV / DUBSW etc... not DUB only. |
|
|
|
|
Burnout
 New Member Posts:7

 |
| 30 Mar 2010 01:20 AM |
|
hi cameronove, in that case i got also an computername wich is already taken: the first and the third 0001 & 0003 are also taken, but why we get here the 0002 ? >> Get-NextName $computernames "DUBPC" >> DUBPC0002 PS C:\ Get-QADComputer -Name dubpc0002 Name Type DN ---- ---- -- DUBPC0002 computer CN=DUBPC0002,CN=Computers,DC |
|
|
|
|
cameronove
 Basic Member Posts:332

 |
| 30 Mar 2010 07:53 AM |
|
To help troubleshoot this you should return the list of computers that $computernames contains to see if the computer in question is in that list. If it isn't then the search that puts the computer names into $computernames needs to be modified so that all of the computers are in that list. Also, I've modified the script so that it considers the naming convention in the evaluation of the computer names. It also grabs the last 4 characters of the computer name instead of replacing non-numeric characters. Perhaps that will be more accurate.
function Get-NextName($names,$nameconvention){ $prev = 0 $namenums = $names | ?{$_ -match "$nameconvention\d"} | %{[int]([string]$_.trim().substring($_.length - 4,4))} | sort foreach($num in $namenums){ if(($num - 1) -gt $prev){ $newnum = $prev + 1 return "$nameconvention{0:0000}" -f $newnum }else{ $prev = $num } } return "$nameconvention{0:0000}" -f ($prev+1) } $computernames = Get-QADComputer -LdapFilter "(name=*dubpc*)" -SearchRoot 'domain.com/computers' | %{$_.name} Get-NextName $computernames "DUBPC"
|
|
|
|
|
Burnout
 New Member Posts:7

 |
| 31 Mar 2010 02:30 AM |
|
Yeah, this is working :-) On question ahead, is there a possibility to cut off / delete the computers from $computernames wich aren't matching the DUBPC0000 rythm (for example it exists a DUBPC0023TEST or sth. like that, so I got an Integer error) Thank you very much! |
|
|
|
|
cameronove
 Basic Member Posts:332

 |
| 31 Mar 2010 05:11 AM |
|
Sure. When finding your computers just make sure you only grab names where the last four characters are numbers. The following code will demonstrates that for you with a where scriptblock.
$computernames = Get-QADComputer -LdapFilter "(name=*dubpc*)" -SearchRoot 'domain.com/computers' | where{[string]$_.trim().substring($_.length - 4,4) -match "\d{4}"} | %{$_.name}
|
|
|
|
|
cameronove
 Basic Member Posts:332

 |
| 31 Mar 2010 05:17 AM |
|
oops one quick edit In the where block it should be $_.name.trim().substring... Here it is again with the edit:
$computernames = Get-QADComputer -LdapFilter "(name=*dubpc*)" -SearchRoot 'domain.com/computers' | where{[string]$_.name.trim().substring($_.length - 4,4) -match "\d{4}"} | %{$_.name}
|
|
|
|
|
cameronove
 Basic Member Posts:332

 |
| 31 Mar 2010 05:26 AM |
|
The following has a different regex -match string that will eliminate the need to do a substring on the name for the match.
$computernames = Get-QADComputer -LdapFilter "(name=*dubpc*)" -SearchRoot 'domain.com/computers' | where{[string]$_.name.trim() -match "\d{4}\Z"} | %{$_.name}
|
|
|
|
|
cameronove
 Basic Member Posts:332

 |
| 31 Mar 2010 07:50 AM |
|
I got to thinking. Why not just move the gathering of the computernames into the function. Here is the function that does that. I've added a property to the function call called $domain. Because it has a default value you don't have to reference it when you make the call. You would only need to reference it if you wanted to get computer names from a different domain that your default naming context. So normally you would just run: Get-NextName dubpc Or you could run: Get-NextName dubpc 'domain2.com/computers' You could drop this function in your profile script and it will be available every time you load PowerShell. Then whenever you need a new computer name just type the function and the type of name you want to get.
function Get-NextName([string]$nameconvention,[string]$domain='domain.com/computers'){ $prev = 0 $names = Get-QADComputer -LdapFilter "(name=*$nameconvention*)" -SearchRoot $domain | where{[string]$_.name.trim() -match "\d{4}\Z"} | %{$_.name} $namenums = $names | ?{$_ -match "$nameconvention\d"} | %{[int]([string]$_.trim().substring($_.length - 4,4))} | sort foreach($num in $namenums){ if(($num - 1) -gt $prev){ $newnum = $prev + 1 return "$nameconvention{0:0000}" -f $newnum }else{ $prev = $num } } return "$nameconvention{0:0000}" -f ($prev+1) }
Just make sure you modify this function to $domain= your real domain. |
|
|
|
|