2

Related to this fantastic answer about how to properly construct a -Filter parameter argument, I'm working on a script that makes heavy use of the Active Directory cmdlets in PowerShell, and am having difficulty constructing filter arguments containing the property of an object variable.

The script basically manages distribution groups by reading in spreadsheet and processing each row as appropriate - creating Active Directory contacts if they don't exist, adding or removing them to the appropriate group and so on.

The spreadsheet is stored in an object array, with each row being treated as an object, with the columns defining the object properties.

For example, the below code takes each row of the imported spreadsheet and attempts to find a matching contact object in Active Directory.

Foreach ($contact in $NOClist)
{
     $contactobject = Get-ADObject -filter ("name -eq `"$contact.name`" -and Objectclass -eq `"contact`"") -SearchBase "$NOCContactPath" -Server $ADServer;
     #... do some more stuff.
}

The problem is that $contact.name is being evaluated literally, so it ends up searching for a contact in Active Directory with a name property that's literally $contact.name. I've tried the other variations in the previously referenced answer, (""$contact.name"", '$contact.name' and "' + $contact.name + '"), but they all either evaluate to the literal $contact.name or throw a syntax error on the . character.

The hacky workaround I've come up with is to assign the object property to a variable and use that instead, such as the below, but that just feels terrible.

Foreach ($contact in $NOClist)
{
    $contactname = $contact.name; 
    $contactobject = Get-ADObject -filter ("name -eq `"$contactname`" -and Objectclass -eq `"contact`"") -SearchBase "$NOCContactPath" -Server $ADServer;
     #... do some more stuff.
}

Is there a way to reference an object property inside the filter argument, or is this workaround of assigning it to a variable and then using the variable really the best approach?

HopelessN00b
  • 452
  • 2
  • 8
  • 22

2 Answers2

5

PowerShell does only simple variable expansion in strings, no complex stuff like index or dot-property access. There are several ways to deal with this limitation, e.g.

  • concatenation:

    -Filter ("name -eq '" + $contact.name + "' -and Objectclass -eq 'contact'")
    
  • subexpressions:

    -Filter "name -eq '$($contact.name)' -and Objectclass -eq 'contact'"
    
  • the format operator:

    -Filter ("name -eq '{0}' -and Objectclass -eq 'contact'" -f $contact.name)
    

Note that for the first and third approach you need to put the operation in a grouping expression (i.e. in parentheses), so that the result of that operation is passed to the parameter.

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • Ah, that would explain it. I’ll verify when I get home, thank you! – HopelessN00b Jan 17 '18 at 23:10
  • Plus-1, better answer than mine! – mfinni Jan 18 '18 at 00:08
  • Related followup... using the subexpression method, if I run into a contact with an apostrophe in the name, I get a syntax error, whereas the hacky assign-to-a-variable-first method doesn't. Is there a particularly good way to handle that case using the subexpression method? – HopelessN00b Jan 18 '18 at 14:32
  • If there's a possibility that a value might contain single quotes the best solution is probably to use escaped double quotes instead of single quotes inside the string (``"name -eq `"$($contact.name)`" -and Objectclass -eq 'contact'"``). – Ansgar Wiechers Jan 18 '18 at 16:05
1

First, are you sure that $contact.name is valid within that that loop? For debug purposes, throw a write-host in there to make sure it's what you think it should be.

But the major thing is that you're using single-quotes around the variable, which blocks variable expansion. It looks like you're trying to escape the double-quotes, not sure if that's possible but if it is, that's not the right way to do it. You should be shooting for this from the link:

Get-ADUser -Filter ('sAMAccountName -eq "' + $SamAc + '"')

Example for me:

PS V:> $contactname = "finn2617"

PS V:> Get-ADuser -filter ('samaccountname -eq "' + $contactname + '"' ) | select name, samaccountname

name samaccountname

---- --------------

Finnigan, Matthew FINN2617

So, for you:

$contactobject = Get-ADObject -filter ('name -eq `"' + $contact.name + " -and Objectclass -eq "contact" ' ) -SearchBase "$NOCContactPath" -Server $ADServer;
mfinni
  • 65
  • 1
  • 17
  • I’m sure it’s valid, yes... which I verified by doing the very debug you suggested. ...and those are all double quotes. The set around the variable are escaped with a backtick, not a single quote, if that’s what you’re seeing. – HopelessN00b Jan 17 '18 at 23:08
  • Aha then. My final answer gets to the same place as the other answer, but their reasoning and explanation is much better than mine. – mfinni Jan 17 '18 at 23:51
  • This works too, now that I try it again... not sure why it wasn't working before, but I think I'm going to go the subexpression route... feels a bit easier than worring about properly escaping and nesting a bunch of quote characters. – HopelessN00b Jan 18 '18 at 14:06