Public/Set-User.ps1
|
function Set-User { <# .SYNOPSIS Changes the properties of a user account. .DESCRIPTION The Set-User cmdlet changes the properties of a user account in the local Windows Security Accounts Manager. It can also reset the password. .PARAMETER InputObject Specifies the local user account to modify. .PARAMETER Name Specifies the local user account to change. .PARAMETER SID Specifies a user from the local Security Accounts Manager by SecurityIdentifier. .PARAMETER Description A descriptive comment for this user account. .PARAMETER FullName Specifies the full name of the user account. .PARAMETER Password Specifies the password for the local user account. .PARAMETER PasswordNeverExpires Specifies that the password will not expire. .PARAMETER UserMayChangePassword Specifies whether the user is allowed to change the password. .PARAMETER AccountExpires Specifies when the user account will expire. .PARAMETER AccountNeverExpires Specifies that the account will not expire. .PARAMETER Visibility Specifies whether the user account is visible on the logon screen. Hidden - User is hidden from the logon screen Visible - User is explicitly visible on the logon screen .PARAMETER Interactive Shows an interactive menu to set user visibility and other properties. .EXAMPLE Set-User -Name "John" -Description "New description" Sets the description for the local user named John. .EXAMPLE Set-User -Name "John" Hidden Hides the local user named John from the logon screen. .EXAMPLE Set-User -Name "John" -Interactive Shows an interactive menu to modify user properties. #> [CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'Name')] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'InputObject')] [LocalUser]$InputObject, [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'Name')] [string]$Name, [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'SecurityIdentifier')] [System.Security.Principal.SecurityIdentifier]$SID, [Parameter(ValueFromPipelineByPropertyName = $true)] [ValidateSet('Hidden', 'Visible', 'Unset')] [string]$Visibility, [Parameter(ValueFromPipelineByPropertyName = $true)] [string]$FullName, [Parameter(ValueFromPipelineByPropertyName = $true)] [System.Security.SecureString]$Password, [Parameter(ValueFromPipelineByPropertyName = $true)] [string]$Description, [Parameter(ValueFromPipelineByPropertyName = $true)] [bool]$PasswordNeverExpires, [Parameter(ValueFromPipelineByPropertyName = $true)] [bool]$UserMayChangePassword = $true, [Parameter(ValueFromPipelineByPropertyName = $true)] [DateTime]$AccountExpires = [DateTime]::MinValue, [Parameter(ValueFromPipelineByPropertyName = $true)] [switch]$AccountNeverExpires, [Parameter(ValueFromPipelineByPropertyName = $true)] [switch]$Interactive, [Parameter()] [switch]$Force ) process { # Handle Interactive mode if ($Interactive) { $visibilityManager = [SpecialAccountHelper]::new() # Get the username to modify $targetUserName = $null if ($null -ne $InputObject) { $targetUserName = $InputObject.Name } elseif ($null -ne $Name) { $targetUserName = $Name } elseif ($null -ne $SID) { # Need to look up the user by SID $foundUser = Get-User -SID $SID -ErrorAction SilentlyContinue if ($foundUser) { $targetUserName = $foundUser.Name } } if ($null -eq $targetUserName) { Write-Error -Message 'Could not determine user name' -ErrorId 'InvalidOperation' -Category InvalidOperation return } # Show interactive menu $visibilityManager.ShowUserList() Write-Host "" Write-Host "Selected user: $targetUserName" -ForegroundColor Cyan Write-Host "" # Prompt for visibility choice Write-Host "Choose visibility option:" -ForegroundColor Yellow Write-Host " [1] Hide user from login screen" Write-Host " [2] Show user on login screen (Visible)" Write-Host " [3] Unset user visibility (restore default system behavior)" Write-Host " [4] Exit without changes" $choice = Read-Host "Select an option (1-4)" switch ($choice) { "1" { if ($PSCmdlet.ShouldProcess($targetUserName, 'Hide user from logon screen')) { $result = $visibilityManager.HideUserAccount($targetUserName, $Force) if ($result) { Write-Host "User '$targetUserName' has been hidden from the login screen." -ForegroundColor Green } } } "2" { if ($PSCmdlet.ShouldProcess($targetUserName, 'Show user on logon screen')) { $result = $visibilityManager.UnhideUserAccount($targetUserName) if ($result) { Write-Host "User '$targetUserName' has been set to visible on the login screen." -ForegroundColor Green } } } "3" { if ($PSCmdlet.ShouldProcess($targetUserName, 'Unset user visibility')) { $result = $visibilityManager.ClearUserVisibility($targetUserName) if ($result) { Write-Host "User '$targetUserName' visibility has been unset (now using default system behavior)." -ForegroundColor Green } } } "4" { Write-Host "No changes made." -ForegroundColor Gray } default { Write-Error -Message 'Invalid option selected' -ErrorId 'InvalidOperation' -Category InvalidArgument } } return } $user = $null if ($null -ne $InputObject) { $user = $InputObject $targetName = $user.ToString() } elseif ($null -ne $Name) { # Check if user exists first $user = [LocalAccountHelper]::GetLocalUserByName($Name) if ($null -eq $user) { $ex = [UserNotFoundException]::new($Name, $Name) Write-Error -Message $ex.Message -ErrorId 'UserNotFound' -Category ObjectNotFound -TargetObject $Name return } $targetName = $Name } elseif ($null -ne $SID) { # Check if user exists first $user = [LocalAccountHelper]::GetLocalUserBySid($SID) if ($null -eq $user) { $ex = [UserNotFoundException]::new($SID.Value, $SID) Write-Error -Message $ex.Message -ErrorId 'UserNotFound' -Category ObjectNotFound -TargetObject $SID return } $targetName = $SID.ToString() } if ($null -eq $user) { return } # Handle visibility parameter if ($PSBoundParameters.ContainsKey('Visibility')) { if ($PSCmdlet.ShouldProcess($targetName, "Set visibility to $Visibility")) { $visibilityManager = [SpecialAccountHelper]::new() if ($Visibility -eq 'Hidden') { $result = $visibilityManager.HideUserAccount($targetName, $Force) if (!$result) { # Check if already hidden $hiddenUsers = [SpecialAccountHelper]::GetHiddenUsersFromRegistry() if ($hiddenUsers.ContainsKey($targetName) -and $hiddenUsers[$targetName] -eq 0) { Write-Warning "User '$targetName' is already hidden from the logon screen." } } } elseif ($Visibility -eq 'Visible') { $result = $visibilityManager.UnhideUserAccount($targetName) if (!$result) { # Check if already visible $hiddenUsers = [SpecialAccountHelper]::GetHiddenUsersFromRegistry() if ($hiddenUsers.ContainsKey($targetName) -and $hiddenUsers[$targetName] -eq 1) { Write-Warning "User '$targetName' is already set to visible on the logon screen." } } } elseif ($Visibility -eq 'Unset') { $result = $visibilityManager.ClearUserVisibility($targetName) if (!$result) { # Check if already unset $hiddenUsers = [SpecialAccountHelper]::GetHiddenUsersFromRegistry() if (!$hiddenUsers.ContainsKey($targetName)) { Write-Warning "User '$targetName' visibility is already unset (using default system visibility)." } } } } } if ($PSCmdlet.ShouldProcess($targetName, 'Set user account')) { try { # 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 $targetName return } [LocalAccountHelper]::SetLocalUser( $user, $Description, $FullName, $Password, $PasswordNeverExpires, $UserMayChangePassword, $AccountExpires, $AccountNeverExpires.IsPresent ) } catch [System.UnauthorizedAccessException] { $ex = [AccessDeniedException]::new($targetName) Write-Error -Message $ex.Message -ErrorId 'AccessDenied' -Category PermissionDenied -TargetObject $targetName } catch { Write-Error -Message $_.Exception.Message -ErrorId 'InvalidLocalUserOperation' -Category InvalidOperation -TargetObject $targetName } } } } |