#Requires -Version 5.1 [CmdletBinding(SupportsShouldProcess)] param() $ErrorActionPreference = 'Stop' $userName = 'alumno' $plainTextPassword = 'ingenieria' $description = 'Cuenta local estandar SGU para recuperacion' $passwordNeverExpiresFlag = 0x10000 function Get-LocalUserFlags { param([Parameter(Mandatory)][string]$Name) $directoryEntry = [ADSI]("WinNT://$env:COMPUTERNAME/$Name,user") return [int]$directoryEntry.InvokeGet('UserFlags') } function Get-LocalGroupMemberSid { param([Parameter(Mandatory)][string]$Name) $group = [ADSI]("WinNT://$env:COMPUTERNAME/$Name,group") foreach ($member in @($group.psbase.Invoke('Members'))) { try { $sidBytes = $member.GetType().InvokeMember( 'objectSid', [Reflection.BindingFlags]::GetProperty, $null, $member, $null) if ($sidBytes) { ([Security.Principal.SecurityIdentifier]::new([byte[]]$sidBytes, 0)).Value } } catch { # An orphaned domain SID can no longer resolve after a forest is # rebuilt. Other members must remain inspectable and unchanged. } } } $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = [Security.Principal.WindowsPrincipal]::new($identity) if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'Run this script from an elevated Windows PowerShell session.' } if (-not $PSCmdlet.ShouldProcess($env:COMPUTERNAME, "Create or update standard local user $userName")) { return } $securePassword = ConvertTo-SecureString $plainTextPassword -AsPlainText -Force try { $user = Get-LocalUser -Name $userName -ErrorAction SilentlyContinue if ($user -and $user.SID.Value.EndsWith('-500', [StringComparison]::Ordinal)) { throw "The local account '$userName' is the built-in Administrator account and cannot be converted to a standard user." } if ($user) { # Preserve existing credentials on enrollment/repair. Resetting the same # password after domain join can violate password history/complexity. Set-LocalUser -Name $userName ` -PasswordNeverExpires $true ` -Description $description if (-not $user.Enabled) { Enable-LocalUser -Name $userName } } else { New-LocalUser -Name $userName ` -Password $securePassword ` -PasswordNeverExpires ` -Description $description | Out-Null } # Windows 10's Get-LocalUser object has PasswordExpires but does not expose # PasswordNeverExpires. Enforce and verify the underlying UF_DONT_EXPIRE_PASSWD # flag so the result is consistent across Windows 10 and Windows 11. $directoryEntry = [ADSI]("WinNT://$env:COMPUTERNAME/$userName,user") $userFlags = [int]$directoryEntry.InvokeGet('UserFlags') if (($userFlags -band $passwordNeverExpiresFlag) -eq 0) { $directoryEntry.InvokeSet('UserFlags', ($userFlags -bor $passwordNeverExpiresFlag)) $directoryEntry.CommitChanges() } $user = Get-LocalUser -Name $userName -ErrorAction Stop $administratorsSid = [Security.Principal.SecurityIdentifier]::new('S-1-5-32-544') $usersSid = [Security.Principal.SecurityIdentifier]::new('S-1-5-32-545') $administratorsGroup = Get-LocalGroup -SID $administratorsSid -ErrorAction Stop $usersGroup = Get-LocalGroup -SID $usersSid -ErrorAction Stop $administratorMembers = @(Get-LocalGroupMemberSid -Name $administratorsGroup.Name) if ($administratorMembers -contains $user.SID.Value) { ([ADSI]("WinNT://$env:COMPUTERNAME/$($administratorsGroup.Name),group")).Remove( "WinNT://$env:COMPUTERNAME/$userName,user") } $standardMembers = @(Get-LocalGroupMemberSid -Name $usersGroup.Name) if ($standardMembers -notcontains $user.SID.Value) { ([ADSI]("WinNT://$env:COMPUTERNAME/$($usersGroup.Name),group")).Add( "WinNT://$env:COMPUTERNAME/$userName,user") } } finally { $securePassword = $null } $verifiedUser = Get-LocalUser -Name $userName -ErrorAction Stop $verifiedAdministratorsGroup = Get-LocalGroup ` -SID ([Security.Principal.SecurityIdentifier]::new('S-1-5-32-544')) ` -ErrorAction Stop $verifiedUsersGroup = Get-LocalGroup ` -SID ([Security.Principal.SecurityIdentifier]::new('S-1-5-32-545')) ` -ErrorAction Stop $verifiedAdministrators = @(Get-LocalGroupMemberSid -Name $verifiedAdministratorsGroup.Name) $verifiedUsers = @(Get-LocalGroupMemberSid -Name $verifiedUsersGroup.Name) if ($verifiedAdministrators -contains $verifiedUser.SID.Value) { throw "The local account '$userName' still belongs to the local Administrators group." } if ($verifiedUsers -notcontains $verifiedUser.SID.Value) { throw "The local account '$userName' does not belong to the local Users group." } $verifiedPasswordNeverExpires = ((Get-LocalUserFlags -Name $userName) -band $passwordNeverExpiresFlag) -ne 0 if (-not $verifiedPasswordNeverExpires) { throw "The local account '$userName' password is not configured to never expire." } [pscustomobject]@{ UserName = $verifiedUser.Name Enabled = $verifiedUser.Enabled IsAdministrator = $false IsStandardUser = $true PasswordNeverExpires = $verifiedPasswordNeverExpires }