Invariably, when I need to do something in Active Directory (AD), I’m never where I need to be. Fortunately, I have PowerShell 2.0—and at least two ways to turn a vanilla Windows 7 desktop into an AD administrative workstation. Last month, in “Find Users with Get-ADUser,” I started showing you how to use Windows Server 2008 R2’s new AD-related PowerShell cmdlets to perform AD maintenance tasks more quickly and consistently. Using AD’s PowerShell cmdlets can get a little irritating, however, as not every Server 2008 R2 or Windows 7 system has the AD module on it. (Remember, you can issue R2’s AD cmdlets from only those two OSs.) Of course, you could just download the Remote Server Administration Tools (RSAT) to get that module, but that would probably take more time than just going back to the office. That’s where PowerShell remoting helps out.

Suppose you’re sitting at a Windows 7 workstation and need to do a query like last month’s against AD:

get-aduser -f {givenname -eq 'Mark'}

If you know the name of a Server 2008 R2-based DC (let’s call it DC64), you might be able to enter these four commands right at your Windows 7 box:

enter-pssession dc64
ipmo ac*
get-aduser -f {givenname -eq 'Mark'}
exit-pssession

Those two new commands—enter/exit-pssession (or etsn/exsn for short)—enable PowerShell remote control atop the Windows Remote Management (WinRM) protocol that’s existed in Windows since Windows Vista, and they’re great because the Windows 7 system needs no previous setup to make this work.

The target of those commands, however—DC64—does need a bit of prep work before it can be remotely controlled. (That’s why I said “might” a couple of paragraphs back.) First, its firewall needs to be either in Domain or Private mode and, second, it needs something called a WinRM listener enabled. Out of the box, Windows computers can initiate WinRM sessions but can’t “hear” other systems ask them to participate in WinRM sessions unless you enable those computers’ WinRM listeners by typing this command from an elevated command prompt on those computers:

winrm quickconfig -q

If you prefer to use Group Policy to enable listeners on many systems en masse, enable the setting Allow automatic configuration of listeners in Computer Configuration, Administrative Templates, Windows Components, Windows Remote Management (WinRM), WinRM Service. If you decide to create a Group Policy to enable remote sessions, remember that in general you need enable it only on the servers. (DC64 needs the listener; your Windows 7 box doesn’t.) Alternatively, PowerShell has a way to enable or disable WinRM listeners in its enable-psremoting and disable-psremoting cmdlets.

Besides enable/exit-pssession, you can similarly send one or more PowerShell commands to a remote system using another PowerShell cmdlet, invoke-command or icm. Its syntax looks like

invoke-command computer-to-run-command-on { command ; command ; command...}

You need to enter two commands (the ipmo and the get-aduser), so your invoke-command cmdlet will look like

icm dc64 {ipmo ac* ; get-aduser -f {givenname -eq 'Mark'}}

Notice a few things here. First, the PowerShell term for the thing between the curly braces is a script block, which really just means “one or more cmdlets.” The script block is two commands separated by a semicolon—the ipmo and the get-aduser commands. Notice that the smaller command inside that script block (givenname –eq 'Mark') isn’t a script block; the PowerShell folks decided to use braces to store query/filter criteria early on, so the folks on the Directory Services team apparently decided to use them for Get-aduser’s filter parameter. It’s a bit confusing, but just remember that in PowerShell, in general, you’ll only see braces used to designate one or more cmdlets that work together—a script block—or to surround some logical criterion.

Second, let me clarify something about PowerShell grammar. Searching for “invoke-command” on the Internet will yield a zillion examples that look like

invoke-command -computername dc64...

but notice that my command lacks -computername. I’ve left that out because although PowerShell tends to require explicit parameters and operators like -computername, -filter, and -eq rather than positional parameters, it bends that rule when there’s a commonly used parameter, as is the case with -computername. (It’s hard to imagine a case in which you want to start a remote session but aren’t going to name the system to start the session at.) It’s all a matter of taste, but I like my PowerShell commands to be as short as is possible. PowerShell’s goal is productivity, not wearing out keyboards. Next month, more queries!