1

I'm currently programing an administration tool and I could need some help.

I want that every user, starting with "ca" gets imported to the listbox. The Import into the listbox works perfectly fine.

The users I own e.g. are "cambridge", "california" and "call".

$searchuser = "ca"

if(@(Get-ADObject -Filter { sAMAccountname -eq $searchuser }).Count -ge 1){
                Get-ADObject -Filter { sAMAccountname -eq $($searchuser) } | foreach{[void]$lstUsers.Items.Add($_.name)}
                
            } else {

                [System.Windows.Forms.MessageBox]::Show("No user found.","Error",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Warning)

            }

If I put a single username into the variable it works without any problems but with multiple it doesn't want to work...

Can someone help me out a little?

mklement0
  • 382,024
  • 64
  • 607
  • 775
yonig
  • 63
  • 7

3 Answers3

1

tl;dr

# Note the '*' to make the search term a wildcard expression.
$searchuser = 'ca*' 

# ...

# Note the use of Get-AdUser and the use of the -like operator.
Get-ADUser -Filter 'sAMAccountname -like $searchuser'

See AdminOfThings' helpful answer for more detailed information on the need for using wildcard patterns combined with the -like operator instead of -eq, and using an LDAP filter as an alternative.

The rest of this answer focuses on the -Filter syntax:


To solve the fundamental problem, replace

-Filter { sAMAccountname -eq $($searchuser) }

with

-Filter 'sAMAccountname -eq $searchuser'

or, using an expandable string ("...")[1] (as suggested by Mathias R. Jessen):

-Filter "sAMAccountname -eq `"$searchuser`""

While seductively convenient, the use of script blocks ({ ... }) as -Filter arguments is conceptually problematic and can lead to misconceptions - such, as in your case, the incorrect expectation that $(...), the subexpression operator can be used.

In short: While -Filter expressions resemble PowerShell expressions, they're strings interpreted by the AD provider, and there are important differences between what those strings support compared to regular PowerShell expressions - see this answer for background information, including how to deal with property-access expressions such as $searchuser.Name.

The additional problems with your code are discussed in AdminOfThings's answer.


[1] That is, variable references are expanded before the resulting string is passed to the AD cmdlet. Note that for the embedded quoting " (escaped as `") is preferable to ', because the search terms themselves may contain ', such as a last name of O'Neal.
Using expandable strings is convenient if you need to use expressions (such as property access, e.g., $searchuser.Name) as part of the filter, but this approach has limitations, notably the inability to embed dates. The generally robust solution is to assign the expression to an auxiliary variable (e.g., $name = $searchuser.Name) and reference that inside a single-quoted string; e.g., 'sAMAccountname -eq $name'

mklement0
  • 382,024
  • 64
  • 607
  • 775
1

The -eq operator is for exact matches rather than partial/substring matches. -like operator is supported in the -Filter parameter and can be used for partial matching. You will need to add your own wildcarding (via *) for the partial match to work.

If you only need to search users, I would opt for Get-ADUser instead.

$searchuser = 'ca*'
Get-ADUser -Filter 'samaccountname -like $searchuser'

Sometimes, -LDAPFilter is more efficient for the machine running the query and can be used in this scenario:

$searchuser = 'ca*'
Get-ADUser -LDAPFilter "(samaccountname=$searchuser)"

Your if statement logic may be impacting your code completion times depending on how long it takes the command to return results. This is because you are running the same query twice. You could opt for storing the command results into a variable first provided it won't cause memory constraints on your system.

$searchuser = 'ca*'
$users = Get-ADUser -Filter 'samaccountname -like $searchuser'
if ($users) {
    # add users to your list
}

The -Filter value is treated as a string. There's no good reason to ever use a script block ({} notation) for the filter value. It can be tricky at times using complex values. PowerShell parses the initial command and does its variable substitutions. Then the Get-AD* command runs and another layer of parsing happens. This creates some confusion for handling quoting for the filter value. See below for examples:

# When using simple variables, you can simply use single quotes
Get-ADUser -Filter 'samaccountname -like $searchuser'

# When using variable property references or strings, use outer double quotes and single inner quotes
# If the string contains apostrophe, it will need to be escaped
# This syntax also works for simple variables
Get-ADUser -Filter "samaccountname -like '$($searchuser.SamAccountName)'"
Get-ADUser -Filter "samaccountname -like 'ca*'"

See mklement0's answer for in-depth detail on how -Filter works in the AD cmdlets.

AdminOfThings
  • 23,946
  • 4
  • 17
  • 27
0
Get-ADObject -LDAPFilter:"(anr=CA)" -Properties:allowedChildClassesEffective,allowedChildClasses,lastKnownParent,sAMAccountType,systemFlags,userAccountControl,displayName,description,whenChanged,location,managedBy,memberOf,primaryGroupID,objectSid,msDS-User-Account-Control-Computed,sAMAccountName,lastLogonTimestamp,lastLogoff,mail,accountExpires,msDS-PhoneticCompanyName,msDS-PhoneticDepartment,msDS-PhoneticDisplayName,msDS-PhoneticFirstName,msDS-PhoneticLastName,pwdLastSet,operatingSystem,operatingSystemServicePack,operatingSystemVersion,telephoneNumber,physicalDeliveryOfficeName,department,company,manager,dNSHostName,groupType,c,l,employeeID,givenName,sn,title,st,postalCode,managedBy,userPrincipalName,isDeleted,msDS-PasswordSettingsPrecedence -ResultPageSize:"100" -ResultSetSize:"20201" -SearchScope:"Subtree" 

Super extra, I know:)

Not really the answer but, wanted to show how much can be included when querying.

Abraham Zinala
  • 4,267
  • 3
  • 9
  • 24