Skip to main content

Windows

How to Search a File for Text or a Pattern in Windows PowerShell

Problem

You want to find a string or regular expression in a file.

Solution

To search a file for an exact (but case insensitive) match, use the –Simple parameter of the SelectString cmdlet:

PS >SelectString –Simple SearchText file.txt To search a file for a regular expression, provide that pattern to the SelectString cmdlet:

PS >SelectString "\(...\) ......." phone.txt To Recursively search all *.txt files for a regular expression, pipe the results of GetChildItem to the SelectString cmdlet:

PS >GetChildItem Filter *.txt Recurse | SelectString pattern

Discussion

The SelectString cmdlet is the easiest way to search files for a pattern or specific string. In contrast to the traditional textmatching utilities (such as grep) that support the same type of functionality, the matches returned by the SelectString cmdlet include detailed information about the match itself.

PS >$matches = SelectString "output file" transcript.txt PS >$matches | Select LineNumber,Line

LineNumber Line 7 Transcript started, output file... If you want to search multiple files of a specific extension, the SelectString cmdlet lets you use wildcards (such as *.txt) on the filename. For more complicated lists of files (which includes searching all files in the directory), it is usually more useful to use the GetChildItem cmdlet to generate the list of files as shown previously.

By default, the SelectString cmdlet outputs the filename, line number, and matching line for every match it finds. In some cases, this output may be too much detail— such as when you are searching for which binary file contains a specific string. Binary files rarely make sense when displayed as text, so your screen quickly fills with apparent garbage.

The solution to this problem comes from the SelectString’s –Quiet switch. It simply returns True or False, depending on whether the file contains the string. So, to find the DLL in the current directory that contains the text "Debug":

GetChildItem | Where { $_ | SelectString "Debug" Quiet } Two other common tools used to search files for text are the –match operator and the switch statement with the –file option.

Enable PowerShell Scripting Through an Execution Policy

Problem

PowerShell provides an error message when you try to run a script:

PS>.\Test.ps1 File C:\temp\test.ps1 cannot be loaded because the execution of scripts is disa bled on this system. Please see "gethelp about_signing" for more details. At line:1 char:10

+ .\Test.ps1

Solution

To prevent this error message, use the SetExecutionPolicy cmdlet to change the PowerShell execution policy to one of the policies that allow scripts to run:

SetExecutionPolicy RemoteSigned

Discussion

As normally configured, PowerShell operates strictly as an interactive shell. By disabling the execution of scripts by default, PowerShell prevents malicious PowerShell scripts from affecting users who have PowerShell installed, but who may never have used (or even heard of!) PowerShell.

You (as a reader of this book) are not part of that target audience, however, so you will want to configure PowerShell to run under one of the following four execution policies:

Restricted

PowerShell operates as an interactive shell only. Attempting to run a script generates an error message. This is PowerShell’s default execution policy.

AllSigned

PowerShell only runs scripts that contain a digital signature. When you attempt to run a script signed by a publisher that PowerShell hasn’t seen before, PowerShell asks whether you trust that publisher to run scripts on your system.

RemoteSigned (recommended)

PowerShell runs most scripts without prompting, but requires that scripts that originate from the Internet contain a digital signature. As in AllSigned mode, PowerShell asks whether you trust that publisher to run scripts on your system when you run a script signed by a publisher it hasn’t seen before. PowerShell considers a script to have come from the Internet when it has been downloaded to your computer by a popular communications programs such as Internet Explorer, Outlook, or Messenger.

Unrestricted

PowerShell does not require a digital signature on any script, but (like Windows Explorer) warns you when a script originates from the Internet.

Run the SetExecutionPolicy cmdlet as an administrator to configure the system’s execution policy. If you want to configure your execution policy on Windows Vista, rightclick the Windows PowerShell link for the option to launch PowerShell as Administrator.

Just because a script is signed, it does not mean that the script is safe! The signature on a script gives you a way to verify who the script came from, but not that you can trust its author to run commands on your

system. You need to make that decision for yourself, which is why PowerShell asks you.

Alternatively, you may directly modify the registry key that PowerShell uses to store its execution policy. This is the ExecutionPolicy property under the registry path HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell.

In an enterprise setting, PowerShell also lets you override this local preference through Group Policy.

When using an execution policy that detects Internetbased scripts, you may want to stop PowerShell from treating those scripts as remote. To do that, rightclick on the file from Windows Explorer, select Properties, and then click Unblock.

In an enterprise setting, PowerShell sometimes warns of the dangers of Internetbased scripts even if they are located only on a network share. If unblocking the file does not resolve the issue, your machine has likely been configured to restrict access to network shares. This is common with Internet Explorer’s Enhanced Security Configuration mode. To prevent this message, add the path of the network share to Internet Explorer’s Intranet or Trusted Sites zone.

For more information about script signing in PowerShell, type GetHelp about_ signing. For more information about the SetExecutionPolicy cmdlet, type GetHelp SetExecutionPolicy.

Get and List the Properties of a PowerShell User Account

Problem

You want to get and list the properties of a specific user account.

Solution

To list the properties of a user account, use the [adsi] type shortcut to bind to the user in Active Directory, and then pass the user to the FormatList cmdlet: $user = [adsi] "LDAP://localhost:389/cn=MyerKen,ou=West,ou=Sales,dc=Fabrikam,dc=COM"

$user | FormatList *

Discussion

The solution retrieves the MyerKen user from the Sales West OU. By default, the FormatList cmdlet shows only the distinguished name of the user, so we type FormatList * to display all properties.

If you know the property for which you want the value, specify it by name:

PS >$user.DirectReports CN=SmithRobin,OU=West,OU=Sales,DC=Fabrikam,DC=COM CN=DoeJane,OU=West,OU=Sales,DC=Fabrikam,DC=COM

Unlike users, some types of Active Directory objects don’t allow you to retrieve their properties by name this way. Instead, you must call the Get() method to retrieve specific properties:

PS >$user.Get("userPrincipalName") Ken.Myer@fabrikam.com

Create a Multiline or Formatted String in Windows PowerShell

Problem

You want to create a variable that holds text with newlines or other explicit formatting.

Solution

Use a PowerShell here string to store and work with text that includes newlines and other formatting information.

$myString = @" This is the first line of a very long string. A "here string" lets you to create blocks of text that span several lines. "@

Discussion

PowerShell begins a here string when it sees the characters @" followed by a newline. It ends the string when it sees the characters "@ on their own line. These seemingly odd restrictions allow you to create strings that include quote characters, newlines, and other symbols that you commonly use when you create large blocks of preformatted text.

These restrictions, while useful, can sometimes cause problems when you copy and paste PowerShell examples from the Internet. Web pages often add spaces at the end of lines, which can interfere with the

strict requirements of the beginning of a here string. If PowerShell produces an error when your script defines a here string, check that the here string does not include an errant space after its first quote character.

Like string literals, here strings may be literal (and use single quotes) or expanding (and use double quotes).

In addition to their usefulness in preformatted text variables, here strings also provide a useful way to temporarily disable lines in your script. Since PowerShell does not provide a firstclass multiline comment, you can use a here string as you would use a multiline comment in other scripting or programming languages. Example 51 demonstrates this technique.

Example 51. Using here strings for multiline comments

## This is a regular comment $null = @" function MyTest {

Example 51. Using here strings for multiline comments (continued)

"This should not be considered a function" }

$myVariable = 10; "@

## This is regular script again

Using $null for the variable name tells PowerShell to not retain the information for your later use.

Safely Build File Paths Out of Their Components

Problem

You want to build a new path out of a combination of subpaths.

Solution

To join elements of a path together, use the JoinPath cmdlet:

PS >JoinPath (GetLocation) newfile.txt C:\temp\newfile.txt

Discussion

The usual way to create new paths is by combining strings for each component, placing a path separator between them:

PS >"$(GetLocation)\newfile.txt" C:\temp\newfile.txt

Unfortunately, this approach suffers from a handful of problems:

  • What if the directory returned by GetLocation already has a slash at the end?
  • What if the path contains forward slashes instead of backslashes?
  • What if we are talking about registry paths instead of filesystem paths? Fortunately, the JoinPath cmdlet resolves these issues and more. For more information about the JoinPath cmdlet, type GetHelp JoinPath.

Launch a Windows PowerShell Process

Problem

You want to launch a new process on the system, but also want to configure its startup environment.

Solution

To launch a new process, use the [System.Diagnostics.Process]::Start() method. To control its startup environment, supply it with a System.Diagnostics. ProcessStartInfo object that you prepare, as shown in Example 211.

Example 211. Configuring the startup environment of a new process

$credential = GetCredential

## Prepare the startup information (including username and password) $startInfo = NewObject Diagnostics.ProcessStartInfo $startInfo.UserName = $credential.Username $startInfo.Password = $credential.Password $startInfo.Filename = "powershell"

## Start the process $startInfo.UseShellExecute = $false [Diagnostics.Process]::Start($startInfo)

Discussion

Normally, launching a process in PowerShell is as simple as typing the program name:

PS >notepad c:\temp\test.txt

However, you may sometimes need detailed control over the process details, such as its credentials, startup directory, environment variables, and more. In those situations, use the [System.Diagnostics.Process]::Start() method to provide that functionality.

The following function acts like the cmd.exe start command and like the Start | Run dialog in Windows:

PS >function start { [Diagnostics.Process]::Start($args) }

PS >start www.msn.com

Store Information in Variables in Windows PowerShell

Problem

You want to store the output of a pipeline or command for later use, or to work with it in more detail.

Solution

To store output for later use, store the output of the command in a variable. You can access this information later, or even pass it down the pipeline as though it was the output of the original command:

PS >$result = 2 + 2 PS >$result 4 PS >$processes = GetProcess PS >$processes.Count 85 PS >$processes | WhereObject { $_.ID eq 0 }

Handles
NPM(K)
PM(K)
WS(K) VM(M)
CPU(s)
Id ProcessName

0
0
0
16
0

0 Idle

Discussion

Variables in PowerShell (and all other scripting and programming languages) let you store the output of something so that you can use it later. Avariable name starts with a dollar sign ($) and can be followed by nearly any character. Asmall set of characters have special meaning to PowerShell, so PowerShell provides a way to make variable names that include even these.

You can store the result of any pipeline or command in a variable to use it later. If that command generates simple data (such as a number or string), then the variable contains simple data. If the command generates rich data (such as the objects that represent system processes from the GetProcess cmdlet), then the variable contains that list of rich data. If the command (such as a traditional executable) generates plain text (such as the output of traditional executable), then the variable contains plain text.

If you’ve stored a large amount of data into a variable, but no longer need that data, assign the value $null (or anything else) to that variable so that PowerShell can release the memory it was using to store

that data.

In addition to variables that you create, PowerShell automatically defines several variables that represent things such as the location of your profile file, the process ID of PowerShell, and more.

Tracing and Error Management in Windows PowerShell

What if it doesn’t all go according to plan? This is the core question behind error management in any system and plays a large part in writing PowerShell scripts as well.

While it is a core concern in many systems, PowerShell’s support for error management provides several unique features designed to make your job easier: the primary benefit being a distinction between terminating and nonterminating errors.

When running a complex script or scenario, the last thing you want is for your world to come crashing down because a script can’t open one of the 1,000 files it is operating on. Although it should make you aware of the failure, the script should still continue to the next file. That is an example of a nonterminating error. But what if the script runs out of disk space while running a backup? That should absolutely be an error that causes the script to exit—also known as a terminating error.

Given this helpful distinction, PowerShell provides several features that allow you to manage errors generated by scripts and programs, and also allows you to generate them yourself.

Comparing Datain Windows PowerShell

When working in PowerShell, it is common to work with collections of objects. Most PowerShell commands generate objects, as do many of the methods that you work with in the .NET Framework. To help work with these object collections, PowerShell introduces the CompareObject cmdlet. The CompareObject cmdlet provides functionality similar to wellknown diff commands, but with an objectoriented flavor.

Store the Output of a Windows PowerShell Command into a File

Problem

You want to redirect the output of a pipeline into a file.

Solution

To redirect the output of a command into a file, use either the OutFile cmdlet or one of the redirection operators.

OutFile:

GetChildItem | OutFile unicodeFile.txt GetContent filename.cs | OutFile Encoding ASCII file.txt GetChildItem | OutFileWidth 120 unicodeFile.cs

Redirection operators:

GetChildItem > files.txt GetChildItem 2> errors.txt

Discussion

The OutFile cmdlet and redirection operators share a lot in common—and for the most part, you can use either. The redirection operators are unique because they give the greatest amount of control over redirecting individual streams. The OutFile cmdlet is unique primarily because it lets you easily configure the formatting width and encoding.

The default formatting width and the default output encoding are two aspects of output redirection that can sometimes cause difficulty.

The default formatting width sometimes causes problems because redirecting PowerShellformatted output into a file is designed to mimic what you see on the screen. If your screen is 80 characters wide, the file will be 80 characters wide as well. Examples of PowerShellformatted output include directory listings (that are implicitly formatted as a table) as well as any commands that you explicitly format using one of the Format* set of cmdlets. If this causes problems, you can customize the width of the file with the —Width parameter on the OutFile cmdlet.

The default output encoding sometimes causes unexpected results because PowerShell creates all files using the UTF16 Unicode encoding by default. This allows PowerShell to fully support the entire range of international characters, cmdlets, and output. Although this is a great improvement to traditional shells, it may cause an unwanted surprise when running large search and replace operations on ASCII source code files, for example. To force PowerShell to send its output to a file in the ASCII encoding, use the —Encoding parameter on the OutFile cmdlet.

For more information about the OutFile cmdlet, type GetHelp OutFile.