Trying to create a powershell user creation script, want to append number to username if it already exists












1















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"









share|improve this question























  • 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
















1















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"









share|improve this question























  • 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














1












1








1








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"









share|improve this question














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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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



















  • 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












2 Answers
2






active

oldest

votes


















2














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
}





share|improve this answer

































    2














    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 for jdoe, whereas only a numeric suffix such as jdoe1 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 to 0, so the first index appended will be 1.



    • 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.






    share|improve this answer

























      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
      });


      }
      });














      draft saved

      draft discarded


















      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









      2














      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
      }





      share|improve this answer






























        2














        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
        }





        share|improve this answer




























          2












          2








          2







          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
          }





          share|improve this answer















          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
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 13 '18 at 21:04









          mklement0

          129k20243275




          129k20243275










          answered Nov 13 '18 at 20:13









          Austin DowningAustin Downing

          442




          442

























              2














              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 for jdoe, whereas only a numeric suffix such as jdoe1 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 to 0, so the first index appended will be 1.



              • 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.






              share|improve this answer






























                2














                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 for jdoe, whereas only a numeric suffix such as jdoe1 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 to 0, so the first index appended will be 1.



                • 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.






                share|improve this answer




























                  2












                  2








                  2







                  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 for jdoe, whereas only a numeric suffix such as jdoe1 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 to 0, so the first index appended will be 1.



                  • 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.






                  share|improve this answer















                  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 for jdoe, whereas only a numeric suffix such as jdoe1 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 to 0, so the first index appended will be 1.



                  • 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.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 15 '18 at 3:07

























                  answered Nov 13 '18 at 20:03









                  mklement0mklement0

                  129k20243275




                  129k20243275






























                      draft saved

                      draft discarded




















































                      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.




                      draft saved


                      draft discarded














                      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





















































                      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







                      Popular posts from this blog

                      Florida Star v. B. J. F.

                      Danny Elfman

                      Retrieve a Users Dashboard in Tumblr with R and TumblR. Oauth Issues