Last month, in “More Control of Active Directory Groups through PowerShell,” I pondered how you might pick out just the users in the folks group who live in bigfirm.com's Sales OU, and I imagined that you might have tried something like this:
get-adgroupmember folks | get-aduser -searchbase "ou=sales,dc=bigfirm,dc=com"
That would have been a very reasonable guess, given how you've used get-aduser to make up for search-adaccount and get-adgroupmember's limitations. But it doesn't work. Understanding why it doesn't work will make you a more efficient PowerShell user, so let’s take that up this month.
First, let's re-examine an example of the pipeline and get-aduser working well together from last month:
get-adgroupmember folks | get-aduser -pr lastlogondate
That showed you how to get past get-adgroupmember's limitations vis-à-vis user properties. In the above example, the get-adgroupmember cmdlet retrieves all the accounts that are members of the folks group and sends them as AD objects to the get-aduser cmdlet via the pipeline, a concept symbolized by the "|" character. Pipelines let you combine two or more of PowerShell's hundreds or thousands of narrow-focus cmdlets into a "one-liner," a quickly constructed tool that gets useful work done. (If the concept of the pipeline is still unclear, imagine an assembly line with multiple stations. Each cmdlet is a station, like the part of an automobile assembly line where the brakes get installed or where the windshield is affixed.) Here's a three-cmdlet one-liner I used a few months ago that generated a table of locked-out users sorted by how long it had been since they last logged on:
search-adaccount -u -l | sort -pr lastlogondate | ft name,lastlogondate
Here, search-adaccount generated all the locked-out user accounts and passed them as an array of objects to the cmdlet sort, which sorted them according to their lastlogondate, resulting in that same array of objects arranged in a different order, and then passed that to the format-table ( ft) command, which displayed them onscreen in a (somewhat) attractive fashion. The beauty of this is that search-adaccount's author needn't include a -sort option, and neither search-adaccount’s nor sort's author need worry about offering formatted table output. In a nutshell, that's the benefit of a pipeline.
That only worked, however, because PowerShell cmdlets are built to accept—to welcome!—objects from a pipeline as input and usually to generate potentially pipeline-able objects as output. Some cmdlets, however, are more easygoing about using pipeline input than others. Sort pretty much accepts any kind of object, as long it has at least one familiar-looking property such as Name or as long as you tell it what to sort on. Format-table will display anything displayable for objects you give it. But get-aduser is a bit pickier. Look at its Help to see what it expects as an input, and you'll see that it insists that you either invoke it as get-aduser -filter something (as we've been using it) or as get-aduser -identity identifier, which lets you find out about any one object by specifying its SID, samaccountname, objectGUID, or distinguished name (DN). (There's also a third option, -ldapfilter, but we'll ignore it for now.) Get-aduser -identity, then, retrieves only a single user according to SID, logon name, GUID, or DN. The -identity option doesn't take wild cards! That being said, -identity makes perfect sense when you realize that it's there to make get-aduser a good consumer of information proffered by a pipeline. A closer look at get-aduser's Help shows that if you invoke get-aduser without -identity, -filter, or -ldapfilter, the cmdlet assumes that you want -identity. Thus, I’ve seen that this works:
get-adgroupmember folks | get-aduser
It works because when get-aduser wakes up and sees no parameters, it assumes it's in - identity mode. In that case, then, it needs to see a samaccountname, an objectGUID, a SID, and/or a DN, or it's stumped. For example, the Dir command in PowerShell returns a set of objects representing the files and folders in the current folder. So, if you typed
dir | get-aduser
you’d get a whole lot of red error messages because poor get-aduser would find itself awash in things that lack a samaccountname, an objectGUID, a SID, or a DN. OK, there's a bit more to it than that, but basically if you go with the pipeline-as-assembly-line analogy, dir | get-aduser essentially makes get-aduser Lucille Ball on the chocolate factory. So, the moral of the story is that PowerShell cmdlets use the pipeline—but not all the same way! Check Help carefully before depending on them. Next month, I’ll take another approach to our group/OU selection process.