Above all else, the design of Windows PowerShell places priority on its use as an efficient and powerful interactive shell. Even its scripting language plays a critical role in this effort, as it too heavily favors interactive use.
What surprises most people when they first launch PowerShell is its similarity to the command prompt that has long existed as part of Windows. Familiar tools continue to run. Familiar commands continue to run. Even familiar hotkeys are the same. Supporting this familiar user interface, though, is a powerful engine that lets you accomplish once cumbersome administrative and scripting tasks with ease.
This chapter introduces PowerShell from the perspective of its interactive shell.
You rely on a lot of effort invested in your current tools. You have traditional executables, Perl scripts, VBScript, and of course, a legacy build system that has organically grown into a tangled mess of batch files. You want to use PowerShell, but don't want to give up everything you already have.
To run a program, script, batch file, or other executable command in the system's path, enter its filename. For these executable types, the extension is optional:
Program.exe arguments ScriptName.ps1 arguments BatchFile.cmd arguments
To run a command that contains a space in its name, enclose its filename in single-quotes (') and precede the command with an ampersand (&), known in PowerShell as the Invoke operator:
& 'C:\Program Files\Program\Program.exe' arguments
To run a command in the current directory, place .\ in front of its filename:
.\Program.exe arguments
To run a command with spaces in its name from the current directory, precede it with both an ampersand and .\:
& '.\Program With Spaces.exe' arguments
In this case, the solution is mainly to use your current tools as you always have. The only difference is that you run them in the PowerShell interactive shell, rather than cmd.exe.
The final three tips in the solution merit special attention. They are the features of PowerShell that many new users stumble on when it comes to running programs. The first is running commands that contain spaces. In cmd.exe, the way to run a command that contains spaces is to surround it with quotes:
"C:\Program Files\Program\Program.exe"
In PowerShell, though, placing text inside quotes is part of a feature that lets you evaluate complex expressions at the prompt, as shown in Example 1.1, “Evaluating expressions at the PowerShell prompt”.
Example 1.1. Evaluating expressions at the PowerShell prompt
PS > 1 + 1 2 PS > 26 * 1.15 29.9 PS > "Hello" + " World" Hello World PS > "Hello World" Hello World PS > "C:\Program Files\Program\Program.exe" C:\Program Files\Program\Program.exe PS >
So, a program name in quotes is no different from any other string in quotes. It's just an expression. As shown previously, the way to run a command in a string is to precede that string with the invoke (&) operator. If the command you want to run is a batch file that modifies its environment, see the section called “Program: Retain Changes to Environment Variables Set by a Batch File”.
By default, PowerShell's security policies prevent scripts from running. Once you begin writing or using scripts, though, you should configure this policy to something less restrictive. For information on how to configure your execution policy, see the section called “Enable Scripting Through an Execution Policy”.
The second command that new users (and seasoned veterans before coffee!) sometimes stumble on is running commands from the current directory. In cmd.exe, the current directory is considered part of the path "the list of directories that Windows searches to find the program name you typed. If you are in the C:\Programs directory, cmd.exe looks in C:\Programs (among other places) for applications to run.
PowerShell, like most Unix shells, requires
that you explicitly state your desire to run a program from the current
directory. To do that, you use the .\Program.exe syntax, as shown previously.
This prevents malicious users on your system from littering your hard
drive with evil programs that have names similar to (or the same as)
commands you might run while visiting that directory.
To save themselves from having to type the location of commonly used scripts and programs, many users put these utilities along with their PowerShell scripts in a "tools" directory, which they add to their system's path. If PowerShell can find a script or utility in your system's path, you do not need to explicitly specify its location.
Scripts and examples from this book are available at http://www.oreilly.com/catalog/9780596801519.
To learn how to write a PowerShell script, see the section called “Write a Script”.
You have a command line that works from
cmd.exe, and want to resolve errors that occur from
running that command in PowerShell.
Enclose any affected command arguments in single quotes to prevent them from being interpreted by PowerShell, and replace any single quotes in the command with two single quotes.
PS > cmd /c echo '!"#$%&''()*+,-./09:;<=>?@AZ[\]^_`az{|}~'
!"#$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~One of PowerShell's primary goals has always been command consistency. Because of this, Cmdlets are very regular in the way that they accept parameters. Native executables write their own parameter parsing, so they usually are not. In addition, PowerShell offers many features that make you more efficient at the command line: command substitution, variable expansion, and more. Since many native executables were written before PowerShell was, they may use special characters that conflict with these features.
Unlike Cmdlets, PowerShell doesn't apply special parameter processing to native executables. However, version one of PowerShell did incorrectly process some arguments that contained the colon character if they looked like parameters for a cmdlet. If you've been impacted by this (or perhaps formed a superstition that "calling native executables doesn't work properly"), try again.
As an example, the command given in the Solution uses all the special characters available on a typical keyboard. Without the quotes, PowerShell treats some of them as language features:
Table 1.1. Sample of special characters
" | The beginning (or end) of quoted text |
# | The beginning of a comment |
$ | The beginning of a variable |
& | Reserved for future use |
(, ) | Parentheses used for sub-expressions |
; | Statement separator |
{ } | Script block |
| | Pipeline separator |
` | Escape character |
When surrounded by single quotes, PowerShell accepts these characters as written.
Despite these precautions, you may still
sometimes run into a command that doesn't seem to work when called from
PowerShell. To see exactly what PowerShell passes
to that command, you can view the output of the trace source called
NativeCommandParameterBinder:
PS > Trace-Command NativeCommandParameterBinder {
>> cmd /c echo '!"#$%&''()*+,-./09:;<=>?@AZ[\]^_`az{|}~'
>> } -PsHost
>>
DEBUG: NativeCommandParameterBinder Information: 0 : WriteLine
Argument 0: /c
DEBUG: NativeCommandParameterBinder Information: 0 : WriteLine
Argument 1: echo
DEBUG: NativeCommandParameterBinder Information: 0 : WriteLine
Argument 2: !#$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~
!"#$%&'()*+,-./09:;<=>?@AZ[\]^_`az{|}~ If the command arguments shown in this output don't match the arguments you expect, they had special meaning to PowerShell and should be escaped.
Get-Help
Trace-Command
To run a PowerShell command, type its name at the command prompt. For example:
PS > Get-Process
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
133 5 11760 7668 46 1112 audiodg
184 5 33248 508 93 1692 avgamsvr
143 7 31852 984 97 1788 avgemcThe Get-Process command is an example of a native
PowerShell command, called a cmdlet. As compared to
traditional commands, cmdlets provide significant benefits to both
administrators and developers:
They share a common and regular command-line syntax.
They support rich pipeline scenarios (using the output of one command as the input of another).
They produce easily manageable object-based output, rather than error-prone plain text output.
Because the Get-Process cmdlet generates rich object-based
output, you can use its output for many process-related tasks.
The Get-Process cmdlet is just one of the many
that PowerShell supports. See the section called “Find a Command to Accomplish a Task” to learn techniques for
finding additional commands that PowerShell supports.
For more information about working with classes from the .NET Framework, see the section called “Work with .NET Objects”.
You want to invoke a long-running command on a local or remote computer.
Invoke the command as a Job
to have PowerShell run it in the background:
PS > Start-Job { while($true) { Get-Random; Start-Sleep 5 } } -Name Sleeper
Id Name State HasMoreData Location
-- ---- ----- ----------- --------
1 Sleeper Running True localhost
PS > Receive-Job Sleeper
671032665
1862308704
PS > Stop-Job SleeperPowerShell's job cmdlets provide a consistent
way to create and interact with background tasks. In the Solution, we
use the Start-Job cmdlet to launch a background job
on the local computer. We give it the name of
Sleeper, but otherwise don't customize much of its
execution environment.
In addition to being able to customize the job
name, the Start-Job cmdlet also lets you launch the
job under alternate user credentials or as a 32-bit process (if run
originally from a 64-bit process.)
an example of running with alternate user credentials would be nice here.
Once you have launched a Job, you can use the other Job cmdlets to interact with it:
Gets all jobs associated with this the current session.
Waits for a job until it has output ready to be retrieved.
Retrieves any output the job has
generated since the last call to
Receive-Job.
Stops a job.
Removes a job from the list of active jobs.
In addition to the
Start-Job cmdlet, you can also use the
-AsJob parameter in many cmdlets to have them
perform their task in the background. Two of the most useful examples
are the Invoke-Command cmdlet (when operating
against remote computers), and the set of WMI-related cmdlets.
Gets all jobs associated with this the current session. --> Gets all jobs associated with the current session.
computers,) and --> computers), and
If your job generates an error, the
Receive-Job cmdlet will display it to you when you
receive the results. If you want to investigate these errors further,
the object returned by Get-Job exposes them through
the Error property.
Example 1.2. Retrieving errors from a Job
PS > Start-Job -Name ErrorJob { Write-Error Error! }
WARNING: column "Command" does not fit into the display and was removed.
Id Name State HasMoreData Location
-- ---- ----- ----------- --------
1 ErrorJob Running True localhost
PS > Receive-Job ErrorJob
Error!
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteError
Exception
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorExc
eption,Microsoft.PowerShell.Commands.WriteErrorCommand
PS > $job = Get-Job ErrorJob
PS > $job | Format-List *
State : Completed
HasMoreData : False
StatusMessage :
Location : localhost
Command : Write-Error Error!
JobStateInfo : Completed
Finished : System.Threading.ManualResetEvent
InstanceId : 801e932c-5580-4c8b-af06-ddd1024840b7
Id : 1
Name : ErrorJob
ChildJobs : {Job2}
Output : {}
Error : {}
Progress : {}
Verbose : {}
Debug : {}
Warning : {}
PS > $job.ChildJobs[0] | Format-List *
State : Completed
StatusMessage :
HasMoreData : False
Location : localhost
Runspace : System.Management.Automation.RemoteRunspace
Command : Write-Error Error!
JobStateInfo : Completed
Finished : System.Threading.ManualResetEvent
InstanceId : 60fa85da-448b-49ff-8116-6eae6c3f5006
Id : 2
Name : Job2
ChildJobs : {}
Output : {}
Error : {Microsoft.PowerShell.Commands.WriteErrorException,Microso
ft.PowerShell.Commands.WriteErrorCommand}
Progress : {}
Verbose : {}
Debug : {}
Warning : {}
PS > $job.ChildJobs[0].Error
Error!
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteError
Exception
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorExc
eption,Microsoft.PowerShell.Commands.WriteErrorCommand
PS > As this example shows, Jobs are sometimes containers for other jobs, called child jobs. Jobs created through the Start-Job cmdlet will always be child jobs attached to a generic container. To access the errors returned by these jobs, you instead access the errors in its first child job (called child job number zero.)
Use the
Register-TemporaryEvent command given in the section called “Create a Temporary Event Subscription” to register for the
event's StateChanged event:
PS > $job = Start-Job -Name TenSecondSleep { Start-Sleep 10 }
PS > Register-TemporaryEvent $job StateChanged -Action {
>> [Console]::Beep(100,100)
>> Write-Host "Job #$($sender.Id) ($($sender.Name)) complete."
>> }
>>
PS > Job #6 (TenSecondSleep) complete.
PS > Register-TemporaryEvent does not seem to be a valid command (windows7)
The term 'Register-TemporaryEvent' is not recognized as the name of a cmdlet, function, script file, or operable prog
m. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:24
+ Register-TemporaryEvent <<<< $job StateChanged -Action {
+ CategoryInfo : ObjectNotFound: (Register-TemporaryEvent:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Register-TemporaryEvent is not a built-in command. It's a script from the section called “Create a Temporary Event Subscription” (Chapter 31). There is a link to it at the beginning of a solution. I would suggest using "Use the Register-TemporaryEvent script given..."
When a job completes, it raises a
StateChanged event to notify subscribers that its
state has changed. We can use PowerShell's event handling cmdlets to
register for notifications about this event, but they are not geared
toward this type of one-time event handling. To solve that, we use the
Register-TemporaryEvent command given in the section called “Create a Temporary Event Subscription”.
In our example action block, we simply emit a beep, and write a message saying that the job is complete.
As another option, you can also update your
prompt function to highlight jobs that are complete,
but still have output you haven't processed:
$psJobs = @(Get-Job -State Completed | ? { $_.HasMoreData })
if($psJobs.Count -gt 0) { ($psJobs | Out-String).Trim() | Write-Host -Fore Yellow }For more information about events and this type of automatic event handling. see Chapter 31, Event Handling
Chapter 31, Event Handling --> Chapter 31. Event Handling
the section called “Run Programs, Scripts, and Existing Tools”
Chapter 31, Event Handling --> Chapter 31. Event Handling
You want to customize PowerShell's interactive experience with a personalized prompt, aliases, and more.
When you want to customize aspects of
PowerShell, place those customizations in your personal profile script.
PowerShell provides easy access to this profile script by storing its
location in the $profile
variable.
By default, PowerShell's security policies prevent scripts (including your profile) from running. Once you begin writing scripts, though, you should configure this policy to something less restrictive. For information on how to configure your execution policy, see the section called “Enable Scripting Through an Execution Policy”.
To create a new profile (and overwrite one if it already exists):
New-Item -type file -force $profile
To edit your profile:
notepad $profile
To see your profile file:
Get-ChildItem $profile
Once you create a profile script, you can add
a function called Prompt that returns
a string. PowerShell displays the output of this function as your
command-line prompt.
function Prompt
{
"PS [$env:COMPUTERNAME] >"
}This example prompt displays your computer
name, and look like: PS
[LEE-DESK]>
You may also find it helpful to add aliases to your profile. Aliases let you refer to common commands by a name that you choose. Personal profile scripts let you automatically define aliases, functions, variables, or any other customizations that you might set interactively from the PowerShell prompt. Aliases are among the most common customizations, as they let you refer to PowerShell commands (and your own scripts) by a name that is easier to type.
If you want to define an alias for a command but also need to modify the parameters to that command, then define a function instead.
For example:
Set-Alias new New-Object Set-Alias iexplore 'C:\Program Files\Internet Explorer\iexplore.exe'
Your changes will become effective once you save your profile and restart PowerShell. To reload your profile immediately, run the command:
. $profile
Functions are also very common customizations,
with the most popular of those being the Prompt function.
Although the Prompt function returns a simple string, you
can also use the function for more complex tasks. For example, many
users update their console window title (by changing the $host.UI.RawUI.WindowTitle variable) or use
the Write-Host cmdlet to output the
prompt in color. If your prompt function handles the screen output
itself, it still needs to return a string (for example, a single space)
to prevent PowerShell from using its default. If you don't want this
extra space to appear in your prompt, add an extra space at the end of
your Write-Host command and return
the backspace ("`b") character, as
shown in Example 1.3, “An example PowerShell prompt”.
Example 1.3. An example PowerShell prompt
function Prompt
{
$id = 1
$historyItem = Get-History -Count 1
if($historyItem)
{
$id = $historyItem.Id + 1
}
Write-Host -ForegroundColor DarkGray "`n[$(Get-Location)]"
Write-Host -NoNewLine "PS:$id > "
$host.UI.RawUI.WindowTitle = "$(Get-Location)"
"`b"
}In addition to showing the current location, this prompt also shows the ID for that command in your history. This lets you locate and invoke past commands with relative ease:
[C:\] PS:73 >5 * 5 25 [C:\] PS:74 >1 + 1 2 [C:\] PS:75 >Invoke-History 73 5 * 5 25 [C:\] PS:76 >
Although the profile referenced by $profile is the one you will almost always
want to use, PowerShell actually supports four separate profile scripts.
For further details of these scripts (along with other shell
customization options), see the section called “Common Customization Points”.
the section called “Enable Scripting Through an Execution Policy”
the section called “Common Customization Points”
an internal server error occurred when trying to access this link.
You want to accomplish a task in PowerShell but don't know the command or cmdlet to accomplish that task.
Use the Get-Command cmdlet to search for and
investigate commands.
To get the summary information about a specific command, specify the command name as an argument:
Get-Command CommandNameTo get the detailed information about a
specific command, pipe the output of Get-Command to the Format-List cmdlet:
Get-Command CommandName | Format-ListTo search for all commands with a name that contains text, surround the text with asterisk characters:
Get-Command *text*To search for all commands that use the
Get verb, supply Get to the -Verb parameter:
Get-Command -Verb GetTo search for all commands that act on a
service, supply Service to the
-Noun parameter:
Get-Command -Noun ServiceOne of the benefits that PowerShell provides
administrators is the consistency of its command names. All PowerShell
commands (called cmdlets) follow a regular
Verb-Noun pattern. For example: Get-Process, Get-EventLog, and Set-Location. The verbs come from a relatively
small set of standard verbs (as listed in Appendix Standard PowerShell
Verbs, Standard PowerShell Verbs), and describe
what action the cmdlet takes. The nouns are specific to the cmdlet and
describe what the cmdlet acts on.
Knowing this philosophy, you can easily learn
to work with groups of cmdlets. If you want to start a service on the
local machine, the standard verb for that is Start. A good guess would be to first try
Start-Service (which in this case
would be correct), but typing Get-Command -Verb
Start would also be an effective way to see what things you
can start. Going the other way, you can see what actions are supported
on services by typing Get-Command -Noun
Service.
See the section called “Get Help on a Command” for a way to list all commands along with a brief description of what they do.
The Get-Command cmdlet is one of the three
commands you will use most commonly as you explore Windows PowerShell.
The other two commands are Get-Help
and Get-Member.
There is one important point when it comes to
looking for a PowerShell command to accomplish a task. Many times, that
PowerShell command does not exist, because the task is best accomplished
the same way it always was: ipconfig.exe to get IP configuration
information, netstat.exe to list
protocol statistics and current TCP/IP network connections, and many
more.
For more information about the Get-Command cmdlet, type Get-Help Get-Command.
You want to learn about how a specific command works and how to use it.
The command that provides help and usage
information about a command is called Get-Help. It supports several different views
of the help information, depending on your needs.
To get the summary of help information for a
specific command, provide the command's name as an argument to the
Get-Help cmdlet. This primarily
includes its synopsis, syntax, and detailed description:
Get-Help CommandNameor
CommandName -?To get the detailed help information for a
specific command, supply the -Detailed flag to the Get-Help cmdlet. In addition to the summary
view, this also includes its parameter descriptions and examples:
Get-Help CommandName -DetailedTo get the full help information for a
specific command, supply the -Full
flag to the Get-Help cmdlet. In
addition to the detailed view, this also includes its full parameter
descriptions and additional notes:
Get-Help CommandName -FullTo get only the examples for a specific
command, supply the -Examples flag to
the Get-Help cmdlet:
Get-Help CommandName -ExamplesTo retrieve the most up-to-date online version
of a command's help topic, supply the -Online flag to the Get-Help cmdlet:
Get-Help CommandName -OnlineTo find all help topics that contain a given
keyword, provide that keyword as an argument to the Get-Help cmdlet. If the keyword isn't also the
name of a specific help topic, this returns all help topics that contain
the keyword, including its name, category, and synopsis:
Get-Help KeywordThe Get-Help cmdlet is the primary way to interact
with the help system in PowerShell. Like the Get-Command cmdlet, the
Get-Help cmdlet supports wildcards. If you want to
list all commands that match a certain pattern (for example,
*process*), you can simply type Get-Help *process*.
To generate a list of all cmdlets and aliases (along with their brief synopsis), run the following command:
This command gives a list of all Aliases, Cmdlets, Providers and HelpFiles
Get-Help * -Category Cmdlet | Select-Object Name,Synopsis | Format-Table -Auto
This command gives a list of all Aliases, Cmdlets, Providers and HelpFiles
If the pattern matches only a single command, PowerShell displays the help for that command. Although command wildcarding and keyword searching is a helpful way to search PowerShell help, see the section called “Program: Search Help for Text” for a script that lets you search the help content for a specified pattern.
In addition to console-based help, PowerShell also offers online and Compiled Help (CHM) versions of its help content. The Solution demonstrates how to quickly access online help content, but accessing the CHM version of help is slightly more difficult.
If you are working within PowerShell's Integrated Scripting Environment (ISE), accessing the CHM help is as easy as pressing F1.
If you are working on Windows 7, you can
access the CHM help through the Windows PowerShell
Help option in PowerShell's jump
list. To open PowerShell's jump list, either right-click
on the taskbar icon, or click the arrow beside PowerShell's icon in
the start menu.
I assume that there will be some sort of screenshot below
Figure 1.1. Launching PowerShell's Help Viewer
If you are working within the PowerShell console, you can access the CHM help by launching the .CHM file directly. the section called “Program: View PowerShell's HTML Help” demonstrates how to do this.
The Get-Help cmdlet is one of the three commands
you will use most commonly as you explore Windows PowerShell. The other
two commands are Get-Command and
Get-Member.
For more information about the Get-Help cmdlet, type Get-Help Get-Help.
Both the Get-Command and Get-Help cmdlets let you search
for command names that match a given pattern. However, when you don't know
exactly what portions of a command name you are looking for, you will more
often have success searching through the help content
for an answer. On Unix systems, this command is called Apropos.
The Get-Help cmdlet automatically searches the help database for keyword references when it can't find a help topic for the argument you supply. In addition to that, you might want to extend this even further to search for text patterns or even help topics that talk about existing help topics. PowerShell's help facilities don't support this type of search.
That doesn't need to stop us, though, as we can write the functionality ourselves.
To run this program, supply a search string to
the Search-Help script (given in Example 1.4, “Search-Help.ps1”). The search string can be either simple text
or a regular expression. The script then displays the name and synopsis of
all help topics that match. To see the help content for that topic, use
the Get-Help cmdlet.
Example 1.4. Search-Help.ps1
##############################################################################
param($pattern = $(throw "Please specify content to search for"))
$helpNames = $(Get-Help * | Where-Object { $_.Category -ne "Alias" })
foreach($helpTopic in $helpNames)
{
$content = Get-Help -Full $helpTopic.Name | Out-String
if($content -match $pattern)
{
$helpTopic | Select-Object Name,Synopsis
}
}
For more information about running scripts, see the section called “Run Programs, Scripts, and Existing Tools”
PowerShell's compiled help (CHM) offers many useful features: a table of contents, index, full-text search, and more. While easy to launch from the Integrated Scripting Environment (ISE) and the Windows 7 jump list, discoverability is still a problem from console windows.
To easily launch PowerShell's CHM help, use the
Show-HtmlHelp script.
Example 1.5. Show-HtmlHelp.ps1
<#
.SYNOPSIS
Launches the CHM version of PowerShell help.
.EXAMPLE
PS >Show-HtmlHelp
#>
$path = (Resolve-Path c:\windows\help\mui\*\WindowsPowerShellHelp.chm).Path
hh "$path::/html/defed09e-2acd-4042-bd22-ce4bf92c2f24.htm"
For more information about running scripts, see the section called “Run Programs, Scripts, and Existing Tools”
You want to launch a PowerShell session in a specific location.
Both Windows and PowerShell offer several ways to launch PowerShell in a specific location.
Explorer's address bar
PowerShell's command-line arguments
Community extensions
If you are browsing the file system with
Windows' Explorer, typing PowerShell into the address
bar launches PowerShell in that location.
Figure 1.2. Launching PowerShell from Windows Explorer

On my server 2008 R2 x64 box, this just launches powershell and loads my profile - it does not function like "Open PowerShell Here" from PSCX.
The resulting session lacks the console window
customizations defined by PowerShell's start menu link (as does
launching PowerShell from the Start | Run dialog, but
the section called “Customize the Shell to Improve Your Productivity” shows how to
make even these PowerShell windows display in PowerShell's signature
blue.
For another way to launch PowerShell from
Windows' Explorer, several members of the PowerShell community have
written power toys and Windows Explorer extensions that provide a
"Launch PowerShell Here" option when you right-click on a folder from
Windows Explorer. An Internet search for "PowerShell
Here" turns up several.
If you aren't browsing the desired folder with
Windows' Explorer, use PowerShell's -NoExit
parameter, along with the implied -Command parameter.
In the -Command parameter, call the
Set-Location cmdlet to initially move to your desired
location. From Start | Run (or any other means of
launching an application), type:
PowerShell -NoExit Set-Location 'C:\Program Files'
You want to invoke a PowerShell commad or script from a batch file, a logon script, scheduled task, or any other non-PowerShell application.
To invoke a PowerShell command, use the
-Command parameter:
PowerShell -Command Get-Process; Read-Host
To launch a PowerShell script, use the
-File parameter:
PowerShell -File 'full path to script' arguments
For example,
PowerShell -File 'c:\shared scripts\Get-Report.ps1' Hello World
By default, any arguments to
PowerShell.exe get interpreted as commands to run.
PowerShell runs the command as though you had typed it in the
interactive shell, and then exits. You can customize this behavior by
supplying other parameters to PowerShell.exe, such
as -NoExit, -NoProfile, and
more.
Since launching a script is so common,
PowerShell provides the -File parameter to eliminate
the complexities that arise from having to invoke a script from the
-Command parameter. This technique lets you invoke a
PowerShell script as the target of a logon script, advanced file
association, scheduled task and more.
When PowerShell detects that its input or
output streams have been redirected, it suppresses any prompts that
it might normally display. If you are want to host an interactive
PowerShell prompt inside another application (such as Emacs), use
"-" as the argument for the -File parameter. In
many shells, this implies "taken from standard input."
powershell -File -
If the script is for background automation or a scheduled task, these scripts can sometimes interfere with (or become influenced by) the user's environment. For these situations, three parameters come in useful:
-NoProfile. Runs the command or script without loading user profile scripts. This makes the script launch faster, but primarily prevents user preferences (i.e.: aliases and preference variables) from interfering with the script's working environment.
-WindowStyle. Runs
the command or script with the specified window style—most commonly
Hidden. When run with a WindowStyle of
Hidden, PowerShell hides its main window
immediately. For more ways to control the window style from
within PowerShell, see the section called “Launch a Process”.
-ExecutionPolicy. Runs the command or script with specified execution policy applied only to this instance of PowerShell. This lets you write PowerShell scripts to manage a system without having to change the system-wide execution policy. For more information about scoped execution policies, see the section called “Enable Scripting Through an Execution Policy”.
If you are the author of the program that needs to run PowerShell scripts or commands, PowerShell lets you call these scripts and commands much more easily than calling its command-line interface. For more information about this approach, see the section called “Add PowerShell Scripting to Your Own Program”.
If the arguments to the
-Command parameter become complex, special character
handling in the application calling PowerShell (such as
cmd.exe) might interfere with the command you want
to send to PowerShell. For this situation, PowerShell supports an
EncodedCommand parameter: a Base64
encoded representation of the Unicode string you want to run. Example 1.6, “Converting PowerShell commands into a Base64 encoded
form” demonstrates how
to convert a string containing PowerShell commands to a Base64 encoded
form.
Example 1.6. Converting PowerShell commands into a Base64 encoded form
$commands = '1..10 | % { "PowerShell Rocks" }'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($commands)
$encodedString = [Convert]::ToBase64String($bytes)Once you have the encoded string, you can use
it as the value of the EncodedCommand
parameter, as shown in Example 1.7, “Launching PowerShell with an encoded command from
cmd.exe”.
Example 1.7. Launching PowerShell with an encoded command from cmd.exe
Microsoft Windows [Version 6.0.6000] Copyright (c) 2006 Microsoft Corporation. All rights reserved. C:\Users\Lee>PowerShell -EncodedCommand MQAuAC4AMQAwACAAfAAgACUAIAB7ACAAIgBQAG8AdwBlAHIAUwBoAGUAbABsACAAUgBvAGMAawBzACIAIAB9AA== PowerShell Rocks PowerShell Rocks PowerShell Rocks PowerShell Rocks PowerShell Rocks PowerShell Rocks PowerShell Rocks PowerShell Rocks PowerShell Rocks PowerShell Rocks
The ? in the Encoded Command does not belong. Correct command is: MQAuAC4AMQAwACAAfAAgACUAIAB7ACAAIgBQAG8AdwBlAHIAUwBoAGUAbABsACAAUgBvAGMAawBzACIAIAB9AA==
For more information about running scripts, see the section called “Run Programs, Scripts, and Existing Tools”
You want to use the PowerShell console more efficiently for copying, pasting, history management, and scrolling.
Run the commands shown in Example 1.8, “Set-ConsoleProperties.ps1” to permanently customize your PowerShell console windows and make many tasks easier.
Example 1.8. Set-ConsoleProperties.ps1
Push-Location Set-Location HKCU:\Console New-Item '.\%SystemRoot%_system32_WindowsPowerShell_v1.0_powershell.exe' Set-Location '.\%SystemRoot%_system32_WindowsPowerShell_v1.0_powershell.exe' New-ItemProperty . ColorTable00 -type DWORD -value 0x00562401 New-ItemProperty . ColorTable07 -type DWORD -value 0x00f0edee New-ItemProperty . FaceName -type STRING -value "Lucida Console" New-ItemProperty . FontFamily -type DWORD -value 0x00000036 New-ItemProperty . FontSize -type DWORD -value 0x000c0000 New-ItemProperty . FontWeight -type DWORD -value 0x00000190 New-ItemProperty . HistoryNoDup -type DWORD -value 0x00000000 New-ItemProperty . QuickEdit -type DWORD -value 0x00000001 New-ItemProperty . ScreenBufferSize -type DWORD -value 0x0bb80078 New-ItemProperty . WindowSize -type DWORD -value 0x00320078 Pop-Location
These commands customize the console color, font, history storage properties, QuickEdit mode, buffer size, and window size.
With these changes in place, you can also improve your productivity by learning some of the hotkeys for common tasks, as listed in Table 1.2, “Partial list of Windows PowerShell hotkeys”. PowerShell uses the same input facilities as cmd.exe, and so brings with it all the input features that you are already familiar with—and some that you aren't!
Table 1.2. Partial list of Windows PowerShell hotkeys
Hotkey | Meaning |
|---|---|
Up arrow | Scan backward through your command history. |
Down arrow | Scan forward through your command history. |
PgUp | Display the first command in your command history. |
PgDown | Display the last command in your command history. |
Left arrow | Move cursor one character to the left on your command line. |
Right arrow | Move cursor one character to the right on your command line. |
Home | Move the cursor to the beginning of the command line. |
End | Move the cursor to the end of the command line. |
Control + Left arrow | Move the cursor one word to the left on your command line. |
Control + Right arrow | Move the cursor one word to the right on your command line. |
When you launch PowerShell from the link on your Windows Start menu, it customizes several aspects of the console window:
Foreground and background color, to make the console more visually appealing
QuickEdit mode, to make copying and pasting with the mouse easier
Buffer size, to make PowerShell retain the output of more commands in your console history
By default, these customizations do not apply when you run PowerShell from the Start→Run dialog. The commands given in the solution section improve the experience by applying these changes to all PowerShell windows that you open.
The hotkeys do, however, apply to all PowerShell windows (and any other application that uses Windows' cooked input mode). The most common are given in the in the solution section, but the section called “Common Customization Points” provides the full list.
In interactive use, full cmdlet names (such as
Get-ChildItem) are cumbersome and slow
to type. Although aliases are much more efficient, it takes a while to
discover them. To learn aliases more easily, you can modify your prompt to
remind you of the shorter version of any aliased commands that you
use.
This involves two steps:
Add the program,
Get-AliasSuggestion.ps1, shown in Example 1.9, “Get-AliasSuggestion.ps1”, to your tools directory or other
directory.
Example 1.9. Get-AliasSuggestion.ps1
param($lastCommand)
$helpMatches = @()
foreach($alias in Get-Alias)
{
if($lastCommand -match ("\b" +
[System.Text.RegularExpressions.Regex]::Escape($alias.Definition) + "\b"))
{
$helpMatches += "Suggestion: An alias for $($alias.Definition) is $($alias.Name)"
}
}
$helpMatches
Add the text from Example 1.10, “A useful prompt to teach you aliases for common
commands” to the Prompt function in your profile. If you do
not yet have a Prompt function, see
the section called “Customize Your Shell, Profile, and Prompt” to learn
how to add one. If you already have a prompt function, you only need
to add the content from inside the prompt function of Example 1.10, “A useful prompt to teach you aliases for common
commands”.
Example 1.10. A useful prompt to teach you aliases for common commands
function Prompt
{
$historyItem = Get-History -Count 1
if($historyItem)
{
$suggestions = @(Get-AliasSuggestion $historyItem.CommandLine)
if($suggestions)
{
foreach($aliasSuggestion in $suggestions)
{
Write-Host "$aliasSuggestion"
}
Write-Host ""
}
}
"PS [$env:COMPUTERNAME] >"
}For more information about running scripts, see the section called “Run Programs, Scripts, and Existing Tools”
Use the Get-ParameterAlias
script to return all aliases for parameters used by the previous command
in your session history.
Example 1.11. Get-ParameterAlias.ps1
##############################################################################
Set-StrictMode -Version Latest
$history = get-history -Count 1
if(-not $history)
{
return
}
$lastCommand = $history.CommandLine
$tokens = [System.Management.Automation.PsParser]::Tokenize(
$lastCommand, [ref] $null)
$currentCommand = $null
foreach($token in $tokens)
{
if($token.Type -eq "Command")
{
$currentCommand = $token.Content
}
if(($token.Type -eq "CommandParameter") -and ($currentCommand))
{
$currentParameter = $token.Content.TrimStart("-")
(Get-Command $currentCommand).Parameters.GetEnumerator() |
Where-Object { $_.Key -like "$currentParameter*" } |
Foreach-Object {
$_.Value.Aliases | Foreach-Object {
"Suggestion: An alias for the '$currentParameter' parameter" +
" of '$currentCommand' is '$_'"
}
}
}
}
To make it easy to type command parameters,
PowerShell lets you type only as much of the command parameter as is
required to disambiguate it from other parameters of that command. In
addition to shortening implicitly supported by the shell, cmdlet authors
can also define explicit aliases for their parameters—for example,
CN as a short-form for
ComputerName.
“Cmdlet” is capitalized in the middle of the sentence here.
While helpful, these aliases are difficult to discover.
“... define explicit aliases for their parameters - for example ...”
The hyphen-minus in there should probably be either U+2013 (–, En Dash) or U+2014 (—, Em Dash).
If you want to learn any aliases for
parameters in your previous command, simply run
Get-ParameterAlias.ps1. To make PowerShell do this
automatically, add a call to Get-ParameterAlias.ps1
in your prompt.
This script builds on two main features:
PowerShell's Tokenizer API, and the rich
information returned by the Get-Command cmdlet.
PowerShell's Tokenizer API examines its input and
returns PowerShell's interpretation of the input: commands, parameters,
parameter values, operators, and more. Like the rich output produced by
most of PowerShell's commands, Get-Command returns
information about a command's parameters, parameter sets, output type
(if specified), and more.
For more information about the tokenizer API, see the section called “Parse and Interpret PowerShell Scripts”.
After working in the shell for a while, you want to invoke commands from your history, view your command history, and save your command history.
The shortcuts given in the section called “Customize the Shell to Improve Your Productivity” let you manage your history, but PowerShell offers several features to help you work with your console in even more detail.
To get the most recent commands from your
session, use the Get-History
cmdlet:
Get-History
To rerun a specific command from your session
history, provide its Id to the Invoke-History cmdlet:
Invoke-History IdTo increase (or limit) the number of commands
stored in your session history, assign a new value to the $MaximumHistoryCount variable:
$MaximumHistoryCount = CountTo save your command history to a file, pipe
the output of Get-History to the
Export-CliXml cmdlet:
Get-History | Export-CliXml FilenameTo add a previously saved command history to your current session history, call the Import-CliXml cmdlet and then pipe that output to the Add-History cmdlet:
Import-CliXml Filename | Add-HistoryTo clear all commands from your session
history, use the Clear-History
cmdlet:
Clear-History
Unlike the console history hotkeys discussed
in the section called “Customize the Shell to Improve Your Productivity” the
Get-History cmdlet produces rich
objects that represent information about items in your history. Each
object contains that item's ID, command line, start of execution time,
and end of execution time.
Once you know the ID of a history item (as
shown in the output of Get-History),
you can pass it to Invoke-History to
execute that command again. The example prompt function shown in the section called “Customize Your Shell, Profile, and Prompt” makes working with
prior history items easy—as the prompt for each command includes the
history ID that will represent it.
The IDs provided by the Get-History cmdlet differ from the IDs given
by the Windows console common history hotkeys (such as F7), because
their history management techniques differ.
By default, PowerShell stores only the last 64
entries of your command history. If you want to raise or lower this
amount, set the $MaximumHistoryCount
variable to the size you desire. To make this change permanent, set the
variable in your PowerShell profile script.
After interactively experimenting at the command-line for a while to solve a multi-step task, you'll often want to keep or share the exact steps you used to eventually solve the problem. The script smiles at you from your history buffer, but is unfortunately surround by many more commands that you don't want to keep.
To solve this problem, use the
Get-History cmdlet to view the recent commands that
you've typed. Then, call Copy-History with the IDs of
the commands you want to keep.
Example 1.12. Copy-History.ps1
##############################################################################
param(
[int[]] $range
)
Set-StrictMode -Version Latest
$history = @()
if((-not $range) -or ($range.Count -eq 0))
{
$history = @(Get-History -Count ([Int16]::MaxValue))
}
elseif(($range.Count -eq 1) -and ($range[0] -lt 0))
{
$count = [Math]::Abs($range[0])
$history = (Get-History -Count $count)
}
else
{
foreach($commandId in $range)
{
if($commandId -eq -1) { $history += Get-History -Count 1 }
else { $history += Get-History -Id $commandId }
}
}
$history | Foreach-Object { $_.CommandLine } | clip.exe
For more information about running scripts, see the section called “Run Programs, Scripts, and Existing Tools”
You want to run a command from the history of your current session.
To invoke a specific command by its
ID:
Invoke-History ID
To search through your history for a command
containing text:
PS > #text<TAB>
To re-populate your command with the text of a
previous command by its ID:
PS > #ID<TAB>
Once you've had your shell open for a while, your history buffer quickly fills with useful commands. The history management hotkeys described in the section called “Customize the Shell to Improve Your Productivity” show one way to navigate your history, but this type of history navigation only works for command lines you've typed in that specific session. If you keep a persistent command history (as shown by the section called “Save State Between Sessions”), these shortcuts do not apply.
The Invoke-History cmdlet
illustrates the simplest example of working with your command history.
Given a specific history ID (perhaps shown in your prompt function),
calling Invoke-History with that ID will run that
commad again. For more information about this technique, see the section called “Customize Your Shell, Profile, and Prompt”.
As part of its tab-completion support,
PowerShell gives you easy access to previous commands, as well. If you
prefix your command with the # character, tab
completion takes one of two approaches:
ID completion. If you
type a number, tab completion finds the entry in your command
history with that ID, then replaces your command line with the text
of that history entry. This is especially useful when you want to
slightly modify a previous history entry, since
Invoke-History by itself doesn't support
that.
Pattern completion.
If you type anything else, tab completion searches for entries in
your command history that contain that text. Under the hood,
PowerShell uses the -like operator to match your
command entries, so you can use all of the wildcard characters
supported by that operator. For more information, on searching text
for patterns, see the section called “Search a String for Text or a Pattern”.
PowerShell's tab completion is largely driven
by the fully customizable TabExpansion function. You
can easily change this function to include more advanced functionality,
or even just customize specific behaviors to suit your personal
preferences. For more information, see the section called “Tab Completion”.
While PowerShell's built-in filtering facilities
are incredibly flexible (for example, the Where-Object
cmdlet), they generally operate against specific properties of the
incoming object. If you are searching for text in the object's formatted
output, or don't know which property contains the text you are looking
for, simple text-based filtering is sometimes helpful.
To solve this problem, you can pipe the output
into the Out-String cmdlet before passing it to the
Select-String cmdlet.
Select-TextOutput does exactly this, and lets you
search for a pattern in the visual representation of command
output.
Example 1.13. Select-TextOutput.ps1
param($pattern)
Set-StrictMode -Version Latest
$input | Out-String -Stream | Select-String $pattern
I think an example here would help with the understanding of the above script
I agree :) There's an example in the comments of the script, but those are unfortunately being dropped in the online version. We're working on getting them in properly.
For more information about running scripts, see the section called “Run Programs, Scripts, and Existing Tools”
You want to graphically explore and analyze the output of a command.
Use the Out-GridView cmdlet
to interactively explore the output of a command.
The Out-GridView cmdlet is
one of the rare PowerShell cmdlets that displays a graphical user
interface. While the Where-Object and
Sort-Object cmdlets are the most common way to sort
and filter lists of items, the Out-GridView cmdlet is
very effective at the style of repeated refinement that sometimes helps
you develop complex queries.
Figure 1.3. Out-GridView, Ready to Filter

Out-GridView lets you
primarily filter your command output in two ways: a quick
filter expression, and a criteria
filter.
Quick filters are fairly
simple. As you type text in the topmost "Filter" window,
Out-GridView filters the list to contain only items
that match that text. If you want to restrict this text filtering to
specific columns, simply provide a column name before your search string
and separate the two with a colon. You can provide multiple search
strings, in which case Out-GridView returns only rows
that match all of the required strings.
Unlike most filtering cmdlets in PowerShell,
the quick filters in the Out-GridView cmdlet do not
support wildcards or regular expressions. For this type of advanced
query, criteria-based filtering can help.
Criteria filters give
fine-grained control over the filtering used by the
Out-GridView cmdlet. To apply a criteria filter,
click the Add criteria button, and select a property
to filter on. Out-GridView adds a row below the quick
filter field, and lets you pick one of several operations to apply to
this property:
less than or equal to
greater than or equal to
between
equals
does not equal
contains
does not contain
In addition to these filtering options,
Out-GridView also lets you click and rearrange the
header columns to sort by them.
Once you've sliced and diced your command
output, you can select any rows you want to keep, and press
Ctrl-C to copy them to the clipboard.
Out-GridView copies the items to the clipboard as
tab-separated data, so you can easily paste the information into a
spreadsheet or other file for further processing.
Despite its clipboard output, exporting
items to the Out-GridView cmdlet is primarily a
one-way operation. While you can somewhat process items further by
exporting them to a spreadsheet or text file, there is no way to
access the results of sorting and filtering as full-fidelity objects.
For an approach that supports this type of full-fidelity filtering,
see the section called “Program: Interactively Filter Lists of Objects”, and a
graphical version at the section called “Program: Add a Graphical User Interface to Your Script”.
To redirect the output of a command into a
file, use either the Out-File cmdlet
or one of the redirection operators.
Out-File:
Get-ChildItem | Out-File unicodeFile.txt Get-Contentfilename.cs | Out-File -Encoding ASCIIfile.txtGet-ChildItem | Out-File -Width 120 unicodeFile.cs
There should be a space between Out-File and -Width in the third line.
Redirection operators:
Get-ChildItem >files.txtGet-ChildItem 2>errors.txt
The Out-File cmdlet and redirection operators
share a lot in common. 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 Out-File 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 PowerShell-formatted 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 PowerShell-formatted 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 Out-File cmdlet.
The default output encoding sometimes causes
unexpected results because PowerShell creates all files using the UTF-16
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 Out-File cmdlet.
For more information about the Out-File cmdlet, type Get-Help Out-File. For a full list of
supported redirection operators, see the section called “Capturing Output”.
You want to redirect the output of a pipeline into a file but add the information to the end of that file.
To redirect the output of a command into a
file, use either the -Append
parameter of the Out-File cmdlet, or
one of the appending redirection operators as described in the section called “Capturing Output”. Both support options to append text to
the end of a file.
Out-File:
Get-ChildItem | Out-File -Append files.txtRedirection operators:
Get-ChildItem >> files.txtThe Out-File cmdlet and redirection operators
share a lot in common. For the most part, you can use either. See the
discussion in the section called “Store the Output of a Command into a File” for a more
detailed comparison of the two approaches, including reasons that you
would pick one over the other.
To record a transcript of your shell session,
run the command Start-Transcript. It
has an optional -Path parameter that defaults to a
filename based on the current system time. By default, PowerShell places
this file in the My Documents
directory. To stop recording the transcript of your shell system, run
the command Stop-Transcript.
Although the Get-History cmdlet is helpful, it does not
record the output produced during your PowerShell session. To accomplish
that, use the Start-Transcript
cmdlet. In addition to the Path parameter described previously, the
Start-Transcript cmdlet also supports
parameters that let you control how PowerShell interacts with the output
file.
You want to use PowerShell cmdlets, providers, or script-based extensions written by a third party.
Use the Import-Module command to import third party commands into your PowerShell session.
To import a registered module by name:
Import-Module Name To import a module from a specific directory:
Import-Module c:\path\to\moduleTo import a module from a specific file (module, script, or assembly):
Import-Module c:\path\to\module\file.ext PowerShell supports two sets of commands that enable additional cmdlets and providers: *-Module, and *-PsSnapin. Snapins were the packages for extensions in version one of PowerShell. They supported only compiled extensions, and had onerous installation requirements.
Version two of PowerShell introduces modules that support everything that snapins support (and more) without the associated installation pain.
The most common way to import a module is by
name. PowerShell searches through every directory listed in the
PSModulePath environment variable, looking for
subdirectories that match the name you specify. Inside those
directories, it looks for the module (*.psd1,
*.psm1, and *.dll) with the same
name and loads it.
When you install a module on your own
system, the most common place to put it is in the
WindowsPowerShell\Modules directory in your
My Documents directory.
To have PowerShell look in another directory for modules, add
it to your personal PSModulePath environment
variable, just as you would add a Tools
directory to your personal Path.
If you want to load a module from a directory
not in PSModulePath, you can provide the entire
directory name and module name to the Import-Module
command. For example, for a module named
Test, Import-Module
. As with loading
modules by name, PowerShell looks in
c:\path\to\Testc:\temp\path\to for a module
(*.psd1, *.psm1, or
*.dll) named Test, and
loads it.
If you know the specific module file you want to load, you can also specify the full path to that module.
One popular source of additional commands is the PowerShell Community Extensions project, located at http://www.codeplex.com/PowerShellCX.
If you want to import these commands for every
PowerShell session, add a call to Import-Module to
your PowerShell Profile.
You want to use the commands from a PowerShell-based product that launches a customized version of the PowerShell console, but in a regular PowerShell session.
Launch the customized version of the
PowerShell console, then use the Get-Module and
Get-PsSnapin commands to see what additional modules
and / or snapins it loaded.
As described in the section called “Extend Your Shell with Additional Commands”, PowerShell
modules and snapins are the two ways that third parties can distribute
and add additional PowerShell commands. Products that provide customized
versions of the PowerShell console do this by calling
PowerShell.exe with one of three parameters:
-PSConsoleFile, to
load a console file that provides a list of snapins to
load.
-Command, to specify
an initial startup command (that then loads a snapin or
module.)
-File, to specify an
initial startup script (that then loads a snapin or
module.)
Regardless of which one it used, you can examine the resulting set of loaded extensions to see which ones you can import into your other PowerShell sessions.
The Get-PsSnapin command
returns all snapins loaded in the current session. It always returns
the set of core PowerShell snapins, but will also return any
additional snapins loaded by the customized environment. For example,
if the name of a snapin you recognize is
Product.Feature.Commands, you can load that
into future PowerShell sessions by typing Add-PsSnapin
Product.Feature.Commands. To
automate this, add the command into your PowerShell profile.
If you are uncertain of the snapin to load,
you can also use the Get-Command command to
discover which snapin defines a specific command:
PS > Get-Command Get-Counter | Select PsSnapin PSSnapIn -------- Microsoft.PowerShell.Diagnostics
Like the Get-PsSnapin
command, the Get-Module command returns all modules
loaded in the current session. It returns any modules you've added so
far into that session, but will also return any additional modules
loaded by the customized environment. For example, if the name of a
module you recognize is ProductModule, you
can load that into future PowerShell sessions by typing
Import-Module
ProductModule. To automate this,
add the command into your PowerShell profile.
If you are uncertain of the module to load,
you can also use the Get-Command command to
discover which module defines a specific command:
PS > Get-Command Start-BitsTransfer | Select Module Module ------ BitsTransfer
I think the above examples could be confusing to some users, first of all you need to snapin/module loaded to find out where it comes from. Secondly you have to know if the "cmdlet" comes from a Module or a Snapin
I think the above examples could be confusing to some users, first of all you need to snapin/module loaded to find out where it comes from. Secondly you have to know if the "cmdlet" comes from a Module or a Snapin
I think the above examples could be confusing to some users, first of all you need to snapin/module loaded to find out where it comes from. Secondly you have to know if the "cmdlet" comes from a Module or a Snapin
Subscribe to the
PowerShell.Exiting engine event to have PowerShell
invoke a script or script block that saves any state you need.
To have PowerShell save your command history,
place a call to Enable-HistoryPersistence in your
profile.
Example 1.14. Enable-HistoryPersistence.ps1
##############################################################################
Set-StrictMode -Version Latest
$GLOBAL:maximumHistoryCount = 32767
$historyFile = (Join-Path (Split-Path $profile) "commandHistory.clixml")
if(Test-Path $historyFile)
{
Import-CliXml $historyFile | Add-History
}
$null = Register-EngineEvent -SourceIdentifier `
([System.Management.Automation.PsEngineEvent]::Exiting) -Action {
$historyFile = (Join-Path (Split-Path $profile) "commandHistory.clixml")
$maximumHistoryCount = 1kb
$oldEntries = @()
if(Test-Path $historyFile)
{
$oldEntries = Import-CliXml $historyFile -ErrorAction SilentlyContinue
}
$currentEntries = Get-History -Count $maximumHistoryCount
$additions = Compare-Object $oldEntries $currentEntries `
-Property CommandLine | Where-Object { $_.SideIndicator -eq "=>" } |
Foreach-Object { $_.CommandLine }
$newEntries = $currentEntries | ? { $additions -contains $_.CommandLine }
$history = @($oldEntries + $newEntries) |
Sort -Unique -Descending CommandLine | Sort StartExecutionTime
Remove-Item $historyFile
$history | Select -Last 100 | Export-CliXml $historyFile
}
Shouldn't script files ideally only contain complete cmdlet names instead of aliases? Or are built-in aliases like Sort and Select ok?
Built-in aliases are OK, although I avoid them when they aren't clear.
I get this error when trying to run this.
You must provide a value expression on the right-hand side of the '-' operator. At C:UsersccarmichscriptsEnable-HistoryPersistence.ps1:21 char:62 + ([System.Management.Automation.PsEngineEvent]::Exiting) - <<<< Action { + CategoryInfo : ParserError: (:) [], ParseException + FullyQualifiedErrorId : ExpectedValueExpression
Disregard previous post. Some kind of weird cut & paste problem with the backtics.
PowerShell provides easy script-based access
to a broad variety of system, engine, and other events. You can register
for notification of, and even automatically process any of those events.
In this example, we subscribe to the only one currently available, which
is called PowerShell.Exiting. PowerShell generates
this event when you close a session.
For PowerShell to handle this event, you must use the
exit keyword to close your session, rather than the X
button at the top right of the console window. In the Integrated
Scripting Environment, the close button generates this event as
well
This script could do anything, but in this example we have it save our command history, and restore it when we launch PowerShell. Why would we want to do this? Well, with a rich history buffer, we can more easily find and re-use commands we've previously run. For two examples of doing this, see the section called “Access and Manage Your Console History”, and the section called “Invoke a Command From your Session History”.
Example 1.14, “Enable-HistoryPersistence.ps1”takes two main actions. First,
we load our stored command history (if any exists.) Then, we register an
automatic action to be processed whenever the engine generates its
PowerShell.Exiting event. The action itself is
relatively straight-forward, although exporting our new history does
take a little finesse. If you have several sessions open at the same
time, each will update the saved history file when it exits. Since we
don't want to overwrite the history saved by the other shells, we first
reload the history from disk and combine it with the history from the
current shell.
Once we have the combined list of command lines, we sort them and pick out the unique ones before storing them back in the file.
For more information about working with PowerShell engine events, see the section called “Create and Respond to Custom Events”.
1 comment
I will take this chapter to review
Add a comment