'Testing if a user exist locally always return false

I'm trying to write a custom powershell script that will create a local user if no user exists with the specified name.

I have this script :

function Ensure-LocalUser
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string] $userName,
        [Parameter(Mandatory=$true)]
        [string] $passWord
    )
    process{

        $objOu = [ADSI]"WinNT://${env:Computername}"
        $localUsers = $objOu.Children | where {$_.SchemaClassName -eq 'user'}  | Select {$_.name[0].ToString()} 

        if($localUsers -NotContains $userName)
        {
            $objUser = $objOU.Create("User", $userName)
            $objUser.setpassword($password)
            $objUser.SetInfo()
            $objUser.description = "CMM Test user"
            $objUser.SetInfo()

            return $true
        }
        else
        {
            return $false
        }

    }
}

The part related to the creation of the user works, but my -NotContains verification always return false. This leads to a failing attempt to create a user because the user already exists. Using a debugger, I can see that $localusers actually contains the username I'm looking for.

How can I correct my script to reach my goal ?



Solution 1:[1]

You're doing it wrong ;) You really want this (which will create an array of strings):

$ou.Children | where {$_.SchemaClassName -eq 'user'}  | foreach {
      $_.name[0].tostring() }

Your code is creating a custom object with a property called "$_.name[0].ToString()"

Solution 2:[2]

In PowerShell 5.1 (available in Windows 10) and later, there are two cmdlets we can use for checking the existence of a local user and creating a new local user: Get-LocalUser and New-LocalUser. So we can rewrite the above function in a more compact way:

function Ensure-LocalUser
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string] $userName,
        [Parameter(Mandatory=$true)]
        [string] $passWord
    )
    process{
        $out = Get-LocalUser -Name $userName -ErrorAction SilentlyContinue
        if($out -eq $null)
        {
            $passEnc = ConvertTo-SecureString -String $passWord -AsPlainText -Force
            New-LocalUser -Name $userName -Password $passEnc -AccountNeverExpires -PasswordNeverExpires
            return $true
        }
        else
        {
            write-host ("User '"+ $userName + "' already exists")
            return $false
        }
    }
}

then call the function like this:

Ensure-LocalUser "john" "p@ssw0rd"

Solution 3:[3]

I know I am late to the party, but here is an easy way to find local users and output their current state.

# Find User Account to change
$usercheck = Get-WmiObject Win32_UserAccount -Filter "LocalAccount='true' and Name='Administrator'"

if($usercheck.disabled -eq $false){write-host "Account has been found"}
elseif($usercheck.disabled -eq $true){write-host "Account has been found, but disabled"}
else{write-host "Account has not been found."}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 x0n
Solution 2 Vlad S.
Solution 3 Danishan