The simplest, most straightforward way to accomplish most tasks in Windows 11 is with the help of the graphical user interface—the dialogs and Settings pages where you can define preferences and change settings.
But just because that’s usually the most direct way doesn’t mean it’s the only way. Many of those tasks have an alternative that you can exercise via the command line or by making changes to the Windows registry. If you’re a system administrator or help desk technician, using command-line tools can save time, especially when you incorporate them into scripts. For some tasks, in fact, using a command-line tool is the only way to get a specific job done.
You have the option of performing command-line tasks in Windows 11 using the venerable Command Prompt (Cmd.exe) or the newer PowerShell. PowerShell, a .NET-based command-line shell and scripting language capable of working with every facet of Windows, is now the default shell in all currently supported Windows releases, desktop and server. You don’t have to choose sides, however. Windows 11 offers Windows Terminal as a host for both shells, with the option to use additional command-line environments such as Azure Cloud Shell and the Windows Subsystem for Linux; using this modern console, you can readily switch between any of those shells just by changing to a different tab.
We begin this chapter with a brief look at Windows Terminal and its customization options. We follow that with a more extensive introduction to the PowerShell language, with pointers to additional learning resources. Because of the ongoing importance of Command Prompt (Cmd.exe), this chapter also includes an overview of its most salient features. We also cover the powerful Registry Editor utility (Regedit.exe), starting with an explanation of how the Windows registry works, and we finish with a quick overview of the many advanced management tools based on the Microsoft Management Console.
It is possible to run Cmd.exe in its own window (technically, it runs in the Windows Console Host, Conhost.exe). You can also run the legacy Windows PowerShell app in its own window. But it’s easier and more productive to allow those command-line shells to run in the Windows Terminal application. This free, open-source application is installed by default in Windows 11 and available on the Quick Link menu. (For documentation on what’s in the latest Windows Terminal builds, see the releases page at Microsoft’s GitHub repository: https://github.com/microsoft/terminal/releases.)
One of the most appealing features of Windows Terminal is its support for multiple tabs, each of which can host a different command-line shell. To open a new tab using the default shell, click the plus sign to the right of the rightmost tab; to open a tab using a different shell, click the downward-pointing arrow at the right edge of the tab bar and choose an entry from the resulting dropdown.
Figure 16-1 shows Terminal in action, with three tabs open: one instance of Command Prompt, another of Ubuntu Linux, and a third running PowerShell.
Figure 16-1 Using tabs in Windows Terminal, you can keep multiple command-line environments running simultaneously.
Windows Terminal includes a profile for each command shell installed on your system. By default, this list includes Windows PowerShell (the legacy version), Command Prompt, and Azure Cloud Shell. When you install the newer, open source PowerShell 7, the installer automatically adds a profile for that shell; likewise, installing the Windows Subsystem for Linux adds a profile for your distribution.
Note the keyboard shortcuts at the right of each new-tab option on the menu. You can use these to open a new tab using the selected profile. To move forward and backward through your current collection of open tabs, press Ctrl+Tab or Ctrl+Shift+Tab.
To modify the way Windows Terminal works, choose Settings from the new-tab menu (or use the Ctrl+Comma [,] keyboard shortcut). Figure 16-2 shows the options available on the Startup tab.
Figure 16-2 Use these menu options to tell Windows Terminal which command-line shell you prefer.
The settings on the Startup page are probably the most useful and are worth a visit if you use Windows Terminal regularly:
Default Profile Select which profile you want to use when you launch Windows Terminal or when you click the plus sign to open a new tab.
Default Terminal Application This setting determines whether command-line apps that you launch using the Run command or the Start menu open in Windows Terminal or in an old-school Windows Console Host window.
Launch On Machine Startup Developers and administrators who use the command line regularly can invoke this option to ensure that a Windows Terminal session is always available.
When Terminal Starts The default setting opens a single tab with your default profile; if you prefer, you can opt to restore your previously open tabs.
Launch Mode The Default option will suffice for most casual users; the options that include the word Focus hide other tabs and suppress the title bar.
New Instance Behavior By default, opening a new Terminal session spawns a new window. Choose either alternative if you want new sessions to appear in the currently open window.
Launch Size The standard column and row assignments are adequate for casual users, but experienced developers might want to create a larger workspace.
After making any changes here, be sure to click the Save button!
Other pages on the Settings menu allow you to change the way Terminal sessions handle keyboard and mouse input, adjust the appearance of Terminal windows, and tweak keyboard shortcuts.
The options under the Profiles heading, shown in Figure 16-3, are a useful way to reduce clutter and improve productivity. For each profile, you can adjust the name that appears on the dropdown and on the tab title text. You can also adjust the icon and configure a profile so it always runs as an administrator.
Figure 16-3 Each available command-line shell has its own profile in Windows Terminal. Use the options here to customize, hide, or delete a profile.
If you’ve installed the newer PowerShell 7 and have no need for the legacy Windows PowerShell app, several options here are useful. You can hide the Windows PowerShell profile from the dropdown new-tab menu if you want to keep its settings available just in case, or choose its profile and click the big red Delete Profile button to remove its option from the dropdown. (Note that doing so does not delete the executable files for that legacy app.)
Microsoft describes PowerShell as a “cross-platform task automation solution made up of a command-line shell, a scripting language, and a configuration management framework.” Longtime Windows users and administrators can use PowerShell for the same kinds of chores they previously tackled with Command Prompt, and you can use its scripting power to automate routine management tasks. If you’re accustomed to using batch programs, VBScript, or JScript to automate administrative tasks, you can retain your current scripting investment but take advantage of the additional capabilities afforded by PowerShell’s object orientation and .NET support as your scripting needs grow.
Note
As we noted earlier, Windows 11 supports two versions of PowerShell. Windows PowerShell version 5.1 is the older product, designed for use exclusively with Windows and built on the .NET Framework v4.5. PowerShell version 7 is built on .NET Core and is a cross-platform solution. PowerShell can load many traditional Windows PowerShell modules without modification; for the rare instances where this option isn’t available, PowerShell 7 includes a Windows PowerShell Compatibility feature, which allows use of Windows PowerShell modules that require the full .NET framework. In this chapter, we assume that you’re using the newer, cross-platform PowerShell.
To download and install PowerShell 7, go to https://aka.ms/PSWindows. An even simpler option is to open Windows Terminal, open a Windows PowerShell session, and issue the command winget install Microsoft.PowerShell.
Among the advantages PowerShell offers over previous shells and scripting platforms are the following:
Integration with the Microsoft .NET Framework Like more traditional development languages, such as C#, PowerShell commands and scripts have access to the vast resources of the .NET Framework.
Object orientation and an object-based pipeline All PowerShell commands that generate output return .NET Framework objects rather than plain text, eliminating the need for text parsing when the output of one command provides input to a second.
A consistent, discoverable command model All of PowerShell’s commands (or “cmdlets,” as they are called) use a verb-noun syntax, with a hyphen separating the two components. All cmdlets that read information from the system begin with Get; all those that write information begin with Set. These and other similar consistencies make the language easy to learn and understand. Each cmdlet has a help topic that can be retrieved by typing get-help cmdletname (where cmdletname is the name of a cmdlet). You can use a -Whatif parameter to test the effect of a cmdlet before you execute it.
Universal scripting capability A PowerShell script is a text file, with the extension .ps1, containing PowerShell commands. Any commands that can be used interactively can be incorporated into a script. Scripting structures, such as looping, branching, and variables, can also be used interactively—that is, outside the context of a script.
A focus on administrators PowerShell includes features of particular interest to system administrators, such as the ability to work with remote computers; access to system resources such as files, folders, registry keys, events, and logs; and the ability to start and stop services.
Extensibility Developers and administrators can extend the PowerShell language by importing modules—packages of PowerShell cmdlets and other items. Modules exist for a variety of Microsoft products, including Azure, Windows Server, and Microsoft 365. Administrators can also find PowerShell modules that work with cloud services from providers other than Microsoft, including Amazon Web Services, VMware, and Google Cloud.
The following pages introduce PowerShell. Our discussion focuses primarily on the use of PowerShell as an interactive command shell, because PowerShell scripting is itself a book-length subject. For more sources of information, see “Finding additional PowerShell resources” later in this chapter.
PowerShell’s default appearance offers a minimal command-line interface similar to that of Command Prompt. The PowerShell label and logo in the tab title, along with the copyright notice and the letters PS at the beginning of the command line, also help to distinguish its appearance.
If you’re an old hand at the command line but new to PowerShell, the first thing you might want to try is using some of Command Prompt’s familiar internal commands. Most such items—for example, dir, cd, md, rd, pushd, and popd—still work in PowerShell. Redirection symbols, such as > to send output to a file and >> to append output to a file, work as well, and you can pipe lengthy output to More, just as you’re accustomed to doing in Command Prompt. PowerShell uses aliases to map Command Prompt commands to its own cmdlets. Thus, dir is an alias for the PowerShell cmdlet Get-Childitem; cd is an alias for PowerShell’s Set-Location. You can create your own aliases to simplify the typing of PowerShell commands that you use often; for details, see “Using and creating aliases” later in this chapter.
You can use PowerShell to launch executables, just as you would use any other command-line shell. Typing regedit, for example, launches Registry Editor; typing taskschd launches Task Scheduler. (Note that with PowerShell, you also can view and edit keys and values in the registry without the use of Registry Editor; for details, see “Working with the registry” later in this section.)
The core of PowerShell’s native vocabulary is a set of cmdlets, each consisting of a verb, followed by a hyphen, followed by a noun—for example, Start-Service. A cmdlet can be followed by one or more parameters; each parameter is preceded by a space and consists of a hyphen connected to the parameter’s name followed by a space and the parameter’s value. So, for example,
Get-Process -Name explorer
returns information about any currently running processes named explorer.
With parameters that accept multiple values, you can use a comma to separate the values. For example,
Get-Process -Name explorer, winword, excel
generates information about Microsoft Word and Excel as well as Windows Explorer.
Many cmdlets use positional parameters. For example, the -Name parameter for Get-Process is positional. PowerShell expects it to come first, so you can omit -Name and simply specify the names of the processes in which you’re interested.
If you omit both the first positional parameter and its value, PowerShell typically assumes a value of *. So, for example,
Get-Process
returns information about all running processes, as shown in Figure 16-4.
Figure 16-4 Entering the cmdlet Get-Process without parameters displays details about all running processes.
In some cases, if you omit values for an initial positional parameter, PowerShell prompts you to supply the parameter. For example, in response to
Get-Eventlog
PowerShell does you the courtesy of prompting for the name of an event log. (Event logs are large; it wouldn’t be reasonable to ask for all of them at once.)
For information about any particular cmdlet, type get-help followed by the cmdlet name.
You can use the pipe operator ( | ) to supply the output of one cmdlet as input to another. You can connect multiple cmdlets using the PowerShell pipeline, as long as each cmdlet to the right of a pipe operator understands the output of the cmdlet to its left. Because PowerShell cmdlets return full-fidelity .NET objects rather than text, a cmdlet to the right of a pipe operator can operate directly on properties or methods of the preceding cmdlet’s output.
The following paragraphs provide examples of the use of piping to format, filter, and sort the output from various Get- cmdlets.
The default output from many Get- cmdlets is a table that presents only some of the resultant object’s properties (about as many as the width of your display is likely to accommodate). For example, the cmdlet
Get-Service
generates a three-column display that includes only the Status, Name, and DisplayName properties.
If you pipe the same output to Format-List,
Get-Service | Format-List
PowerShell, which is no longer constrained by display width, can display more of the object’s properties (as shown in Figure 16-5), including in this case such useful items as the dependencies of each service and whether the service can be paused or stopped.
Figure 16-5 By piping a cmdlet to Format-List, you can see more of each resultant object’s properties.
In some cases, you’ll find the Format-List cmdlet, with no parameters, is equivalent to Format-List -Property *. But this is by no means always the case. For example,
Get-Process | Format-List
returns five properties for each process: ID, Handles, CPU, SI, and Name. Asking for all properties produces a wealth of additional information.
To generate a list of particular properties, add the -Property parameter to Format-List and supply a comma-separated list of the properties you want to see. To see what properties are available for the object returned by a cmdlet, pipe that cmdlet to Get-Member:
Get-Process | Get-Member -Membertype property
Perhaps you want tabular output but with different properties from those that your cmdlet gives you by default. Format-Table does the trick. For example,
Get-Service | Format-Table -Property name, dependentservices, servicesdependedon
generates a table consisting of these three enumerated properties. Note that PowerShell’s console output is constrained by your console width, no matter how many properties you ask to see. For results that are too wide to display, redirect output to a file (using the > operator) or try the Out-Gridview cmdlet, described next.
Piping the output to Out-Gridview generates a graphical tabular display you can filter, sort, and copy easily into other programs, such as Excel, that accommodate tabular data. For example,
Get-Process | Select-Object * | Out-Gridview
produces output comparable to that shown in Figure 16-6. Note that in this example, Get-Process is piped first to Select-Object * because Out-Gridview, unlike Format-Table, does not include a -Property parameter. Select-Object * passes all properties of the object returned by Get-Process along the pipeline to Out-Gridview.
Figure 16-6 The Out-Gridview cmdlet produces a graphical tabular display you can sort, filter, and copy into a spreadsheet.
You can manipulate the contents of the Out-Gridview window with techniques comparable to those used by many other programs:
To sort the display, click a column heading; click a second time to reverse the sort.
To change the position of a column, drag its heading. You can also rearrange columns by right-clicking any column head, choosing Select Columns, and then using the Move Down and Move Up buttons in the Select Columns dialog.
To remove columns from the display, right-click any column heading, click Select Columns, and then use the << button in the Select Columns dialog.
To perform a quick filter, enter text in the line labeled Filter. For example, to limit the display shown previously in Figure 16-6 to processes with properties containing the word beta, type beta on the Filter line.
To filter on one or more specific columns, click the Add Criteria button. In the drop-down list that appears, select check boxes for the columns on which you want to filter and then click Add.
To filter output from a cmdlet, pipe it to the Where-Object cmdlet. With Where-Object, you encapsulate filtering criteria in a script block, between curly braces. The following example filters output from Get-Service so that only services whose status is Stopped are displayed:
Get-Service | Where-Object {$_.Status -eq "Stopped"}
You can use the Sort-Object cmdlet to sort the output from a cmdlet on one or more of the resultant object’s properties in a variety of useful ways. If you omit the -Property parameter, Sort-Object sorts on the default property. For example,
Get-Childitem | Sort-Object
sorts the contents of the current directory by Name, the default property in this case. To sort on multiple properties, follow -Property with a comma-separated list. Sort-Object sorts on the first named property first, sorting items with identical values for the first property by the second property, and so on. Sorts are ascending by default; to sort in descending order, add the parameter -Descending.
By piping Sort-Object to Select-Object, you can do such things as return the largest or smallest n items in a resultant object. For example,
Get-Process | Sort-Object -Property WS | Select-Object -Last 10
returns the processes with the 10 largest values of the working set (WS) property. Using -First 10 instead of -Last 10 gives you the items with the smallest values.
To redirect output to the default printer, pipe it to Out-Printer. To use a nondefault printer, specify its name, in quotation marks, after Out-Printer. For example,
Get-Content C:\Users\EdBott\Documents\Inventory.txt | Out-Printer "Microsoft Print To PDF"
sends the content of C:\Users\EdBott\Documents\Inventory.txt to the device named Microsoft Print To PDF.
PowerShell is a wordy language and doesn’t take kindly to misspellings. Fortunately, it includes many features to streamline and simplify the task of formulating acceptable commands.
An alias is an alternative formulation for a cmdlet. As mentioned earlier, PowerShell uses aliases to translate Command Prompt commands to its own native tongue—for example, cd to Set-Location. But it includes a great many more simply for your typing convenience; gsv, for example, is an alias for Get-Service. And you can create aliases of your own.
To see what aliases are currently available (including any you created yourself during the current session), type get-alias. (Or just type gal, which is the alias for get-alias.) To see whether an alias is available for a particular cmdlet, pipe Get-Alias to Where-Object, like this:
Get-Alias | Where-Object { $_.definition -eq "Set-Variable" }
This particular command string inquires whether an alias is available for the Set-Variable cmdlet. If you type this, you discover that PowerShell offers two: sv and set. And if you think that Where-Object is too many characters to type, try replacing it with its alias, ?.
To create a new alias, type set-alias name value, where name is the alias and value is a cmdlet, function, executable program, or script. If name already exists as an alias, Set-Alias redefines it. If value is not valid, PowerShell doesn’t bother you with an error message—until you try to use the alias.
Aliases you create are valid for the current session only. To make them available permanently, include them in your profile. See “Using your profile to customize PowerShell” later in this chapter.
Aliases are useful for cmdlets, but they’re no help for parameter names. Fortunately, with PowerShell, you can abbreviate such names. The commands Get-Process -name explorer and Get-Process -n explorer are equivalent. As soon as you’ve typed enough of a parameter name to let PowerShell recognize it unambiguously, you can give your fingers a rest. And, of course, you can combine aliases with parameter abbreviations to further lighten your load.
As a further convenience, you can complete the names of files, cmdlets, or parameters by pressing Tab. Type part of a name, press Tab, and PowerShell presents the first potential completion. Continue pressing Tab to cycle through all the possibilities. Tab expansion works with all portions of a cmdlet, including verbs, nouns, and parameters.
Like all its Windows-shell predecessors, PowerShell supports the * and ? wildcards—the former standing in for any combination of zero or more characters, the latter for any single character. PowerShell also provides a vast panoply of “regular expressions” for matching character strings. For more details, go to https://learn.microsoft.com/search/?scope=PowerShell. Then search for regular_expressions. In general, you can use this method to get additional information about and documentation for any PowerShell topic.
PowerShell maintains a history of your recent commands, which makes it easy to reuse (or edit and reuse) a command you already entered. To see the history, type get-history. Each item in the history is identified by an ID number. Type invoke-history ID (where ID is the ID number) to bring an item to the command line. On the command line, you can edit an item before executing it. PowerShell maintains a history of commands that you can recall using shortcut keys that are identical to those available in a Command Prompt session. (For details, see “Editing the Command Line,” later in this chapter.)
The number of history items retained in a PowerShell session is defined by the automatic variable $MaximumHistoryCount. By default, that variable is set to 4096, which should be more than enough for anyone. If you find you need more, you can assign a larger number to the variable. For example, to double the default for the current session, type $MaximumHistoryCount = 8192. To change the history size for all sessions, add a variable assignment to your profile. For more information, see “Using your profile to customize PowerShell” later in this chapter.
PowerShell includes a set of built-in providers that give you access to various kinds of data stores. Providers are .NET Framework–based programs, and their data is exposed in the form of drives, comparable to familiar file-system drives. Thus, you can access a key in the HKLM registry hive with a path structure similar to that of a file-system folder; for example, the path HKLM:\Hardware\ACPI specifies the ACPI key of the Hardware key of the HKEY_LOCAL_MACHINE hive. Or, to use a quite different example, you can use the command Get-Childitem env: to get a list of current environment variables and their values.
Table 16-1 lists PowerShell’s built-in providers.
Table 16-1 Built-in providers
Provider |
Drive |
Data store |
---|---|---|
Alias |
Alias: |
Currently defined aliases |
Certificate |
Cert: |
X509 certificates for digital signatures |
Environment |
Env: |
Windows environment variables |
FileSystem |
(varies) |
File-system drives, directories, and files |
Function |
Function: |
PowerShell functions |
Registry |
HKLM:, HKCU: |
HKLM and HKCU registry hives |
Variable |
Variable: |
PowerShell variables |
WSMan |
WSMan: |
WS-Management configuration information |
The following paragraphs provide some basic information about working with the file system and registry.
For very simple file-system operations, you might find that familiar Command Prompt commands are adequate and easier to use than PowerShell cmdlets. The built-in aliases listed in Table 16-2 let you stick with time-honored methods. PowerShell supports the familiar single period (.) and double period (..) symbols for the current and parent directories, and it includes a built-in variable, $Home, that represents your home directory (by default, equivalent to the %UserProfile% environment variable).
Table 16-2 File-system aliases
Alias |
PowerShell cmdlet |
---|---|
cd, chdir |
Set-Location |
copy |
Copy-Item |
del |
Remove-Item |
dir |
Get-Childitem |
move |
Move-Item |
md, mkdir |
New-Item |
rd, rmdir |
Remove-Item |
type |
Get-Content |
The PowerShell cmdlets, however, include valuable optional parameters:
-Confirm and -Whatif The -Confirm parameter, used with Copy-Item, Move-Item, Remove-Item, or Clear-Content, causes PowerShell to display a confirmation prompt before executing the command. (Clear-Content can be used to erase the contents of a file.) If you use the -Whatif parameter, PowerShell shows you the result of a command without executing it.
-Credential Use the -Credential parameter to supply security credentials for a command that requires them. Follow -Credential with the name of a user, within double quotation marks. PowerShell will prompt for a password.
-Exclude You can use the -Exclude parameter to make exceptions. For example, -Copy-Item directory1\*.* directory2 -Exclude *.log copies everything, excluding all .log files, from Directory1 to Directory2.
-Recurse The -Recurse parameter causes a command to operate on subfolders of a specified path. For example, Remove-Item x:\garbagefolder\*.* -Recurse deletes everything from X:\Garbagefolder, including files contained within that folder’s subfolders.
-Include By using the -Include parameter in conjunction with -Recurse, you can restrict the scope of a command. For example, Get-Childitem c:\users\edbott\documents\* -Recurse -Include *.xlsx restricts a recursive listing of C:\Users\EdBott\Documents to files with the extension .xlsx.
-Force The -Force parameter causes a command to operate on items that are not ordinarily accessible, such as hidden and system files.
For detailed information about using these parameters with Set-Location, Get-Childitem, -Move-Item, Copy-Item, Get-Content, New-Item, Remove-Item, or Get-Acl, type get-help cmdletname, substituting the cmdlet name for the final argument. The results include the full syntax as well as any aliases for the specified cmdlet.
The built-in registry provider provides drives for two registry hives: HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER. To change the working location to either of these, type set-location hklm:\ or set-locati on hkcu:\, respectively. Use standard path notation to navigate to particular subkeys but enclose paths that include spaces in quotation marks—for example, set-location “hkcu:\control panel\accessibility”.
To display information about all subkeys of a key, use Get-Childitem. For example,
Get-Childitem -Path hkcu:\software\microsoft
returns information about all the subkeys of HKCU:\Software\Microsoft.
To add a key to the registry, use New-Item. For example,
New-Item -Path hkcu:\software\mynewkey
adds the key mynewkey to HKCU:\Software. To remove this key, type remove-item -path hkcu:\software\mynewkey.
To copy a key, use Copy-Item and specify the source and destination paths; for example:
Copy-Item -Path hkcu:\software\myk ey hkcu:\software\copyofmykey
To move a key, use Move-Item. The command
Move-Item -Path hkcu:\software\mykey -Destination hkcu:\software\myrelocatedkey
copies all properties and subkeys associated with HKCU:\Software\Mykey to HKCU:\Software\Myrelocatedkey and deletes HKCU:\Software\Mykey.
To display the security descriptor associated with a key, use Get-Acl. To see all the properties of the security descriptor, pipe this to Format-List -Property *. For example,
Get-Acl -Path hkcu:\software\microsoft | Format-List -Property *
generates a display comparable to the one shown in Figure 16-7.
Figure 16-7 You can work with values from the registry by using one of the two predefined providers for registry hives, in this case hkcu:.
Go to https://learn.microsoft.com/search/?scope=PowerShell and type registry for more information about working with the registry.
PowerShell provides plenty of resources to help you learn as you go. Type help for a quick overview of the PowerShell Help System and its key cmdlets, Get-Help and Update-Help.
You can display help information about any cmdlet by typing get-help cmdletname. If you do so on a fresh installation, Get-Help generates basic help information automatically for cmdlets, functions, and scripts. Type update-help to download the most recent help files for PowerShell modules and install them locally. (Note that that command requires that you be signed in as an administrator on Windows PowerShell but not in PowerShell 7.) After the help files are available locally, Get-Help returns a much more expansive set of results.
For example, to read help about Get-Process, type get-help get-process.
Among the useful parameters for Get-Help are the following:
-Examples To display only the name, synopsis, and examples associated with a particular help text, add the -Examples parameter.
-Parameter To get help for a particular parameter associated with a cmdlet, include -Parameter. Specify the parameter name in quotation marks.
-Detailed To get the description, syntax, and parameter details for a cmdlet, as well as a set of examples, use the -Detailed parameter. (Without this parameter, the examples are omitted; with -Examples, the syntax information is omitted.)
-Full For the works, including information about input and output object types and additional notes, specify -Full.
-Online For the latest information that Microsoft has, including additions or corrections to the native output of Get-Help, specify -Online. That parameter opens a browser window and displays relevant information from Microsoft’s online PowerShell documentation.
Using the Help command instead of Get-Help produces the full display of help information, with the help text pausing after each screenful.
The Get-Command cmdlet can help you figure out which cmdlet is the right one to use for a given task. Type get-command with no arguments to get the names and definitions of all available cmdlets, functions, and aliases. Get-Command can also give you information about non-PowerShell executables. If you type get-command *, for example, you get a huge list including all program files in all folders included in your current %Path% environment variable.
Either global list (with or without the non-PowerShell executables) is likely to be less than useful when you just want to know which cmdlets are available for use with a particular object. To get such a focused list, add the -Noun parameter. For example, type get-command -noun eventlog to get a list of the cmdlets that use that noun; you’re rewarded with the names and definitions of Clear-Eventlog, Get-Eventlog, Limit-Eventlog, New-Eventlog, Remove-Eventlog, Show-Eventlog, and Write-Eventlog. You can get a list focused similarly on a particular verb by using the -Verb parameter.
A PowerShell script is a text file with the extension .ps1. You can create a script in any plain text editor (Notepad will do fine), or you can use the Integrated Scripting Environment (ISE).
Anything you do interactively with PowerShell you can also do in a script. The reverse is true as well; you can take lines from a script, including those that involve looping or branching structures, and execute them individually outside the context of a script. For example, if you type
For ($i=1; $i -le 5; $i++) { "Hello, World" }
at the PowerShell command prompt, PowerShell performs the familiar greeting five times.
Using PowerShell’s history feature, you can transfer commands you have used interactively into a script. That way you can test to see what works and how it works before committing text to a .ps1 file.
For example, the command
Get-History | Foreach-Object { $_.commandline } >> c:\scripts\mynewscript.ps1
appends the CommandLine property from each item in your current history to the file C:\Scripts\Mynewscript.ps1. (If the path doesn’t exist, the command returns an error.) Once you have transferred your history to Mynewscript.ps1 in this manner, you can edit it in Notepad by typing notepad c:\scripts\mynewscript.ps1.
Although files with the extension .ps1 are executable PowerShell scripts, running one is not quite as straightforward as double-clicking a .bat file. In the first place, if you double-click a .ps1 file in File Explorer, it opens in Notepad because the default action for a PowerShell script in File Explorer is Edit.
Second, the first time you try to run a script by typing its name at the PowerShell command prompt, you might see a distressing message displayed in red letters and with possibly unwelcome detail. This means that PowerShell has declined to run your script “because running scripts is disabled on this system.” You need to change PowerShell’s execution policy, as described next.
Third, even after you’ve cleared the execution-policy hurdle, you might still be rebuffed if you try to run a script stored in the current directory. That’s because PowerShell requires a full path specification, even when the item you’re running is stored in the current directory. For example, to run a script named Displayprocessor.ps1 from the current directory, you must type .\displayprocessor.
PowerShell’s power can be used for evil ends. The majority of Windows users will never run PowerShell, but many will have .ps1 files lying about on their system or will download them inadvertently. To protect you from malware delivered in this fashion, PowerShell disables script execution until you explicitly enable it. Enabling execution requires a change to the execution policy.
Note that your profile script (if you have one) is subject to the same execution policy as any other script. (See “Using your profile to customize PowerShell” later in this chapter.) Therefore, it’s pointless to set an execution policy by means of a profile script; that script itself will not run until you’ve enabled script execution elsewhere.
The following execution policies, listed here from least permissive to most, are available:
Restricted The default policy. No scripts are allowed to run.
AllSigned Any script signed by a trusted publisher is allowed to run. PowerShell presents a confirmation prompt before running a script signed by a publisher that you have not designated as “trusted.”
RemoteSigned Scripts from local sources can run. Scripts downloaded from the internet (including scripts that originated as email or instant-messaging attachments) can run if signed by a trusted publisher.
Unrestricted All scripts can run, but PowerShell presents a confirmation prompt before running a script from a remote source.
Bypass All scripts are allowed to run.
Execution policies can be set separately for the following scopes:
Process Affects the current PowerShell session only. The execution policy is stored in memory and expires at the end of the session.
CurrentUser The execution policy is stored in a subkey of HKCU and applies to the current user only. The setting is retained between PowerShell sessions.
LocalMachine The execution policy is stored in a subkey of HKLM and applies to all users at this computer. The setting is retained between PowerShell sessions.
If policies are set at two or more of these scopes, the Process policy takes precedence over the CurrentUser policy, which takes precedence over the LocalMachine policy. Execution policy can also be set via Group Policy, however, and settings made in that manner trump any of the foregoing scopes. (Group Policy settings can be made in either the Computer Configuration or User Configuration node; a Computer Configuration setting trumps any other.)
To see the execution policies in effect at all scopes, type get-executionpolicy -list.
To set an execution policy, use Set-ExecutionPolicy. To set a policy at the LocalMachine scope, you need to be running PowerShell with administrative privileges.
The default scope for Set-ExecutionPolicy is LocalMachine, so if you’re planning to apply a policy to all users at your computer, you can omit the -Scope parameter. For example, if you’re comfortable disabling all of PowerShell’s script-execution security measures, including warning prompts, you can type set-executionpolicy bypass. For a slightly more protective environment, type set-executionpolicy unrestricted.
To set an execution policy at the CurrentUser or Process scope, add -Scope followed by CurrentUser or Process. Note that you can also set an execution policy at the Process scope by adding an -Executionpolicy argument to a command that launches PowerShell. For example, from a command prompt in Command Prompt, in PowerShell, or on the Start menu, you can type powershell -executionpolicy unrestricted to launch PowerShell with the Unrestricted execution policy at the Process scope.
To remove an execution policy from a particular scope, set that scope’s policy to Undefined. For example, if you set a Process policy to, say, Bypass, and you would like PowerShell to revert to the policy at the next level of precedence (CurrentUser, if a policy is set there, or LocalMachine, if not), type set-executionpolicy undefined -scope process.
Your profile is a script that PowerShell executes at the beginning of each session. You can use it to tailor your PowerShell environment to your preferences. Your profile must have the following path and file name:
$Home\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
where $Home is a system-generated PowerShell variable corresponding to the environment variable %UserProfile%. You can see where this is on your system by typing $profile, and you can edit an existing profile by typing notepad $profile. If you have not yet created a profile, you can type the following:
if (!(test-path $profile)){New-Item -Type file -Path $profile -Force}
PowerShell creates the file for you in the appropriate folder. Then you can type notepad $profile to edit the blank file.
You can use your profile to customize PowerShell in a variety of ways. Possibilities to consider include changing the default prompt and creating new aliases.
PowerShell’s prompt is derived from a built-in function called Prompt. You can overwrite that function with your own. For example, the function
Function prompt {"PS [$env:computername] $(Get-Date) > "}
replaces the built-in PowerShell prompt with the letters PS, followed by your computer name, followed by the current date and time.
To add new aliases to the ones PowerShell already offers, include Set-Alias statements in your profile. (See “Using and creating aliases” earlier in this chapter.)
A feature introduced with Windows PowerShell 2.0 allows you to issue commands and work with scripts in a graphical environment. This ISE includes a command pane, a script pane, and an output pane. The output pane displays the results of any commands you issue in the command pane or any scripts you run in the script pane. (Note that this app uses the legacy Windows PowerShell, not PowerShell 7.)
Windows PowerShell ISE is a desktop app that you can launch from Start. Alternatively, at a PowerShell prompt or in a Command Prompt window, type powershell_ise.
The ISE supports multiple tabs, so you can open several scripts at once. Click File > New to open a new blank tab (for example, to write a new script) or File > Open to open an existing script in a new tab. To run the current script, click Debug > Run/Continue, press F5, or click the green arrow in the middle of the toolbar. You can use other commands on the Debug menu to set and remove breakpoints and step through execution.
The ISE offers all the usual amenities of a graphical environment. You can resize and rearrange the panes, for example. You can use the View menu’s Zoom commands (or adjust the slider in the lower-right corner of the window) to make the text display larger or smaller. And you can easily select and copy text from one pane to another or from the ISE to another application.
The ISE uses its own profile, separate from the one you use to customize PowerShell itself. The path and file name are as follows:
$Home\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
and you create the file by typing:
if(!(Test-Path $profile)){New-Item -Type file -Path $profile -Force}
This chapter’s discussion of PowerShell has barely nicked the surface. You’ll find complete documentation for PowerShell at https://learn.microsoft.com/powershell/. For more about getting started in PowerShell, visit https://learn.microsoft.com/powershell/scripting/.
To open a Command Prompt session, run Cmd.exe (or double-click any shortcut for Cmd.exe). To open a separate Command Prompt window when one is already open, you can type start in the session that’s already running. The new session opens in a separate window of your default terminal app.
Your activities in a Command Prompt session are subject to the same User Account Control (UAC) restrictions as anything else you do in Windows. If you use Command Prompt to launch an app (for example, Registry Editor) that requires an administrative token, you’re asked to confirm a UAC prompt before moving on. If you plan to run several such tasks from Command Prompt, you might prefer to run Command Prompt itself with elevated privileges. To do this, use any of the following techniques:
Type cmd in the search box and press Ctrl+Shift+Enter.
Right-click any shortcut for Command Prompt and then click Run As Administrator, or press Ctrl+Shift as you click the shortcut or press Enter.
Open a Terminal session from the Quick Link menu, click the arrow to the right of the rightmost tab, point to Command Prompt on the dropdown, and hold down Ctrl as you click the command.
Open a Terminal (Admin) session from the Quick Link menu, click the arrow to the right of the rightmost tab, and choose Command Prompt from the dropdown, or use the Terminal shortcut Ctrl+Shift+2.
Windows displays the word Administrator in the title bar or tab title of any Command Prompt window running with elevated privileges.
If you open a Command Prompt session from Windows Terminal, your session opens in the folder specified in your Windows Terminal profile. By default, this location is the root of your user profile. (To adjust those settings, see the instructions earlier in this chapter, in “Using and configuring Windows Terminal.”)
If you run Command Prompt by typing cmd in the Start menu search box and then pressing Enter, Windows uses the default location: %HOMEDRIVE%%HOMEPATH%.
To run a Command Prompt session at a different folder, hold down the Shift key while you right-click the folder in File Explorer. On the shortcut menu, click Open In Terminal or Open PowerShell Window Here, and then enter cmd.
By using the /C and /K command-line arguments, you can start a Command Prompt session and immediately run a command or start an app, which we refer to as commandstring in this section. The difference between the two is that cmd /C commandstring terminates the Command Prompt session as soon as commandstring has finished, whereas cmd /K commandstring keeps the Command Prompt session open after commandstring has finished. Note the following:
You must include either /C or /K if you want to specify a command string as an argument to Cmd. If you type cmd commandstring, the command processor simply ignores commandstring.
While commandstring is executing, you can’t interact with the command processor. To run a command or start an app and keep the Command Prompt window interface, use the Start command. For example, to run Mybatch.bat and continue issuing commands while the batch program is running, type
cmd /k start mybatch.bat
If you include other command-line arguments along with /C or /K, /C or /K must be the last argument before commandstring.
By default, Command Prompt executes on startup whatever it finds in the following two registry values:
The AutoRun value in HKLM\Software\Microsoft\Command Processor
The AutoRun value in HKCU\Software\Microsoft\Command Processor
The AutoRun value in HKLM affects all user accounts on the current machine. The AutoRun value in HKCU affects only the current user account. If both values are present, both are executed—HKLM before HKCU. Both AutoRun values are of data type REG_SZ, which means they can contain a single string. To execute a sequence of separate Command Prompt statements, therefore, you must use command symbols or store the sequence as a batch program and then use AutoRun to call the batch program.
You can also use Group Policy objects to specify startup tasks for Command Prompt.
When working in a Command Prompt (Cmd.exe) session, you often enter the same command multiple times or enter several similar commands. To assist you with repetitive or corrective tasks, Windows includes a feature that recalls commands you previously issued in a Command Prompt window and allows you to edit them on the current command line. Table 16-3 lists these editing keys and what they do. (Many of these keys work in a PowerShell window as well.)
Table 16-3 Command-line editing keys
Key |
Function |
---|---|
Up Arrow or F3 |
Recalls the previous command in the command history |
Down Arrow |
Recalls the next command in the command history |
Page Up |
Recalls the earliest command used in the session |
Page Down |
Recalls the most recently used command |
Left Arrow |
Moves left one character |
Right Arrow |
Moves right one character |
Ctrl+Left Arrow |
Moves left one word |
Ctrl+Right Arrow |
Moves right one word |
Home |
Moves to the beginning of the line |
End |
Moves to the end of the line |
Esc |
Clears the current command |
F7 |
Displays the command history in a scrollable pop-up box |
F8 |
Displays commands that start with the characters currently on the command line |
Alt+F7 |
Clears the command history |
Old-fashioned programs that take all their input from a command line and then run unaided can be useful in a multitasking environment. You can turn them loose to perform complicated processing in the background while you continue to work with other programs in the foreground.
To work better with other programs, many command-line programs follow a set of conventions that control their interaction:
By default, programs take all their input as lines of text typed at the keyboard. But input in the same format also can be redirected from a file or any device capable of sending lines of text.
By default, programs send all their output to the screen as lines of text. But output in the same format also can be redirected to a file or another line-oriented device, such as a printer.
Programs set a number (called a return value) when they terminate to indicate the results of the program.
When programs are written according to these rules, you can use the symbols listed in Table 16-4 to control a program’s input and output or chain programs together.
Table 16-4 Command symbols
Symbol |
Function |
---|---|
< |
Redirects input |
> |
Redirects output |
>> |
Appends redirected output to existing data |
| |
Pipes output |
& |
Separates multiple commands in a command line |
&& |
Runs the command after && only if the command before && is successful |
|| |
Runs the command after || only if the command before || fails |
^ |
Treats the next symbol as a character |
( and ) |
Groups commands |
Command Prompt sessions in Windows allow you to override the default source for input (the keyboard) or the default destination for output (the screen).
To redirect output to a file, type the command followed by a greater-than sign (>) and the name of the file.
Using two greater-than signs (>>) redirects output and appends it to an existing file.
To redirect input from a file, type the command followed by a less-than sign (<) and the name of the file.
You can redirect both input and output in a command line. For example, to use Batch.lst as input to the Sort command and send its output to a file named Sorted.lst, type the following:
Sort < batch.lst > sorted.lst
Programs can be written to send their output either to the standard output device or to the standard error device. Sometimes programs are written to send different types of output to each device. You can’t always tell which is which because, by default, both devices are the screen.
The Type command illustrates the difference. When used with wildcards, the Type command sends the name of each matching file to the standard error device and sends the contents of the file to the standard output device. Because they both go to the screen, you see a nice display with each file name followed by its contents.
However, if you try to redirect output to a file by typing something like this:
type *.bat > std.out
the file names still appear on your screen because standard error is still directed to the screen. Only the file contents are redirected to Std.out.
With Windows, you can qualify the redirection symbol by preceding it with a number. Use 1> (or simply >) for standard output and 2> for standard error. For example:
type *.bat 2> err.out
This time, the file contents go to the screen and the names are redirected to Err.out.
The pipe symbol (|) is used to send, or pipe, the output of one app to a second app as the second app’s input. Piping is commonly used with the More command, which displays multiple screenfuls of output one screenful at a time. For example:
help dir | more
This command line uses the output of Help as the input for More. The More command filters out the first screenful of Help output, sends it to the screen as its own output, and then waits for a keystroke before sending more filtered output.
The Windows registry is the central storage location that contains configuration details for hardware, system settings, services, user customizations, applications, and every detail—large and small—that makes Windows work.
Note
The registry is the work of many hands, over many years, and capitalization and word spacing are not consistent. With readability as our goal, we made our own capitalization decisions for this book, and our treatment of names frequently differs from what you see in Registry Editor. No matter. Capitalization is irrelevant. Spelling and spacing must be correct, however.
Although it’s convenient to think of the registry as a monolithic database, its contents are actually stored in multiple locations as separate hive files, alongside logs and other support files. Some of those hive files are read into memory when the operating system starts; hive files that contain user-specific settings are stored in the user profile and are loaded when a new user signs in. (You can’t open a hive file directly except using Registry Editor.)
The Boot Configuration Data (BCD) store has its own file on the boot drive. The core hives for Windows—the Security Account Manager (SAM), Security, Software, and System—are securely stored in %SystemRoot%\System32\Config. Two hives that contain settings for local and network services are located in %SystemRoot%\ServiceProfiles\LocalService and %SystemRoot%\ServiceProfiles\NetworkService, respectively. User-specific hives are stored as part of the user profile folder.
The Hardware hive is unique in that it has no associated disk file. This hive, which contains details about your hardware configuration, is completely volatile; that is, Windows creates it anew each time you turn your system on.
Note
You can see where the hives of your system physically live by examining the values associated with HKLM\System\CurrentControlSet\Control\HiveList. Windows assigns drive letters after assembling the registry, so these paths do not specify drive letters.
Windows 11 is designed in such a way that direct registry edits by end users are generally unnecessary. When you change your configuration by using the Settings app or Control Panel, for example, Windows writes the necessary updates to the registry for you. Likewise, when you install a new piece of hardware or a new app, the app’s installer makes the required registry changes; you don’t need to know the details.
On the other hand, because the designers of Windows couldn’t provide a user interface for every conceivable customization you might want to make, sometimes working directly with the registry is the only way to make a change. Even when it’s not the only way, it might be the fastest way. Removing or modifying registry entries is occasionally a crucial part of troubleshooting and repair as well. Windows includes a registry editor you should know how to use—safely. This section tells you how.
Caution
Most Microsoft support articles contain a dire warning about the risks associated with editing the registry. We echo those warnings here. An incorrect registry modification can render your system unbootable and, in some cases, might require a complete reinstall of the operating system. Use Registry Editor at your own risk.
Registry Editor (Regedit.exe) offers a unified view of the registry’s contents as well as tools for modifying those contents. In Windows 11, Microsoft has removed this and other administrative tools from the All Apps list, but you can still find it using the search box. Alternatively, you can type regedit at a command prompt or in the Run dialog. Registry Editor has been virtually unchanged since the last century, with the exception of a few small improvements that debuted in the Windows 10 era: an address bar, new keyboard shortcuts for traversing the registry, options to save favorite registry locations for easier access, and the addition of a View > Font menu option that allows you to customize the font used when viewing or editing the contents of the registry.
Figure 16-8 shows a (mostly) collapsed view of the Windows 11 registry, as seen through Registry Editor.
Figure 16-8 The registry consists of five root keys, each of which contains many subkeys.
The Computer node appears at the top of the Registry Editor tree listing. Beneath it, as shown here, are five root keys: HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS, and HKEY_CURRENT_CONFIG. For simplicity’s sake and typographical convenience, this book, like many others, abbreviates the root key names as HKCR, HKCU, HKLM, HKU, and HKCC, respectively.
Root keys, sometimes called predefined keys, contain subkeys. Registry Editor displays this structure in a hierarchical tree in the left pane. In the previous Figure 16-8, for example, HKLM is open, showing its top-level subkeys.
Subkeys, which we call keys for short, can contain subkeys of their own, which in turn can be expanded as necessary to display additional subkeys. The address bar near the top of the Registry Editor window in the previous figure shows the full path of the currently selected key: Computer\HKLM\HARDWARE\DESCRIPTION\System\BIOS.
Note
One of the Registry Editor changes introduced in the Windows 10 era is the address bar. In it, you can type a registry path and press Enter to jump directly to that key, much as you can for jumping to a folder in File Explorer. For the root keys, you can type the full name or the commonly used abbreviations described earlier.
To go to the address bar and select its current content, press Alt+D or Ctrl+L, the same keyboard shortcuts that work in File Explorer as well as most web browsers.
The contents of HKEY_LOCAL_MACHINE define the workings of Windows itself, and its subkeys map neatly to several hives we mentioned at the start of this section. HKEY_USERS contains an entry for every existing user account (including system accounts), each of which uses the security identifier, or SID, for that account.
For a detailed discussion of the relationship between user accounts and SIDs, see the “What are security identifiers?” sidebar in Chapter 10, “Managing user accounts, passwords, and credentials.”
The remaining three predefined keys don’t exist, technically. Like the file system in Windows—which uses junctions, symlinks, and other trickery to display a virtual namespace—the registry uses a bit of misdirection (implemented with the REG_LINK data type) to create these convenient representations of keys that are actually stored within HKEY_LOCAL_MACHINE and HKEY_USERS:
HKEY_CLASSES_ROOT is merged from keys within HKLM\Software\Classes and HKEY_USERS\sid_Classes (where sid is the security identifier of the currently signed-in user).
HKEY_CURRENT_USER is a view into the settings for the currently signed-in user account, as stored in HKEY_USERS\sid (where sid is the security identifier of the currently signed-in user).
HKEY_CURRENT_CONFIG displays the contents of the Hardware Profiles\Current subkey in HKLM\SYSTEM\CurrentControlSet\Hardware Profiles.
Any changes you make to keys and values in these virtual keys have the same effect as if you had edited the actual locations. The HKCR and HKCU keys are generally more convenient to use.
Every key contains at least one value. In Registry Editor, that obligatory value is known as the default value. Many keys have additional values. The names, data types, and data associated with values appear in the right pane.
The default value for many keys is not defined. You can think of an empty default value as a placeholder—a slot that could hold data but currently does not.
All values other than the default always include the following three components: name, data type, and data. Figure 16-9, for example, shows customized settings for the current user’s Cloud Clipboard. (Note the full path to this key in the address bar at the top of the Registry Editor window.)
Figure 16-9 Selecting a key on the left displays all its values on the right.
The EnableClipboardHistory value is of data type REG_DWORD. The data associated with this value (on the system used for this figure) is 0x00000001. The prefix 0x denotes a hexadecimal value. Registry Editor displays the decimal equivalent of hexadecimal values in parentheses after the value.
The registry uses the following data types:
REG_SZ The SZ indicates a zero-terminated string. This variable-length string can contain Unicode as well as ANSI characters. When you enter or edit a REG_SZ value, Registry Editor terminates the value with a 00 byte for you.
REG_BINARY The REG_BINARY type contains binary data—0s and 1s.
REG_DWORD This data type is a “double word”—that is, a 32-bit numeric value. Although it can hold any integer from 0 to 232, the registry often uses it for simple Boolean values (0 or 1) because the registry lacks a Boolean data type.
REG_QWORD This data type is a “quadruple word”—a 64-bit numeric value.
REG_MULTI_SZ This data type contains a group of zero-terminated strings assigned to a single value.
REG_EXPAND_SZ This data type is a zero-terminated string containing an unexpanded reference to an environment variable, such as %SystemRoot%. (For information about environment variables, see “Interacting with PowerShell” earlier in this chapter.) If you need to create a key containing a variable name, use this data type, not REG_SZ.
Internally, the registry also uses REG_LINK, REG_FULL_RESOURCE_DESCRIPTOR, REG_RESOURCE_LIST, REG_RESOURCE_REQUIREMENTS_LIST, and REG_NONE data types. Although you might occasionally see references in technical documentation to these data types, they’re not visible or accessible in Registry Editor.
Because of the registry’s size, looking for a particular key, value, or data item can be daunting. In Registry Editor, the Find command (on the Edit menu and also available by pressing Ctrl+F) works in the forward direction only and does not wrap around when it gets to the end of the registry. If you’re not sure where the item you need is located, select the highest level in the left pane before issuing the command. If you have an approximate idea where the item you want is located, you can save time by starting at a node closer to (but still above) the target.
After you locate an item of interest, you can put it on the Favorites list to simplify a return visit. Open the Favorites menu, click Add To Favorites, and supply a friendly name (or accept the default). If you’re about to close Registry Editor and know you’ll be returning to the same key the next time you open the editor, you can skip the Favorites step because Registry Editor always remembers your last position and returns to that position in the next session.
Registry Editor includes a number of time-saving keyboard shortcuts for navigating the registry:
To move to the next subkey that starts with a particular letter, simply type that letter when the focus is in the left pane; in the right pane, use the same trick to jump to the next value that begins with that letter.
To open a key (revealing its subkeys), press Right Arrow or Alt+Right Arrow.
To collapse the subkeys of the current key, press Left Arrow or Alt+Left Arrow. With all subkeys collapsed, either action moves up one level in the subkey hierarchy. To move up a level without closing the subkeys as you move up, press Alt+Up Arrow.
To move to the top of the hierarchy, press Home.
To quickly move between the left and right panes, use the Tab key.
In the right pane, press F2 to rename a value, and press Enter to open that value and edit its data.
Some of these shortcuts match the behavior of File Explorer shortcuts, allowing you to apply your knowledge of that app to Registry Editor.
Once you are comfortable using these keyboard shortcuts, you’ll find it’s usually easier to zip through the subkey hierarchy with a combination of arrow keys and letter keys than it is to open outline controls with the mouse.
You can change the data associated with a value by selecting a value in the right pane and pressing Enter or by double-clicking the value. Registry Editor pops up an edit window appropriate for the value’s data type.
To add a key, select the new key’s parent in the left pane, open the Edit menu, point to New, and click Key. The new key arrives as a generically named outline entry, exactly the way a new folder does in File Explorer. Type a new name.
To add a value, select the parent key, open the Edit menu, and point to New. On the submenu that appears, click the type of value you want to add. A value of the type you select appears in the right pane with a generic name. Type over the generic name, press Enter twice, enter your data, and press Enter once more.
To delete a key or value, select it and then press Delete. Note that deleting a key also deletes every value and subkey associated with it.
One expert-level option is to use the Reg command in a Command Prompt window or in a batch file or script. It’s not uncommon, in fact, to see sites for Windows enthusiasts share commands using this syntax to make tweaks in the Windows user interface. Type reg /? to see the full list of eligible arguments for the reg command (query, add, export, import, and so on). Each of those variants has its own syntax help. Try reg add /? to see the correct syntax for adding a value.
Similarly, you can manipulate the registry using PowerShell commands. For more information, see “Working with the registry” earlier in this chapter.
Before you make any changes to the registry, consider using System Restore to set a restore point, which includes a snapshot of the registry as it currently exists. Taking this precaution allows you to roll back any ill-advised changes.
For information about using System Restore, see “Rolling back to a previous restore point” in Chapter 15, “Troubleshooting, backup, and recovery.”
In addition, or as an alternative, you can use the Export command in Registry Editor to back up the portion of the registry where you plan to work. Registry Editor can save all or portions of your registry in any of four different formats, but only one is relevant in the modern era.
The Registration Files option creates a .reg file, which is a text file that can be read and edited in Notepad or a similar app. A .reg file can be merged into the registry of a system running any version of Windows. When you merge a .reg file, its keys and values replace the corresponding keys and values in the registry. By using .reg files, you can edit your registry “offline” and add your changes to the registry without even opening Registry Editor. You can also use .reg files as an easy way to share registry settings and copy them to other computers.
To export a portion of the registry before you work on it, select a key in the left pane, and then click File > Export. (Easier still, right-click a key and click Export.) In the Save As Type list in the Export Registry File dialog, select Registration Files (*.reg). Under Export Range, choose Selected Branch and then click Save. The resulting file includes the selected key and all its subkeys and values.
Caution
Exporting a registry hive file using the Registry Hive Files format saves the entire hive; importing the saved file replaces the entire contents of the selected key with the contents of the file—regardless of its original source. That is, it wipes out everything in the selected key and then adds the keys and values from the file. The potential for chaos is obvious, and the benefits are not worth the risk, in our estimation.
If you saved your backup as a .reg file, you use the same process to import it. (As an alternative, you can double-click the .reg file in File Explorer without opening Registry Editor.) The complete path to each key and value is stored as part of the file, and it always restores to the same location. This approach for recovering from registry editing mishaps is fine if you did not add new values or subkeys to the section of the registry you’re working with; it returns existing data to its former state but doesn’t alter the data you added.
The .reg files created by the Export command in Registry Editor are plain text, suitable for reading and editing in Notepad or any similar editor. Therefore, they provide an alternative method for editing your registry. You can export a section of the registry, change it offline, and then merge it back into the registry. Or you can add new keys, values, and data to the registry by creating a .reg file from scratch and merging it. A .reg file is particularly useful if you need to make the same changes to the registry of several computers. You can make and test your changes on one machine, save the relevant part of the registry as a .reg file, and then import the saved file to the registry on other machines that require it.
Every .reg file includes the following elements:
Header line The file begins with the line “Windows Registry Editor Version 5.00.” When you merge a .reg file into the registry, Registry Editor uses this line to verify that the file contains registry data. Version 5 (the version used with Windows 7 and later versions, up to and including Windows 11) generates Unicode text files, which can be used with all supported versions of Windows as well as the now-unsupported Windows XP and Windows 2000.
Key names Key names are delimited by brackets and must include the full path from the root key to the current subkey. The root key name must not be abbreviated. (Don’t use HKCU, for example.)
The default value Undefined default values do not appear in .reg files. Defined default values are identified by the special character @. Thus, a key whose default REG_SZ value was defined as MyApp would appear in a .reg file this way:
"@"="MyApp"
Value names Value names must be enclosed in quotation marks, regardless of whether they include space characters. Follow the value name with an equal sign.
Data types REG_SZ values don’t get a data type identifier or a colon. The data directly follows the equal sign. Other data types are identified as shown in Table 16-5.
Table 16-5 Data types identified in .reg files
Data type |
Identifier |
---|---|
REG_BINARY |
hex |
REG_DWORD |
dword |
REG_QWORD |
hex(b) |
REG_MULTI_SZ |
hex(7) |
REG_EXPAND_SZ |
hex(2) |
A colon separates the identifier from the data. Thus, for example, a REG_DWORD value named “Keyname” with value data of 00000000 looks like this:
"Keyname"=dword:00000000
REG_SZ values Ordinary string values must be enclosed in quotation marks. A backslash character within a string must be written as two backslashes. Thus, for example, the path C:\Program Files\Microsoft Office\ is written like this:
" C:\\Program Files\\Microsoft Office\\"
REG_DWORD values DWORD values are written as eight hexadecimal digits, without spaces or commas. Do not use the 0x prefix.
All other data types Other data types—including REG_EXPAND_SZ, REG_MULTI_SZ, and REG_QWORD—appear as comma-delimited lists of hexadecimal bytes (two hex digits, a comma, two more hex digits, and so on). The following is an example of a REG_MULTI_SZ value:
"Addins"=hex(7):64,00,3a,00,5c,00,6c,00,6f,00,74,00,00,75,00,73,00,5c,00,\
31,00,32,00,33,00,5c,00,61,00,64,00,64,00,64,00,69,00,6e,00,73,00,5c,00,\
64,00,71,00,61,00,75,00,69,00,2e,00,31,00,32,00,61,00,00,00,00,00,00,00
Line-continuation characters You can use the backslash as a line-continuation character. The REG_MULTI_SZ value just shown, for example, is all one stream of bytes. We added backslashes and broke the lines for readability, and you can do the same in your .reg files.
Line spacing You can add blank lines for readability. Registry Editor ignores them.
Comments To add a comment line to a .reg file, begin the line with a semicolon.
.Reg files are most commonly used to modify existing registry data or add new data. But you can also use them to delete existing values and keys.
To delete an existing value, specify a hyphen character (minus sign) as the value’s data. For example, to use a .reg file to remove the value ShellState from the key HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer, add the following line to the .reg file:
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer]"ShellState"=-
To delete an existing key with all its values and data, insert a hyphen in front of the key name (inside the left bracket). For example, to use a .reg file to remove the key HKCR\.xyz\shell and all its values, add the following to the .reg file:
[-HKEY_CLASSES_ROOT\.xyz\shell]
To merge a .reg file into the registry from within Registry Editor, open the File menu and click Import. Registry Editor adds the imported data under the appropriate key names, overwriting existing values where necessary.
The default action for a .reg file is Merge—meaning merge with the registry. Therefore, you can merge a file into the registry by simply double-clicking it in File Explorer and answering the confirmation prompt.
One of the longstanding fundamental principles of security in Windows is that it prevents apps running under a standard user’s token from writing to system folders in the file system and to machine-wide keys in the registry. Windows 11 respects that principle while still enabling users with a standard account to run apps without running into “access denied” roadblocks.
That’s a particular challenge with older applications that require administrator-level access. Those apps are usable in Windows 11, even by standard users. The secret? User Account Control uses registry virtualization to redirect attempts to write to subkeys of HKLM\Software. (Settings in HKLM apply to all users of the computer; therefore, only administrators have write permission.) When an application attempts to write to this hive, Windows writes instead to a per-user location, HKCR\VirtualStore\Machine\Software. Like file virtualization, this is done transparently; the application (and all but the most curious users) never know this is going on behind the scenes.
Note
When an app requests information from HKLM\Software, Windows looks first in the virtualized key if it exists. Therefore, if a value exists in both the VirtualStore hive and in HKLM, the app sees only the one in VirtualStore.
Note that because the virtualized data is stored in a per-user section of the registry, settings made by one user do not affect other users.
For more information about registry virtualization, see https://bit.ly/registry-virtualization.
Windows 11 provides several ways to automate tasks. The built-in Task Scheduler tool allows you to create tasks using a point-and-click interface; batch commands and scripts, especially those using Windows PowerShell, represent the most common automation alternative.
Task Scheduler is a Microsoft Management Console (MMC) snap-in that supports an extensive set of triggering and scheduling options. Scheduled tasks can run programs or scripts at specified times, launch actions when a computer has been idle for a specified period of time, run tasks when particular users sign in or out, and so on. Task Scheduler is also tightly integrated with the Event Viewer snap-in, making it possible to use events (an application crash or a disk-full error, for example) as triggers for tasks.
Windows and third-party apps make extensive use of Task Scheduler to set up maintenance activities that run on various schedules. You can also create custom tasks. To see the full library of tasks, click Start, type task, and open the Task Scheduler app. To create a task, open Task Scheduler and click Action > Create Basic Task. For full documentation on this tool, see https://learn.microsoft.com/windows/win32/taskschd/using-the-task-scheduler.
For automating administrative tasks on a business network, PowerShell scripts are the preferred solution. (We discuss these useful resources earlier in this chapter, in “Scripting with PowerShell.”) But for file management and other simple tasks, old-fashioned batch programs are still useful.
A batch program (also commonly called a batch file) is a text file with a .bat filename extension (.cmd is also a valid filename extension) that contains a sequence of commands to be executed. You execute the commands by entering the file name at a command prompt. Any action you can take by typing a command at a command prompt can be encapsulated in a batch program.
When you type the name of your batch program at the command prompt (or when you specify it as a task to be executed by Task Scheduler and the appropriate trigger occurs), the command interpreter opens the file and starts reading the statements. It reads the first line, executes the command, and then goes on to the next line. On the surface, this seems to operate just as though you were typing each line yourself at the command prompt. In fact, however, the batch program can be more complicated because the language includes replaceable parameters, conditional and branching statements, the ability to call subroutines, and so on. Batch programs can also respond to values returned by programs and to the values of environment variables.
Microsoft Windows Script Host (WSH) provides a way to perform more sophisticated tasks than the simple jobs that batch programs are able to handle. You can control virtually any component of Windows and of many Windows-based programs with WSH scripts.
Run a script by typing a script name at a command prompt or double-click the script’s icon in File Explorer. WSH has two nearly equivalent programs—Wscript.exe and Cscript.exe—that, with the help of a language interpreter dynamic-link library such as Vbscript.dll, execute scripts written in VBScript or another scripting language. (Cscript.exe is a command-line program; Wscript.exe is its graphical counterpart.)
With WSH, the files can be written in several languages, including VBScript (a scripting language similar to Microsoft Visual Basic) and JScript (a form of JavaScript). All the objects are available to any language, and in most situations, you can choose the language with which you are most comfortable. WSH doesn’t care what language you use, provided the appropriate interpreter dynamic-link library is available. VBScript and JScript interpreters come with Windows 10 and Windows 11; interpreters for Perl, KiXtart (KixKIXE), Python, RexxHex, and other languages are available elsewhere.
Microsoft Management Console (MMC) is an application that hosts tools for administering computers, networks, and other system components. By itself, MMC performs no administrative services. Rather, it acts as the host for one or more modules, called snap-ins, which do the useful work. MMC provides user-interface consistency so that you or the users you support see more or less the same style of application each time you need to carry out some kind of computer management task. A combination of one or more snap-ins can be saved in a file called a Microsoft Common Console Document or, more commonly, an MMC console.
Creating snap-ins requires expertise in programming. You don’t have to be a programmer, however, to make your own custom MMC consoles. All you need to do is run MMC, start with a blank console, and add one or more of the snap-ins available on your system. Alternatively, you can customize some of the MMC consoles supplied by Microsoft or other vendors simply by adding or removing snap-ins. You might, for example, want to combine the Services console with the Event Viewer console, the latter filtered to show only events generated by services. You might also want to include a link to a website that offers details about services and service-related errors. Or perhaps you would like to simplify some of the existing consoles by removing snap-ins you seldom use.
MMC consoles use, by default, the file name extension .msc, and .msc files are associated by default with MMC. Thus, you can run any MMC console by double-clicking its file name in a File Explorer window or by entering the file name at a command prompt. Windows 11 includes several predefined consoles; the most commonly used ones, described in Table 16-6, can be easily found by typing their name in the search box.
Table 16-6 Useful predefined consoles
Console name (file name) |
Description |
---|---|
Certificate Manager (Certmgr.msc) |
Uses the Certificates snap-in to view and manage security certificates for the current user. A similar console, Certlm.msc, manages certificates on the local machine. |
Computer Management (Compmgmt.msc) |
Includes the functionality of the Task Scheduler, Event Viewer, Shared Folders, Local Users And Groups, Performance, Device Manager, Disk Management, Services, and WMI Control snap-ins, providing control over a wide range of computer tasks. |
Device Manager (Devmgmt.msc) |
Uses the Device Manager snap-in to enable administration of all attached hardware devices and their drivers. See Chapter 13 for more information on configuring hardware. |
Disk Management (Diskmgmt.msc) |
Uses the Disk Management snap-in for configuring disk volumes and partitions. For details, see “Setting up hard disks and other storage devices,” in Chapter 8. |
Event Viewer (Eventvwr.msc) |
Uses the Event Viewer snap-in to display all types of logged information. See “Event Viewer” in Chapter 15. |
Hyper-V Manager (Virtmgmt.msc) |
Uses the Hyper-V Manager snap-in to provide an environment for creating, modifying, and running virtual machines. See Chapter 17, “Running Windows 11 in a virtual machine or in the cloud,” for details. |
Local Group Policy Editor (Gpedit.msc) |
Uses the Local Computer Policy snap-in to configure policies that can be applied to a local machine or to a user account. See “Managing computers with Group Policy” in Chapter 19. |
Local Users and Groups (Lusrmgr.msc) |
Uses the Local Users and Groups snap-in to manage local user accounts and security groups. For more information, see “Creating and managing user accounts” in Chapter 10. |
Performance Monitor (Perfmon.msc) |
Uses the Performance Monitor snap-in to provide a set of monitoring tools. See Chapter 14, “Performance and power management,” for details. |
Print Management (Print-management.msc) |
Uses the Print Management snap-in for managing printers and print jobs. |
Services (Services.msc) |
Uses the Services snap-in to manage services in Windows. For details, see “Managing services” in Chapter 14. |
Task Scheduler (Taskschd.msc) |
Uses the Task Scheduler snap-in for managing tasks that run automatically. |
Trusted Platform Module (TPM) Management (Tpm.msc) |
Displays information about and enables configuration of a computer’s TPM chip. |
Windows Firewall With Advanced Security (Wf.msc) |
Uses the Windows Firewall With Advanced Security snap-in to configure rules and make other firewall settings. For details, see “Managing Windows Defender Firewall” in Chapter 12, “Windows security and privacy.” |