Creating Local Users

I’m helping some of our test teams more and more.  In one case, we need to create local users in bulk.

I’m surprised PSH doesn’t have something for this. 

 function New-LocalUser
{
    <#
    .syopsis
    Creates a local user account

    .parameter UserName
    Username of local user to be created. Ignored if -Credential specified.  
    Legal username characters are A-Z, a-z, 0-9, _, and - characters.
    If length is greater than 15, it will be truncated to 15 characters.
    Defaults to [DateTime].ToString('_yyyyMMddHHmmss').

    If username already exists on local machine, script will generate a warning.

    .parameter Password
    Password for local user to be created.  Ignored if -Credential specified.
    Legal password characters are [char]33 until [char]126.
    If length is less than 8, function will stop.
    Defaults to randomly generated string of length specified by -PasswordLength.

    .parameter FullName
    String to populate "Full Name" property.  "Description" property will be populated with "$FullName (Created [DateTime])";
    Defaults to "Test User."
    
    .parameter PasswordLength
    Auto-generated password length.  Ignored if -Credential specified.  
    Defaults to 24 characters.

    .parameter Credential
    PSCredential to add to local computer.

    .parameter IsAdministrator
    Add specified user to the local administrators group.

    .inputs
    None

    .outputs
    PSCredential

    .links
    https://gallery.technet.microsoft.com/scriptcenter/504cf1a7-c5e3-4a8f-b734-488b90a5965b
    https://blogs.technet.com/b/heyscriptingguy/archive/2008/05/22/how-can-i-use-windows-powershell-to-determine-whether-a-local-user-account-exists.aspx
    #>

    param (
        [string]$UserName = $null,
        [string]$Password = $null,
        [string]$FullName = "Test User",
        [int]$PasswordLength = 24,
        [System.Management.Automation.PSCredential]$Credential = $null,
        [switch]$IsAdministrator
    );

    $timeStamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss';

    # get / create password
    if ($Credential)
    {
        $UserName = $Credential.UserName;
        $Password = [System.Runtime.InteropServices.marshal]::PtrToStringAuto(
            [System.Runtime.InteropServices.marshal]::SecureStringToBSTR($Credential.Password)
        );

    } # if ($Credential)

    if (!$Password)
    {
        $rand = New-Object System.Random;
        1..$PasswordLength | 
            ForEach-Object -begin { $Password = $null; } -process { $Password = $Password + [char]$rand.next(33,127); } 

    } # if (!$Password)

    if ($Password.Length -lt 8)
    {
        Write-Warning "$($MyInvocation.MyCommand.Name) supplied password must e at least 8 characters long.  Stopping";
        return;

    } # if ($Password.Length -lt 8)

    $securePass = ConvertTo-SecureString -AsPlainText $password -Force;

    # get / create username (note: -Credential if test above gets username 

    if (!$UserName) { $userName = "_$($timeStamp -replace '\D')"; }
    $UserName = $UserName -replace "[^\w-]";

    if ($UserName.Length -gt 15) { $UserName = $UserName.Substring(0,15); }

    $adsiComputerObject = [ADSI]("WinNT://$env:ComputerName,computer") 
    
    if (
        $adsiComputerObject.Children |
        ? { 
            $_.SchemaClassName -eq 'User' -and
            $_.Name -eq $UserName
        } 
    )
    {
        Write-Warning "$($MyInvocation.MyCommand.Name) -UserName '$UserName' exists.";
    
    } # if ($adsiComputerObject.Children ...
    else
    {
        $localAdminGroup = $adsiComputerObject.Children |
            ? { ($_.SchemaClassName -eq 'User') -and ($_.Name -eq 'Administrator'); } |
            Select-Object -First 1;
        & {
            $userObject = $adsiComputerObject.Create("User", $UserName);
            $userObject.SetPassword($Password);
            $userObject.Put("Description", "$FullName (Created $timeStamp)");
            $userObject.Put("FullName", "$FullName");
            $userObject.SetInfo();
        } | Out-Null
         
    } # if ($adsiComputerObject.Children ... else

    if ($IsAdministrator) { ([ADSI]"WinNT://$Env:ComputerName/Administrators,group").Add("WinNT://$UserName"); }

    New-Object System.Management.Automation.PSCredential $Username, $SecurePass; 

} # function New-LocalUser