Trying to create a powershell user creation script, want to append number to username if it already exists
I am attempting to create a user creation script as a way to teach myself more Powershell. Currently I am only working on creating just the username and want to make sure each username is unique.
After a user inputs the name and number of a user the script should do the following.
Get the the first name
Get the middle initial
Get the last name
Combine the first letter of the first name + middle initial + 6 characters from the last name
If users already exists, add number starting at 1 until username is unique.
I am currently stuck on step 5. If the username is not unique it appends a number one. I.E. User Brenda T Follower has a username of BTFollow and if that username exists already it becomes BTFollow1.
However if BTFollow and BTFollow1 already exist instead of making BTFollow2 it makes BTFollow12.
Lastly, although not a huge issue I want my parameters to show what comes after Read-Host but that text is not appearing only the variable name.
Here is my code.
Param(
#Gather users first name, required input and must not be empty or null
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]
$FirstName = (Read-Host -Prompt 'Please input the users first name.'),
#Gather users middle initial, required input and must not be empty or null and must only be one character
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidateLength(1,1)]
[string]
$MiddleInitial = (Read-Host -Prompt 'Please input the users middle initial.'),
#Gather users last name, required input and must not be empty or null
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]
$LastName = (Read-Host -Prompt 'Please input the users last name.'),
#Gathers user phone extension, required input, mustn ot be empty or null, and must only user numbers
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidatePattern("[0-9][0-9][0-9][0-9]")]
[ValidateLength(4,4)]
[String]
$PhoneExtension = (Read-Host -Prompt 'Please input the users 4 digit exension, numbers only')
)
$i = 0
#Create user name
$Username = $FirstName.Substring(0,1) + $MiddleInitial + $LastName.Substring(0,6)
#Check username does not exist, if it does add numbers
Do {
Try {
Get-ADUser $UserName | Out-Null
$UserName = $Username + ++$i
Continue
}
Catch {
Break
}
} While ($True)
Write-Host "Username is $Username"
powershell
add a comment |
I am attempting to create a user creation script as a way to teach myself more Powershell. Currently I am only working on creating just the username and want to make sure each username is unique.
After a user inputs the name and number of a user the script should do the following.
Get the the first name
Get the middle initial
Get the last name
Combine the first letter of the first name + middle initial + 6 characters from the last name
If users already exists, add number starting at 1 until username is unique.
I am currently stuck on step 5. If the username is not unique it appends a number one. I.E. User Brenda T Follower has a username of BTFollow and if that username exists already it becomes BTFollow1.
However if BTFollow and BTFollow1 already exist instead of making BTFollow2 it makes BTFollow12.
Lastly, although not a huge issue I want my parameters to show what comes after Read-Host but that text is not appearing only the variable name.
Here is my code.
Param(
#Gather users first name, required input and must not be empty or null
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]
$FirstName = (Read-Host -Prompt 'Please input the users first name.'),
#Gather users middle initial, required input and must not be empty or null and must only be one character
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidateLength(1,1)]
[string]
$MiddleInitial = (Read-Host -Prompt 'Please input the users middle initial.'),
#Gather users last name, required input and must not be empty or null
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]
$LastName = (Read-Host -Prompt 'Please input the users last name.'),
#Gathers user phone extension, required input, mustn ot be empty or null, and must only user numbers
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidatePattern("[0-9][0-9][0-9][0-9]")]
[ValidateLength(4,4)]
[String]
$PhoneExtension = (Read-Host -Prompt 'Please input the users 4 digit exension, numbers only')
)
$i = 0
#Create user name
$Username = $FirstName.Substring(0,1) + $MiddleInitial + $LastName.Substring(0,6)
#Check username does not exist, if it does add numbers
Do {
Try {
Get-ADUser $UserName | Out-Null
$UserName = $Username + ++$i
Continue
}
Catch {
Break
}
} While ($True)
Write-Host "Username is $Username"
powershell
take a look at the 1st answer here ... active directory - Powershell AD Script - Add a number onto the end of account Name - Stack Overflow — stackoverflow.com/questions/50694247/…
– Lee_Dailey
Nov 13 '18 at 19:18
That did not work at all.
– Austin Downing
Nov 13 '18 at 19:43
As for "I want my parameters to show what comes after Read-Host but that text is not appearing only the variable name": It's an interesting problem, but please ask in it in a new, separate question.
– mklement0
Nov 13 '18 at 20:17
@AustinDowning - this line$SamAccountName = $defaultname + [string]$i
sure seems to work. i guess we must be thinking of different things. however, your answer below sure looks similar ... [grin]
– Lee_Dailey
Nov 13 '18 at 22:53
add a comment |
I am attempting to create a user creation script as a way to teach myself more Powershell. Currently I am only working on creating just the username and want to make sure each username is unique.
After a user inputs the name and number of a user the script should do the following.
Get the the first name
Get the middle initial
Get the last name
Combine the first letter of the first name + middle initial + 6 characters from the last name
If users already exists, add number starting at 1 until username is unique.
I am currently stuck on step 5. If the username is not unique it appends a number one. I.E. User Brenda T Follower has a username of BTFollow and if that username exists already it becomes BTFollow1.
However if BTFollow and BTFollow1 already exist instead of making BTFollow2 it makes BTFollow12.
Lastly, although not a huge issue I want my parameters to show what comes after Read-Host but that text is not appearing only the variable name.
Here is my code.
Param(
#Gather users first name, required input and must not be empty or null
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]
$FirstName = (Read-Host -Prompt 'Please input the users first name.'),
#Gather users middle initial, required input and must not be empty or null and must only be one character
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidateLength(1,1)]
[string]
$MiddleInitial = (Read-Host -Prompt 'Please input the users middle initial.'),
#Gather users last name, required input and must not be empty or null
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]
$LastName = (Read-Host -Prompt 'Please input the users last name.'),
#Gathers user phone extension, required input, mustn ot be empty or null, and must only user numbers
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidatePattern("[0-9][0-9][0-9][0-9]")]
[ValidateLength(4,4)]
[String]
$PhoneExtension = (Read-Host -Prompt 'Please input the users 4 digit exension, numbers only')
)
$i = 0
#Create user name
$Username = $FirstName.Substring(0,1) + $MiddleInitial + $LastName.Substring(0,6)
#Check username does not exist, if it does add numbers
Do {
Try {
Get-ADUser $UserName | Out-Null
$UserName = $Username + ++$i
Continue
}
Catch {
Break
}
} While ($True)
Write-Host "Username is $Username"
powershell
I am attempting to create a user creation script as a way to teach myself more Powershell. Currently I am only working on creating just the username and want to make sure each username is unique.
After a user inputs the name and number of a user the script should do the following.
Get the the first name
Get the middle initial
Get the last name
Combine the first letter of the first name + middle initial + 6 characters from the last name
If users already exists, add number starting at 1 until username is unique.
I am currently stuck on step 5. If the username is not unique it appends a number one. I.E. User Brenda T Follower has a username of BTFollow and if that username exists already it becomes BTFollow1.
However if BTFollow and BTFollow1 already exist instead of making BTFollow2 it makes BTFollow12.
Lastly, although not a huge issue I want my parameters to show what comes after Read-Host but that text is not appearing only the variable name.
Here is my code.
Param(
#Gather users first name, required input and must not be empty or null
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]
$FirstName = (Read-Host -Prompt 'Please input the users first name.'),
#Gather users middle initial, required input and must not be empty or null and must only be one character
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidateLength(1,1)]
[string]
$MiddleInitial = (Read-Host -Prompt 'Please input the users middle initial.'),
#Gather users last name, required input and must not be empty or null
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]
$LastName = (Read-Host -Prompt 'Please input the users last name.'),
#Gathers user phone extension, required input, mustn ot be empty or null, and must only user numbers
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidatePattern("[0-9][0-9][0-9][0-9]")]
[ValidateLength(4,4)]
[String]
$PhoneExtension = (Read-Host -Prompt 'Please input the users 4 digit exension, numbers only')
)
$i = 0
#Create user name
$Username = $FirstName.Substring(0,1) + $MiddleInitial + $LastName.Substring(0,6)
#Check username does not exist, if it does add numbers
Do {
Try {
Get-ADUser $UserName | Out-Null
$UserName = $Username + ++$i
Continue
}
Catch {
Break
}
} While ($True)
Write-Host "Username is $Username"
powershell
powershell
asked Nov 13 '18 at 18:56
Austin DowningAustin Downing
442
442
take a look at the 1st answer here ... active directory - Powershell AD Script - Add a number onto the end of account Name - Stack Overflow — stackoverflow.com/questions/50694247/…
– Lee_Dailey
Nov 13 '18 at 19:18
That did not work at all.
– Austin Downing
Nov 13 '18 at 19:43
As for "I want my parameters to show what comes after Read-Host but that text is not appearing only the variable name": It's an interesting problem, but please ask in it in a new, separate question.
– mklement0
Nov 13 '18 at 20:17
@AustinDowning - this line$SamAccountName = $defaultname + [string]$i
sure seems to work. i guess we must be thinking of different things. however, your answer below sure looks similar ... [grin]
– Lee_Dailey
Nov 13 '18 at 22:53
add a comment |
take a look at the 1st answer here ... active directory - Powershell AD Script - Add a number onto the end of account Name - Stack Overflow — stackoverflow.com/questions/50694247/…
– Lee_Dailey
Nov 13 '18 at 19:18
That did not work at all.
– Austin Downing
Nov 13 '18 at 19:43
As for "I want my parameters to show what comes after Read-Host but that text is not appearing only the variable name": It's an interesting problem, but please ask in it in a new, separate question.
– mklement0
Nov 13 '18 at 20:17
@AustinDowning - this line$SamAccountName = $defaultname + [string]$i
sure seems to work. i guess we must be thinking of different things. however, your answer below sure looks similar ... [grin]
– Lee_Dailey
Nov 13 '18 at 22:53
take a look at the 1st answer here ... active directory - Powershell AD Script - Add a number onto the end of account Name - Stack Overflow — stackoverflow.com/questions/50694247/…
– Lee_Dailey
Nov 13 '18 at 19:18
take a look at the 1st answer here ... active directory - Powershell AD Script - Add a number onto the end of account Name - Stack Overflow — stackoverflow.com/questions/50694247/…
– Lee_Dailey
Nov 13 '18 at 19:18
That did not work at all.
– Austin Downing
Nov 13 '18 at 19:43
That did not work at all.
– Austin Downing
Nov 13 '18 at 19:43
As for "I want my parameters to show what comes after Read-Host but that text is not appearing only the variable name": It's an interesting problem, but please ask in it in a new, separate question.
– mklement0
Nov 13 '18 at 20:17
As for "I want my parameters to show what comes after Read-Host but that text is not appearing only the variable name": It's an interesting problem, but please ask in it in a new, separate question.
– mklement0
Nov 13 '18 at 20:17
@AustinDowning - this line
$SamAccountName = $defaultname + [string]$i
sure seems to work. i guess we must be thinking of different things. however, your answer below sure looks similar ... [grin]– Lee_Dailey
Nov 13 '18 at 22:53
@AustinDowning - this line
$SamAccountName = $defaultname + [string]$i
sure seems to work. i guess we must be thinking of different things. however, your answer below sure looks similar ... [grin]– Lee_Dailey
Nov 13 '18 at 22:53
add a comment |
2 Answers
2
active
oldest
votes
Figured it out with the help of Reddit. I needed to replace my current code.
Do {
Try {
Get-ADUser $UserName | Out-Null
$UserName = $Username + ++$i
Continue
}
Catch {
Break
}
} While ($True)
New code that works.
#Check username does not exist, if it does add numbers
$UniqueUserName = $Username
while (Get-ADUser -Filter "SamAccountName -like '$UniqueUserName'"){
$UniqueUserName = $Username + ++$i
}
add a comment |
Because you iteratively modified $UserName
in your loop, you ended up appending an additional number in each iteration:
$UserName = $Username + ++$i
With BTFollow
as the original value, the value is BTFollow1
after the first iteration, and in the second iteration you then append 2
to that, resulting in BTFollow12
, and so on.
Your own answer works (though -like
should be replaced with -eq
) and, given its appealing concision and the presumed relative rarity of duplicate names, is probably the way to go.
The following solution provides optimizations, but the required complexity may not be worth it; at least I hope it showcases some interesting techniques.
You can avoid a costly loop around Get-AdUser
altogether, by pre-filtering potential duplicates with Get-ADUser -Filter
and then processing the candidates locally:
$highestIndexSoFar = (
Get-ADUser -Filter "SamAccountName -like '$UserName*'" |
ForEach-Object {
if ($_.SamAccountName -match "^$UserName(d*)`$") { [int] $Matches[1] }
} |
Sort-Object -Descending
)[0]
if ($null -eq $highestIndexSoFar) { # no duplicates -> use as-is
$UniqueUserName = $UserName
} else { # increment the highest index to date to make the username unique
$UniqueUserName = $UserName + (1 + $highestIndexSoFar)
}
Note: If there's a chance that $UserName
contains chars. with special meaning in a regex, construct the regex as follows:('^' + [regex]::Escape($UserName) + '(d*)$')
Another advantage of the above solution is that it determines the highest number suffix in the actual names, which reliably uses a new suffix that is the highest to date + 1, whereas the call-Get-AdUser
-in-a-loop approach uses the first index that isn't taken (though that would only be a concern if users got deleted over time or if out-of-sequence suffixes were manually created).
Get-ADUser -Filter "SamAccountName -like '$UserName*'"
retrieves potential duplicates; the-Filter
syntax isn't sophisticated enough to allow regex-based matching, so this pre-filtering can only find all usernames that share the same prefix, which may include false positives (e.g.,jdoet
forjdoe
, whereas only a numeric suffix such asjdoe1
should be considered).Regex
"^$UserName(d*)
$"is then used to weed out such false positives, and the actual numeric suffix (
d*) is reflected in the automatic
$Matchesvariable's
[1]entry, what the 1st (and only) capture group (
(...)` in the regex captured.
The numeric suffix, if present or empty, is then cast to
[int]
and output.
- Note that an initially unindexed username such as
BTFollow
will cause$Matches[1]
to be the empty string, which[int]
converts to0
, so the first index appended will be1
.
- Note that an initially unindexed username such as
Sort-Object -Descending
sorts the resulting numbers in descending order, and index[0]
of the sorted array therefore contains the highest suffix number found.If no matches are found at all, i.e. if the username isn't taken yet, the array is empty, and index
[0]
yields$null
; otherwise,1
must be added to highest number to form the new unique username.
Caveat: This approach may still fail if others are creating users simultaneously.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287794%2ftrying-to-create-a-powershell-user-creation-script-want-to-append-number-to-use%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Figured it out with the help of Reddit. I needed to replace my current code.
Do {
Try {
Get-ADUser $UserName | Out-Null
$UserName = $Username + ++$i
Continue
}
Catch {
Break
}
} While ($True)
New code that works.
#Check username does not exist, if it does add numbers
$UniqueUserName = $Username
while (Get-ADUser -Filter "SamAccountName -like '$UniqueUserName'"){
$UniqueUserName = $Username + ++$i
}
add a comment |
Figured it out with the help of Reddit. I needed to replace my current code.
Do {
Try {
Get-ADUser $UserName | Out-Null
$UserName = $Username + ++$i
Continue
}
Catch {
Break
}
} While ($True)
New code that works.
#Check username does not exist, if it does add numbers
$UniqueUserName = $Username
while (Get-ADUser -Filter "SamAccountName -like '$UniqueUserName'"){
$UniqueUserName = $Username + ++$i
}
add a comment |
Figured it out with the help of Reddit. I needed to replace my current code.
Do {
Try {
Get-ADUser $UserName | Out-Null
$UserName = $Username + ++$i
Continue
}
Catch {
Break
}
} While ($True)
New code that works.
#Check username does not exist, if it does add numbers
$UniqueUserName = $Username
while (Get-ADUser -Filter "SamAccountName -like '$UniqueUserName'"){
$UniqueUserName = $Username + ++$i
}
Figured it out with the help of Reddit. I needed to replace my current code.
Do {
Try {
Get-ADUser $UserName | Out-Null
$UserName = $Username + ++$i
Continue
}
Catch {
Break
}
} While ($True)
New code that works.
#Check username does not exist, if it does add numbers
$UniqueUserName = $Username
while (Get-ADUser -Filter "SamAccountName -like '$UniqueUserName'"){
$UniqueUserName = $Username + ++$i
}
edited Nov 13 '18 at 21:04
mklement0
129k20243275
129k20243275
answered Nov 13 '18 at 20:13
Austin DowningAustin Downing
442
442
add a comment |
add a comment |
Because you iteratively modified $UserName
in your loop, you ended up appending an additional number in each iteration:
$UserName = $Username + ++$i
With BTFollow
as the original value, the value is BTFollow1
after the first iteration, and in the second iteration you then append 2
to that, resulting in BTFollow12
, and so on.
Your own answer works (though -like
should be replaced with -eq
) and, given its appealing concision and the presumed relative rarity of duplicate names, is probably the way to go.
The following solution provides optimizations, but the required complexity may not be worth it; at least I hope it showcases some interesting techniques.
You can avoid a costly loop around Get-AdUser
altogether, by pre-filtering potential duplicates with Get-ADUser -Filter
and then processing the candidates locally:
$highestIndexSoFar = (
Get-ADUser -Filter "SamAccountName -like '$UserName*'" |
ForEach-Object {
if ($_.SamAccountName -match "^$UserName(d*)`$") { [int] $Matches[1] }
} |
Sort-Object -Descending
)[0]
if ($null -eq $highestIndexSoFar) { # no duplicates -> use as-is
$UniqueUserName = $UserName
} else { # increment the highest index to date to make the username unique
$UniqueUserName = $UserName + (1 + $highestIndexSoFar)
}
Note: If there's a chance that $UserName
contains chars. with special meaning in a regex, construct the regex as follows:('^' + [regex]::Escape($UserName) + '(d*)$')
Another advantage of the above solution is that it determines the highest number suffix in the actual names, which reliably uses a new suffix that is the highest to date + 1, whereas the call-Get-AdUser
-in-a-loop approach uses the first index that isn't taken (though that would only be a concern if users got deleted over time or if out-of-sequence suffixes were manually created).
Get-ADUser -Filter "SamAccountName -like '$UserName*'"
retrieves potential duplicates; the-Filter
syntax isn't sophisticated enough to allow regex-based matching, so this pre-filtering can only find all usernames that share the same prefix, which may include false positives (e.g.,jdoet
forjdoe
, whereas only a numeric suffix such asjdoe1
should be considered).Regex
"^$UserName(d*)
$"is then used to weed out such false positives, and the actual numeric suffix (
d*) is reflected in the automatic
$Matchesvariable's
[1]entry, what the 1st (and only) capture group (
(...)` in the regex captured.
The numeric suffix, if present or empty, is then cast to
[int]
and output.
- Note that an initially unindexed username such as
BTFollow
will cause$Matches[1]
to be the empty string, which[int]
converts to0
, so the first index appended will be1
.
- Note that an initially unindexed username such as
Sort-Object -Descending
sorts the resulting numbers in descending order, and index[0]
of the sorted array therefore contains the highest suffix number found.If no matches are found at all, i.e. if the username isn't taken yet, the array is empty, and index
[0]
yields$null
; otherwise,1
must be added to highest number to form the new unique username.
Caveat: This approach may still fail if others are creating users simultaneously.
add a comment |
Because you iteratively modified $UserName
in your loop, you ended up appending an additional number in each iteration:
$UserName = $Username + ++$i
With BTFollow
as the original value, the value is BTFollow1
after the first iteration, and in the second iteration you then append 2
to that, resulting in BTFollow12
, and so on.
Your own answer works (though -like
should be replaced with -eq
) and, given its appealing concision and the presumed relative rarity of duplicate names, is probably the way to go.
The following solution provides optimizations, but the required complexity may not be worth it; at least I hope it showcases some interesting techniques.
You can avoid a costly loop around Get-AdUser
altogether, by pre-filtering potential duplicates with Get-ADUser -Filter
and then processing the candidates locally:
$highestIndexSoFar = (
Get-ADUser -Filter "SamAccountName -like '$UserName*'" |
ForEach-Object {
if ($_.SamAccountName -match "^$UserName(d*)`$") { [int] $Matches[1] }
} |
Sort-Object -Descending
)[0]
if ($null -eq $highestIndexSoFar) { # no duplicates -> use as-is
$UniqueUserName = $UserName
} else { # increment the highest index to date to make the username unique
$UniqueUserName = $UserName + (1 + $highestIndexSoFar)
}
Note: If there's a chance that $UserName
contains chars. with special meaning in a regex, construct the regex as follows:('^' + [regex]::Escape($UserName) + '(d*)$')
Another advantage of the above solution is that it determines the highest number suffix in the actual names, which reliably uses a new suffix that is the highest to date + 1, whereas the call-Get-AdUser
-in-a-loop approach uses the first index that isn't taken (though that would only be a concern if users got deleted over time or if out-of-sequence suffixes were manually created).
Get-ADUser -Filter "SamAccountName -like '$UserName*'"
retrieves potential duplicates; the-Filter
syntax isn't sophisticated enough to allow regex-based matching, so this pre-filtering can only find all usernames that share the same prefix, which may include false positives (e.g.,jdoet
forjdoe
, whereas only a numeric suffix such asjdoe1
should be considered).Regex
"^$UserName(d*)
$"is then used to weed out such false positives, and the actual numeric suffix (
d*) is reflected in the automatic
$Matchesvariable's
[1]entry, what the 1st (and only) capture group (
(...)` in the regex captured.
The numeric suffix, if present or empty, is then cast to
[int]
and output.
- Note that an initially unindexed username such as
BTFollow
will cause$Matches[1]
to be the empty string, which[int]
converts to0
, so the first index appended will be1
.
- Note that an initially unindexed username such as
Sort-Object -Descending
sorts the resulting numbers in descending order, and index[0]
of the sorted array therefore contains the highest suffix number found.If no matches are found at all, i.e. if the username isn't taken yet, the array is empty, and index
[0]
yields$null
; otherwise,1
must be added to highest number to form the new unique username.
Caveat: This approach may still fail if others are creating users simultaneously.
add a comment |
Because you iteratively modified $UserName
in your loop, you ended up appending an additional number in each iteration:
$UserName = $Username + ++$i
With BTFollow
as the original value, the value is BTFollow1
after the first iteration, and in the second iteration you then append 2
to that, resulting in BTFollow12
, and so on.
Your own answer works (though -like
should be replaced with -eq
) and, given its appealing concision and the presumed relative rarity of duplicate names, is probably the way to go.
The following solution provides optimizations, but the required complexity may not be worth it; at least I hope it showcases some interesting techniques.
You can avoid a costly loop around Get-AdUser
altogether, by pre-filtering potential duplicates with Get-ADUser -Filter
and then processing the candidates locally:
$highestIndexSoFar = (
Get-ADUser -Filter "SamAccountName -like '$UserName*'" |
ForEach-Object {
if ($_.SamAccountName -match "^$UserName(d*)`$") { [int] $Matches[1] }
} |
Sort-Object -Descending
)[0]
if ($null -eq $highestIndexSoFar) { # no duplicates -> use as-is
$UniqueUserName = $UserName
} else { # increment the highest index to date to make the username unique
$UniqueUserName = $UserName + (1 + $highestIndexSoFar)
}
Note: If there's a chance that $UserName
contains chars. with special meaning in a regex, construct the regex as follows:('^' + [regex]::Escape($UserName) + '(d*)$')
Another advantage of the above solution is that it determines the highest number suffix in the actual names, which reliably uses a new suffix that is the highest to date + 1, whereas the call-Get-AdUser
-in-a-loop approach uses the first index that isn't taken (though that would only be a concern if users got deleted over time or if out-of-sequence suffixes were manually created).
Get-ADUser -Filter "SamAccountName -like '$UserName*'"
retrieves potential duplicates; the-Filter
syntax isn't sophisticated enough to allow regex-based matching, so this pre-filtering can only find all usernames that share the same prefix, which may include false positives (e.g.,jdoet
forjdoe
, whereas only a numeric suffix such asjdoe1
should be considered).Regex
"^$UserName(d*)
$"is then used to weed out such false positives, and the actual numeric suffix (
d*) is reflected in the automatic
$Matchesvariable's
[1]entry, what the 1st (and only) capture group (
(...)` in the regex captured.
The numeric suffix, if present or empty, is then cast to
[int]
and output.
- Note that an initially unindexed username such as
BTFollow
will cause$Matches[1]
to be the empty string, which[int]
converts to0
, so the first index appended will be1
.
- Note that an initially unindexed username such as
Sort-Object -Descending
sorts the resulting numbers in descending order, and index[0]
of the sorted array therefore contains the highest suffix number found.If no matches are found at all, i.e. if the username isn't taken yet, the array is empty, and index
[0]
yields$null
; otherwise,1
must be added to highest number to form the new unique username.
Caveat: This approach may still fail if others are creating users simultaneously.
Because you iteratively modified $UserName
in your loop, you ended up appending an additional number in each iteration:
$UserName = $Username + ++$i
With BTFollow
as the original value, the value is BTFollow1
after the first iteration, and in the second iteration you then append 2
to that, resulting in BTFollow12
, and so on.
Your own answer works (though -like
should be replaced with -eq
) and, given its appealing concision and the presumed relative rarity of duplicate names, is probably the way to go.
The following solution provides optimizations, but the required complexity may not be worth it; at least I hope it showcases some interesting techniques.
You can avoid a costly loop around Get-AdUser
altogether, by pre-filtering potential duplicates with Get-ADUser -Filter
and then processing the candidates locally:
$highestIndexSoFar = (
Get-ADUser -Filter "SamAccountName -like '$UserName*'" |
ForEach-Object {
if ($_.SamAccountName -match "^$UserName(d*)`$") { [int] $Matches[1] }
} |
Sort-Object -Descending
)[0]
if ($null -eq $highestIndexSoFar) { # no duplicates -> use as-is
$UniqueUserName = $UserName
} else { # increment the highest index to date to make the username unique
$UniqueUserName = $UserName + (1 + $highestIndexSoFar)
}
Note: If there's a chance that $UserName
contains chars. with special meaning in a regex, construct the regex as follows:('^' + [regex]::Escape($UserName) + '(d*)$')
Another advantage of the above solution is that it determines the highest number suffix in the actual names, which reliably uses a new suffix that is the highest to date + 1, whereas the call-Get-AdUser
-in-a-loop approach uses the first index that isn't taken (though that would only be a concern if users got deleted over time or if out-of-sequence suffixes were manually created).
Get-ADUser -Filter "SamAccountName -like '$UserName*'"
retrieves potential duplicates; the-Filter
syntax isn't sophisticated enough to allow regex-based matching, so this pre-filtering can only find all usernames that share the same prefix, which may include false positives (e.g.,jdoet
forjdoe
, whereas only a numeric suffix such asjdoe1
should be considered).Regex
"^$UserName(d*)
$"is then used to weed out such false positives, and the actual numeric suffix (
d*) is reflected in the automatic
$Matchesvariable's
[1]entry, what the 1st (and only) capture group (
(...)` in the regex captured.
The numeric suffix, if present or empty, is then cast to
[int]
and output.
- Note that an initially unindexed username such as
BTFollow
will cause$Matches[1]
to be the empty string, which[int]
converts to0
, so the first index appended will be1
.
- Note that an initially unindexed username such as
Sort-Object -Descending
sorts the resulting numbers in descending order, and index[0]
of the sorted array therefore contains the highest suffix number found.If no matches are found at all, i.e. if the username isn't taken yet, the array is empty, and index
[0]
yields$null
; otherwise,1
must be added to highest number to form the new unique username.
Caveat: This approach may still fail if others are creating users simultaneously.
edited Nov 15 '18 at 3:07
answered Nov 13 '18 at 20:03
mklement0mklement0
129k20243275
129k20243275
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287794%2ftrying-to-create-a-powershell-user-creation-script-want-to-append-number-to-use%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
take a look at the 1st answer here ... active directory - Powershell AD Script - Add a number onto the end of account Name - Stack Overflow — stackoverflow.com/questions/50694247/…
– Lee_Dailey
Nov 13 '18 at 19:18
That did not work at all.
– Austin Downing
Nov 13 '18 at 19:43
As for "I want my parameters to show what comes after Read-Host but that text is not appearing only the variable name": It's an interesting problem, but please ask in it in a new, separate question.
– mklement0
Nov 13 '18 at 20:17
@AustinDowning - this line
$SamAccountName = $defaultname + [string]$i
sure seems to work. i guess we must be thinking of different things. however, your answer below sure looks similar ... [grin]– Lee_Dailey
Nov 13 '18 at 22:53