asotelo
asotelo

Reputation: 3

Filter Get-ADComputer where "Name -notlike" in Powershell

My goal is to get a list of AD computer objects not following naming conventions with the whenCreated property. I am trying to export out a HTML file using the following PowerShell function:

function get_bad_names
{
$result = Get-ADComputer -searchbase $OU
-Filter {Name -notlike 'name1' -and 
         Name -notlike 'name2' -and
         Name -notlike 'name3'} 
-Properties whenCreated | sort whenCreated

$result | ConvertTo-Html | Out-File $dir\badnames.html
}

get_bad_names

Is there a more elegant way of structuring the Name filter lines? We have over 40 lines of different "names." In other words, over 40 lines in my script say Name -notlike 'name#' -and

Ideally I'd like for the code to read from a text file and export out the same results.

FYI: this function works but it is not ideally written. Any suggestions would be appreciated.

Upvotes: 0

Views: 5119

Answers (4)

asotelo
asotelo

Reputation: 3

Thank you to everyone for their feedback. I was impressed how fast the responses were.

I was able to achieve my goal using regular expressions reading from a text file.

My code now looks like this:

[regex]$Expression = Get-Content $dir\regex.txt

function get_bad_names
{
$result = Get-ADComputer -searchbase $OU 
-Filter {Enabled -eq $true} 
-Properties whenCreated | Where-Object {$_.Name -notmatch $Expression}| sort whenCreated

$result | ConvertTo-Html | Out-File $dir\badnames.html
}

get_bad_names

Upvotes: 0

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174475

If you'd like to filter the query, construct an LDAP filter:

# Define the names to exclude
$NamesToExclude = "Name1","Name2","Name3"
# Turn them into LDAP clauses in the form of "(!(Name=Name1))"
$LDAPClauses = $NamesToExclude |ForEach-Object {
    '(!(Name={0}))' -f $_
}
# Create a single query filter string with all the clauses from above
$LDAPFilter = "(&$LDAPClauses)"

$result = Get-ADComputer -LDAPFilter $LDAPFilter -SearchBase $OU -Properties whenCreated |Sort-Object whenCreated

Upvotes: 1

Bacon Bits
Bacon Bits

Reputation: 32155

Is there a more elegant way of structuring the Name filter lines?

Not exactly. You have a fairly limited set of operators when you use the -Filter parameter of commands in the ActiveDirectory module because it has to translate them all to LDAP filters.

However, you can do something like this:

$ExcludedPatterns = 'Name1', 'Name2', 'Name3'
$ComputerFilter = foreach ($Pattern in $ExcludedPatterns) { "(Name -notlike '$Pattern')" }
$ComputerFilter = $ComputerFilter -join ' -and '
Get-ADComputer -Filter $ComputerFilter

Now you can maintain a list of name patterns.

Keep in mind that the -Filter property is not a ScriptBlock on the ActiveDirectory commands. They're all Strings and in spite of the documentation for these commands they should be written that way. Writing them as ScriptBlocks will eventually cause you problems with variable expansion.

Compare:

$ComputerName = hostname
Get-ADComputer -Filter "Name -eq '$ComputerName'"
Get-ADComputer -Filter { Name -eq '$ComputerName' }

Upvotes: 0

Janne Tuukkanen
Janne Tuukkanen

Reputation: 1660

You could filter with a regular expression using Select-Object but then you should get all computers in the OU with the -filter *, and that might strain your network. I would do the filtering and if more properties are needed, run Get-Computer again only for the matches:

Get-ADComputer -searchbase $OU -Filter * |
? { $_.name -match "name\d{1,2}" } | # Match if string "name" is followed one or two digits
Get-ADComputer -property * # Get all properties for the computers if needed

Upvotes: 0

Related Questions