SECCION 2 LA POLITICA E INSTRUMENTOS DE FOMENTO: UN AVANCE SIGNIFICATIVO DESDE UNA PERSPECTIVA DE GÉNERO
6. CONAF: Ley forestal, equidad social y de género
The CSV example was cool, but it’s pretty easy to make property and parameter names line up when you’re creating the input from scratch. Things get tougher when you’re forced to deal with objects that are created for you, or data that’s being produced by someone else.
For this example, we’re going to introduce a new command that you might not have access to: New-ADUser. It’s part of the ActiveDirectory module, which you’ll find on any Windows Server 2008 R2 (or later) domain controller. You can also get that module on a client computer by installing Microsoft’s Remote Server Administration Tools (RSAT). But for now, don’t worry about running the command; follow along with the example.
New-ADUser has a number of parameters, each designed to accept information about a new Active Directory user. Here are some examples:
-Name (this is mandatory)
-samAccountName (technically not mandatory, but you have to provide it to make the account usable)
-Department
-City
-Title
We could cover the others, but let’s work with these. All of them accept pipeline input ByPropertyName.
For this example, we’ll again assume you’re getting a CSV file, but it’s coming from your company’s Human Resources or Personnel department. You’ve given them your desired file format a dozen times, but they persist in giving you something that’s close, but not quite right, as shown in figure 9.12.
As you can see in figure 9.12, the shell can import the CSV file fine, resulting in three objects with four properties apiece. The problem is that the dept property won’t line up with the -Department parameter of New-ADUser, the login property is meaning- less, and you don’t have samAccountName or Name properties—both of which are required if you want to be able to run this command to create new users:
PS C:\> import-csv .\newusers.csv | new-aduser
How can you fix this? Obviously, you could open the CSV file and fix it, but that’s a lot of manual work over time, and the whole point of PowerShell is to reduce manual labor. Why not set up the shell to fix it instead? Look at the following example:
PS C:\> import-csv .\newusers.csv | >> select-object -property *, >> @{name='samAccountName';expression={$_.login}}, >> @{label='Name';expression={$_.login}}, >> @{n='Department';e={$_.Dept}} >> login : DonJ
Figure 9.12 Working with the CSV file provided by Human Resources
dept : IT city : Las Vegas title : CTO samAccountName : DonJ Name : DonJ Department : IT login : GregS dept : Custodial city : Denver title : Janitor samAccountName : GregS Name : GregS Department : Custodial login : JeffH dept : IT city : Syracuse
title : Network Engineer samAccountName : JeffH
Name : JeffH Department : IT
That’s some pretty funky syntax, so let’s break it down:
We used Select-Object and its -Property parameter. We started by specifying the property *, which means “all of the existing properties.” Notice that the * is followed by a comma, which means we’re continuing the list of properties.
We then created a hash table, which is the construct starting with @{ and ending with }. Hash tables consist of one or more key=value pairs, and Select-Object has been programmed to look for some specific keys, which we’ll provide to it.
The first key Select-Object wants can be Name, N, Label, or L, and the value for that key is the name of the property we want to create. In the first hash table, we specified samAccountName, in the second, Name, and in the third, Department. These correspond to the parameter names of New-ADUser.
The second key that Select-Object needs can be either Expression or E. The value for this key is a script block, contained within {curly brackets}. Within that script block, you use the special $_ placeholder to refer to the existing piped-in object (the original row of data from the CSV file) followed by a period. $_ lets you access one property of the piped-in object, or one column of the CSV file. This specifies the contents for the new properties.
TRY IT NOW Go ahead and create the CSV file that’s shown in figure 9.12. Then try running the exact command we did above—you can type it exactly as shown.
What we’ve done is taken the contents of the CSV file—the output of Import-CSV— and modified it, dynamically, in the pipeline. Our new output matches what New-ADUser wants to see, so we can now create new users by running this command:
>> select-object -property *, >> @{name='samAccountName';expression={$_.login}}, >> @{label='Name';expression={$_.login}}, >> @{n='Department';e={$_.Dept}} | >> new-aduser >>
The syntax might be a bit ugly, but this is an incredibly powerful technique. It’s also usable in many other places in PowerShell, and you’ll see it again in upcoming chap- ters. You’ll even see it in the examples contained in PowerShell’s help files: Run Help Select -Example and look for yourself.
9.6
Parenthetical commands
Sometimes, no matter how hard you try, you can’t make pipeline input work. For example, consider the Get-WmiObject command. You’ll learn more about it in an upcoming chapter, but for right now, look at the help for its -ComputerName property, as shown in figure 9.13.
This parameter doesn’t accept computer names from the pipeline. How can we retrieve names from someplace—like our text file, which contains one computer name per line—and feed them to the command? The following won’t work:
PS C:\> get-content .\computers.txt | get-wmiobject -class win32_bios
The String objects produced by Get-Content won’t match the -computerName parameter of Get-WmiObject. What can we do? Use parentheses:
PS C:\> Get-WmiObject -class Win32_BIOS -ComputerName (Get-Content .\comput ers.txt)
Think back to high school algebra class, and you’ll recall that parentheses mean “do this first.” That’s what PowerShell does: it runs the parenthetical command first. The results of that command—in this case, a bunch of String objects—are fed to the parameter. Because -ComputerName happens to want a bunch of String objects, the command works.
TRY IT NOW If you have a couple of computers with which you can test this, go ahead and try that command. Put the correct computer names or IP
addresses into your own Computers.txt file. This will work best for computers all in the same domain, because permissions will be taken care of more easily in that environment.
The parenthetical command trick is powerful because it doesn’t rely on pipeline parameter binding at all—it takes objects and sticks them right into the parameter. But the technique doesn’t work if your parenthetical command isn’t generating the exact type of object that the parameter expects, which means sometimes you’ll have to manipulate things a bit. Let’s look at how.