Find a Wildcard Match in an Array with PowerShell

0

I have a list of users I want to do an ActiveDirectory lookup on but I don't want to do a lookup on System accounts that pop into my list. My list I am checking against will have the fullname of user account. I'd like to check against that list using a predictable pattern.

The code I am writing currently looks something like this:

$Usertest = "BUILTIN\Administrator"
$SystemUsers = @(
    'NT AUTHORITY\*',
    'BUILTIN\*',
    'S-*',
    'Everyone'
 )
if ($SystemUsers -contains $UserTest)
{
    Write-Host "$Usertest is a system or deleted account"
}
else
{
    Write-Host "$Usertest exists in Active Directory"
}

Obviously the code above does not work but it does convey what I am trying to accomplish.

cyborgcommando0

Posted 2018-02-22T00:15:03.850

Reputation: 803

Answers

1

Afternoon,

You had a few things wrong with what you were trying to do:

Single Quotes

$SystemUsers = @(
    'NT AUTHORITY\*',
    'BUILTIN\*',
    'S-*',
    'Everyone'
 )

Single quotes are literal strings and arent interperated. In this case, you would be looking for a user called NT Authority\*. By changing these to double quotes - you will start matching patterns. For more information see About Quoting Rules on Microsoft's Documentation website.


Escaping

In PowerShell, the "\" is an escape character. To escape your slashes - double them up:

$SystemUsers = @(
    "NT AUTHORITY\\*",
    "BUILTIN\\*",
    "S-1*",
    "Everyone"
 )

For more information on this - have a look at this question on Stack OverFlow. Also, matching against S-* will give you loads of matches you don't want, try "S-1*". Windows SIDs havent really changed since windows 2000 days so this is a fairly safe thing to do


Loop Through The Array

In short - a string will not compare to an array when using wild cards. This article demonstrates this for you.

The easiest way to compare all items in your array is to loop through the array:

ForEach ($SystemUser in $SystemUsers) { }


Match not Contains

Match is a much better way of matching an item in an array. Microsoft's About Comparison Operators page will give you a jump start, but there's loads more to it than this. Try something like:

ForEach ($SystemUser in $SystemUsers) {
    if ($Usertest -match $SystemUser)
    {
        Write-Host "$Usertest is a system or deleted account"
    }
    else
    {
        Write-Host "$Usertest exists in Active Directory"
    }
}

Putting it all Together

$Usertest = "BUILTIN\Administrator"
$SystemUsers = @(
    "NT AUTHORITY\\*",
    "BUILTIN\\*",
    "S-1*",
    "Everyone"
 )

 ForEach ($SystemUser in $SystemUsers) {
    if ($Usertest -match $SystemUser)
    {
        Write-Host "$Usertest is a system or deleted account"
    }
    else
    {
        Write-Host "$Usertest exists in Active Directory"
    }
 }

This will give you a matching output:

BUILTIN\Administrator exists in Active Directory

BUILTIN\Administrator is a system or deleted account

BUILTIN\Administrator exists in Active Directory

BUILTIN\Administrator exists in Active Directory

...but this only half solves your problem - you only really care if you get a match, let alone 2, 3, or 4. You also don't want to continue testing if you've found a match! Extend it to include a swtch, move the line print to the end, and job done:

$Usertest = "BUILTIN\Administrator"
$SystemUsers = @(
   "NT AUTHORITY\\*",
   "BUILTIN\\*",
   "S-1*",
   "Everyone"
)

$HasUserBeenMatchedYet = $false
    ForEach ($SystemUser in $SystemUsers) {
        if ($Usertest -match $SystemUser) {
            $HasUserBeenMatchedYet = $true
            break
        }
    }

if ($HasUserBeenMatchedYet -eq $true) {
    Write-Host "$Usertest is a system or deleted account"
} else {
    Write-Host "$Usertest exists in Active Directory"
}

BUILTIN\Administrator is a system or deleted account

MyStupidFakeUser exists in Active Directory


BONUS POINTS!

Stick the users to test in an array and loop through those too:

$Usertests = @("MyStupidFakeUser", "NT Authority\Someone")
$SystemUsers = @(
   "NT AUTHORITY\\*",
   "BUILTIN\\*",
   "S-1*",
   "Everyone"
)

ForEach ($UserTest in $userTests) {
    $HasUserBeenMatchedYet = $false
        ForEach ($SystemUser in $SystemUsers) {
            if ($Usertest -match $SystemUser) {
                $HasUserBeenMatchedYet = $true
                break
            }
        }

    if ($HasUserBeenMatchedYet -eq $true) {
        Write-Host "$Usertest is a system or deleted account"
    } else {
        Write-Host "$Usertest exists in Active Directory"
    }
}

...now all you have to do is actually test if they are in AD - have a look at Get-ADUser in PowerShell

Fazer87

Posted 2018-02-22T00:15:03.850

Reputation: 11 177