Public/New-User.ps1

function New-User {
  <#
  .SYNOPSIS
    Creates a new local user account.
  .DESCRIPTION
    The New-User cmdlet creates a new local user account.
  .PARAMETER Name
    Specifies the user name for the local user account.
  .PARAMETER Password
    Specifies the password for the local user account.
  .PARAMETER Description
    A descriptive comment for this user account.
  .PARAMETER FullName
    Specifies the full name of the user account.
  .PARAMETER Disabled
    Specifies whether this user account is enabled or disabled.
  .PARAMETER PasswordNeverExpires
    Specifies that the password will not expire.
  .PARAMETER UserMayNotChangePassword
    Specifies whether the user is allowed to change the password.
  .PARAMETER NoPassword
    Specifies that the new user account has no password.
  .PARAMETER AccountExpires
    Specifies when the user account will expire.
  .PARAMETER AccountNeverExpires
    Specifies that the account will not expire.
  .EXAMPLE
    New-User -Name "John" -Password (ConvertTo-SecureString "P@ssw0rd!" -AsPlainText -Force)
    Creates a new local user named John with the specified password.
  #>

  [CmdletBinding(DefaultParameterSetName = 'Password', SupportsShouldProcess = $true)]
  param(
    [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    [ValidateNotNullOrEmpty()]
    [ValidateLength(1, 20)]
    [string]$Name,

    [Parameter(Mandatory = $true, ParameterSetName = 'Password', ValueFromPipelineByPropertyName = $true)]
    [ValidateNotNull()]
    [System.Security.SecureString]$Password,

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [string]$Description,

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [string]$FullName,

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [switch]$Disabled,

    [Parameter(ParameterSetName = 'Password')]
    [switch]$PasswordNeverExpires,

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [switch]$UserMayNotChangePassword,

    [Parameter(Mandatory = $true, ParameterSetName = 'NoPassword')]
    [switch]$NoPassword,

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [DateTime]$AccountExpires = [DateTime]::MinValue,

    [Parameter(ValueFromPipelineByPropertyName = $true)]
    [switch]$AccountNeverExpires
  )

  process {
    try {
      if ($PSCmdlet.ShouldProcess($Name, 'Create user account')) {
        # Check for conflicting parameters
        if ($PSBoundParameters.ContainsKey('AccountExpires') -and $AccountNeverExpires) {
          $ex = [InvalidParametersException]::new('AccountExpires', 'AccountNeverExpires')
          Write-Error -Message $ex.Message -ErrorId 'InvalidParameters' -Category InvalidArgument -TargetObject $Name
          return
        }

        $user = [LocalAccountHelper]::NewLocalUser(
          $Name,
          $Password,
          $Description,
          $FullName,
          $Disabled.IsPresent,
          $PasswordNeverExpires.IsPresent,
          $UserMayNotChangePassword.IsPresent,
          $NoPassword.IsPresent,
          $AccountExpires,
          $AccountNeverExpires.IsPresent
        )

        $user
      }
    } catch [System.DirectoryServices.AccountManagement.PrincipalExistsException] {
      $ex = [UserExistsException]::new($Name, $Name, $_.Exception)
      Write-Error -Message $ex.Message -ErrorId 'UserExists' -Category ResourceExists -TargetObject $Name
    } catch [System.DirectoryServices.AccountManagement.PasswordException] {
      $ex = [InvalidPasswordException]::new('The password is invalid.')
      Write-Error -Message $ex.Message -ErrorId 'InvalidPassword' -Category InvalidData -TargetObject $Password
    } catch [System.UnauthorizedAccessException] {
      $ex = [AccessDeniedException]::new($Name)
      Write-Error -Message $ex.Message -ErrorId 'AccessDenied' -Category PermissionDenied -TargetObject $Name
    } catch {
      # Check if this is a duplicate user error
      if ($_.Exception.Message -match 'already exists' -or 
          $_.Exception.Message -match 'The specified account already exists' -or
          $_.Exception.Message -match 'The user already exists') {
        $ex = [UserExistsException]::new($Name, $Name, $_.Exception)
        Write-Error -Message $ex.Message -ErrorId 'UserExists' -Category ResourceExists -TargetObject $Name
      } else {
        Write-Error -Message $_.Exception.Message -ErrorId 'InvalidLocalUserOperation' -Category InvalidOperation -TargetObject $Name
      }
    }
  }
}