The pipeline: connecting commands
6.5 Using cmdlets that modify the system: killing processes and stopping services
Exporting and converting aren’t the only reasons you might want to connect two com- mands together. For example, consider—but please do not run—this command:
Get-Process | Stop-Process
Can you imagine what that command would do? We’ll tell you: crash your computer. It would retrieve every process and then start trying to end each one of them. It would get to a critical process, like the Local Security Authority, and your computer would probably crash with the famous Blue Screen of Death (BSOD). If you’re running PowerShell inside of a virtual machine and want to have a little fun, go ahead and try running that command.
The point is that cmdlets with the same noun (in this case, Process) can often pass information among each other. Typically, you’d specify the name of a specific process rather than trying to stop them all:
Get-Process -name Notepad | Stop-Process
Services offer something similar: the output from Get-Service can be piped to cmdlets like Stop-Service, Start-Service, Set-Service, and so forth.
As you might expect, there are some specific rules about which commands can connect to each other. For example, if you look at a command sequence like Get-ADUser | New-SQLDatabase, you would probably not expect it to do anything sen- sible (although it might well do something nonsensical). In chapter 7, we’ll dive into the rules that govern how commands can connect to each other.
Above and beyond
Time for a bit more useless background information, although, in this case, it’s the answer to a question that many students often ask us: Why would Microsoft provide both Export-CSV and ConvertTo-CSV, as well as two nearly identical cmdlets for XML?
In certain advanced scenarios, you might not want to save the data to a file on disk. For example, you might want to convert data to XML and then transmit it to a web service, or some other destination. By having distinct ConvertTo- cmdlets that don’t save to a file, you have the flexibility to do whatever you want.
We’d like you to know one more thing about cmdlets like Stop-Service and Stop-Process. These cmdlets modify the system in some fashion, and all cmdlets that modify the system have an internally defined impact level. The cmdlet’s creator sets this impact level and it can’t be changed. The shell has a corresponding $ConfirmPreference setting, which is set to High by default. Type the following set- ting name to see your shell’s setting:
PS C:\> $confirmpreference High
Here’s how it works: when a cmdlet’s internal impact level is equal to or higher than the shell’s $ConfirmPreference setting, the shell will automatically ask, “Are you sure?” when the cmdlet does whatever it’s trying to do. In fact, if you used a virtual machine to try the crash-your-computer command we mentioned earlier, you proba- bly were asked, “Are you sure?” for each process. When a cmdlet’s internal impact level is less than the shell’s $ConfirmPreference setting, you don’t automatically get the “Are you sure?” prompt.
But you can force the shell to ask you whether you’re sure:
Get-Service | Stop-Service -confirm
Next, add the -confirm parameter to the cmdlet. This should be supported by any cmdlet that makes some kind of change to the system, and it’ll show up in the help file for the cmdlet if it’s supported.
A similar parameter is -whatif. This is supported by any cmdlet that supports -confirm. The -whatif parameter isn’t triggered by default, but you can specify it whenever you want to:
PS C:\> get-process | stop-process -whatif
What if: Performing operation "Stop-Process" on Target "conhost (1920) ".
What if: Performing operation "Stop-Process" on Target "conhost (1960) ".
What if: Performing operation "Stop-Process" on Target "conhost (2460) ".
What if: Performing operation "Stop-Process" on Target "csrss (316)".
This tells you what the cmdlet would have done, without letting the cmdlet do it. It’s a useful way to preview what a potentially dangerous cmdlet would have done to your computer, to make certain that you want to do that.
6.6
Common points of confusion
One common point of confusion in PowerShell revolves around the Export-CSV and Export-CliXML commands. Both of these commands, technically speaking, create text files. That is, the output of either command can be viewed in Notepad, as shown in figure 6.2. But you have to admit that the text is definitely in a special kind of for- mat—either in comma-separated values or XML.
The confusion tends to set in when someone is asked to read these files back into the shell. Do you use Get-Content (or its aliases, Type or Cat)? For example, suppose you did this:
PS C:\> get-eventlog -LogName security -newest 5 | export-csv events.csv
Now, try reading that back in by using Get-Content:
PS C:\> Get-Content .\events.csv #TYPE System.Diagnostics.EventLogEntry#security/Microsoft-Windows-Security -Auditing/4797 "EventID","MachineName","Data","Index","Category","CategoryNumber","EntryT ype","Message","Source","ReplacementStrings","InstanceId","TimeGenerated", "TimeWritten","UserName","Site","Container" "4797","DONJONES1D96","System.Byte[]","263","(13824)","13824","SuccessAudi t","An attempt was made to query the existence of a blank password for an account.
Subject:
Security ID: S-1-5-21-87969579-3210054174-450162487-100 Account Name: donjones
Account Domain: DONJONES1D96 Logon ID: 0x10526 Additional Information:
Caller Workstation: DONJONES1D96 Target Account Name: Guest
Target Account Domain: DONJONES1D96","Microsoft-Windows-Security- uditing
","System.String[]","4797","3/29/2012 9:43:36 AM","3/29/2012 9:43:36 AM",, ,
"4616","DONJONES1D96","System.Byte[]","262","(12288)","12288","SuccessAudi t","The system time was changed.
We truncated the preceding output, but there’s a lot more of the same. Looks like gar- bage, right? You’re looking at the raw CSV data. The command didn’t try to interpret, or parse, the data at all. Contrast that with the results of Import-CSV:
PS C:\> import-csv .\events.csv EventID : 4797 MachineName : DONJONES1D96 Data : System.Byte[] Index : 263 Category : (13824) CategoryNumber : 13824 EntryType : SuccessAudit
Message : An attempt was made to query the existence of a blank password for an account.
Subject:
Security ID:
S-1-5-21-87969579-3210054174-450162487-1001 Account Name: donjones
Logon ID: 0x10526 Additional Information:
Caller Workstation: DONJONES1D96 Target Account Name: Guest
Target Account Domain: DONJONES1D96 Source : Microsoft-Windows-Security-Auditing ReplacementStrings : System.String[] InstanceId : 4797 TimeGenerated : 3/29/2012 9:43:36 AM TimeWritten : 3/29/2012 9:43:36 AM UserName :
Much nicer, right? The Import- cmdlets pay attention to what’s in the file, attempt to interpret it, and create a display that looks more like the output of the original command (Get-EventLog, in this case). Typically then, if you create a file with Export-CSV, you’ll read it by using Import-CSV. If you create it by using Export-CliXML, you’ll generally read it by using Import-CliXML. By using these com- mands in pairs, you’ll get better results. Use Get-Content only when you’re reading in a text file and don’t want PowerShell attempting to parse the data—that is, when you want to work with the raw text.
6.7
Lab
NOTE For this lab, you’ll need any computer running PowerShell v3.
We’ve kept this chapter’s text slightly shorter because some of the examples we showed you probably took a bit longer to complete, and because we want you to spend more time completing the following hands-on exercises. If you haven’t already com- pleted all of the “Try it now” tasks in the chapter, we strongly recommend that you do so before tackling these tasks:
1 What happens if you run Get-Service | Export-CSV services.csv | Out-File
from the console? Why does that happen?
2 Apart from getting one or more services and piping them to Stop-Service,
what other means does Stop-Service provide for you to specify the service or services you want to stop? Is it possible to stop a service without using Get-Service at all?
3 What if you want to create a pipe-delimited file instead of a comma-separated
(CSV) file? You would still use the Export-CSV command, but what parameters would you specify?
4 Is there a way to eliminate the # comment line from the top of an exported CSV
file? That line normally contains type information, but what if you want to omit that from a particular file?
5 Export-CliXML and Export-CSV both modify the system because they can cre- ate and overwrite files. What parameter would prevent them from overwriting
an existing file? What parameter would ask you if you were sure before proceed- ing to write the output file?
6 Windows maintains several regional settings, which include a default list separa-
tor. On U.S. systems, that separator is a comma. How can you tell Export-CSV to use the system’s default separator, rather than a comma?
TRY IT NOW After you’ve completed this lab, try to complete Review Lab 1, which you’ll find in appendix A of this book.
74