Windows PowerShell 的基本目标是使您能够以交互方式或通过脚本更好、更容易地对系统进行管理控制。本章综述了在用 Windows PowerShell 管理 Windows 系统时出现的很多特定问题的解决方案。尽管我们尚未在“Windows PowerShell 入门”中介绍脚本或函数,但随后可以在脚本中或作为函数使用这些解决方案。在提供的示例中,函数将作为解决问题的解决方案的一部分。
在整个解决方案说明中,您将看到使用特定 cmdlet 的解决方案、常规 Get-WmiObject cmdlet、甚至还有作为 Windows 和 .NET 基础结构组成部分的外部工具等诸多方案的混合体。使用外部工具是 Windows PowerShell 的长期设计意图的一部分。甚至随着系统不断发展,用户将继续遇到可用工具集无法完成所有任务的情况。Windows PowerShell 不鼓励仅仅依赖 cmdlet 实现,而是尝试支持将来自所有可能的替代方案的解决方案集成在一起。
核心进程 cmdlet 只有两个:Get-Process 和 Stop-Process。由于有可能使用参数或对象 cmdlet 来检查和筛选进程,因此可以只使用这两个 cmdlet 来执行一些复杂的任务。
通过无参数运行 Get-Process,可以获得正在本地系统中运行的所有进程的列表。
通过使用 ID 参数指定 ProcessId,还可以返回单个进程。以下示例将返回系统空闲进程:
PS> Get-Process -Id 0 Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 0 0 0 16 0 0 Idle |
尽管在某些情况下 cmdlet 不返回任何数据是正常的,但按其 ProcessId 指定进程时,如果 Get-Process 找不到匹配项,它将生成错误,因为它的常见用途是检索已知的正在运行的进程。如果不存在具有该 ID 的进程,则很可能是 ID 不正确,或者感兴趣的进程已经退出:
PS> Get-Process -Id 99 Get-Process :找不到 ID 为 99 的进程。 所在行:1 字符:12 + Get-Process <<<< -Id 99 |
Name 参数可以用来基于进程名称指定进程的子集。因为进程可以有相同名称,所以输出可能包括多个进程。如果不存在具有该名称的进程,则 Get-Process 将像指定 ProcessId 时一样返回错误。例如,如果指定进程名称 explore 而不是 explorer:
PS> Get-Process -Name explore Get-Process :找不到名称为“explore”的进程。 所在行:1 字符:12 + Get-Process <<<< -Name explore |
Name 参数支持使用通配符,因此可以键入名称的前几个字符并且后跟星号来获得列表:
PS> Get-Process -Name ex* Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 234 7 5572 12484 134 2.98 1684 EXCEL 555 15 34500 12384 134 105.25 728 explorer |
请注意:
因为 .NET System.Diagnostics.Process 类是 Windows PowerShell 进程的基础,因此它遵从 System.Diagnostics.Process 所使用的某些约定。这些约定之一是,可执行文件的进程名称永远不包括可执行文件名末尾的“.exe”。
Get-Process 还将接受 Name 参数的多个值。像指定单个名称一样,如果无法匹配名称,则尽管仍会获得匹配进程的正常输出,但将显示错误:
PS> Get-Process -Name exp*,power*,NotAProcess Get-Process :找不到名称为“NotAProcess”的进程。 所在行:1 字符:12 + Get-Process <<<< -Name exp*,power*,svchost,NotAProcess Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 540 15 35172 48148 141 88.44 408 explorer 605 9 30668 29800 155 7.11 3052 powershell |
Windows PowerShell 可让您灵活地列出进程,但如何停止进程呢?
Stop-Process cmdlet 采用 Name 或 ID 来指定希望停止的进程。是否能够停止进程取决于您的权限。某些进程不能停止。例如,如果试图停止空闲进程,则将获得错误:
PS> Stop-Process -Name Idle Stop-Process :由于以下错误无法停止进程“Idle (0)”: 访问被拒绝 所在行:1 字符:13 + Stop-Process <<<< -Name Idle |
还可以用 Confirm 参数强制进行提示。如果指定进程名称时使用通配符,则此参数特别有用,因为您可能意外匹配一些不想停止的进程:
PS> Stop-Process -Name t*,e* -Confirm 确认 是否确实要执行此操作? 对目标“explorer (408)”执行操作“Stop-Process”。 [Y] 是 [A] 全是 [N] 否 [L] 全否 [S] 挂起 [?] 帮助 (默认值为“Y”):n 确认 是否确实要执行此操作? 对目标“taskmgr (4072)”执行操作“Stop-Process”。 [Y] 是 [A] 全是 [N] 否 [L] 全否 [S] 挂起 [?] 帮助 (默认值为“Y”):n |
通过使用某些对象筛选 cmdlet,可以进行复杂的进程操作。由于进程对象有 Responding 属性,当进程不再响应时该属性将为 True,因此可以用以下命令停止所有无响应的应用程序:
Get-Process | Where-Object -FilterScript {$_.Responding -eq $false} | Stop-Process |
您可以在其他情况下使用相同的方法。例如,假设用户启动一个应用程序时另一个辅助的系统任务栏应用程序自动运行。您可能发现这在终端服务会话中无法正确工作,但仍然需要使它在物理计算机控制台上的会话中持续运行。连接到物理计算机桌面的会话的会话 ID 始终是 0,因此通过使用 Where-Object 和进程的 SessionId,可以停止在其他会话中的所有进程实例:
Get-Process -Name BadApp | Where-Object -FilterScript {$_.SessionId -neq 0} | Stop-Process |
可能偶尔需要能够停止除了当前会话以外所有正在运行的 Windows PowerShell 会话。如果会话正在使用太多资源,或者不可访问(它可能正在远程运行,或者在另一个桌面会话中),则可能无法直接停止它。但是,如果试图停止所有正在运行的会话,则可能终止当前会话。
每个 Windows PowerShell 会话都有环境变量 PID,其中包含 Windows PowerShell 进程的 ID。可以对照每个会话的 ID 检查该 $PID,并只终止有不同 ID 的 Windows PowerShell 会话。以下管道命令执行此操作,并返回被终止会话的列表(由于使用了 PassThru 参数):
PS> Get-Process -Name powershell | Where-Object -FilterScript {$_.Id -ne $PID} | Stop-Process - PassThru Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName ------- ------ ----- ----- ----- ------ -- ----------- 334 9 23348 29136 143 1.03 388 powershell 304 9 23152 29040 143 1.03 632 powershell 302 9 20916 26804 143 1.03 1116 powershell 335 9 25656 31412 143 1.09 3452 powershell 303 9 23156 29044 143 1.05 3608 powershell 287 9 21044 26928 143 1.02 3672 powershell |
共有八个核心服务 cmdlet,它们是为众多的服务任务设计的。我们将只介绍如何列出和更改服务的运行状态,但您可以使用 Get-Help *-Service 获得服务 cmdlet 的列表,还可以使用 Get-Help
通过使用 Get-Service,可以枚举计算机上的本地服务。与 Get-Process 一样,无参数使用 Get-Service 命令将返回所有服务。可以按名称筛选,甚至使用星号通配符:
PS> Get-Service -Name se* Status Name DisplayName ------ ---- ----------- Running seclogon Secondary Logon Running SENS System Event Notification Stopped ServiceLayer ServiceLayer |
由于服务的真实名称是什么并非始终是很明显的,因此您可能发现需要按显示名查找服务。可以按具体名称、使用通配符或使用显示名列表来执行该操作:
PS> Get-Service -DisplayName se* Status Name DisplayName ------ ---- ----------- Running lanmanserver Server Running SamSs Security Accounts Manager Running seclogon Secondary Logon Stopped ServiceLayer ServiceLayer Running wscsvc PS> Get-Service -DisplayName ServiceLayer,Server Status Name DisplayName ------ ---- ----------- Running lanmanserver Server Stopped ServiceLayer ServiceLayer |
所有服务 cmdlet 都有相同的常规形式。可以按公用名或显示名指定服务,并且可以用列表和通配符作为值。若要停止后台打印程序,请使用:
Stop-Service -Name spooler |
若要在后台打印程序停止之后启动它,请使用:
Start-Service -Name spooler |
若要挂起后台打印程序,请使用:
Suspend-Service -Name spooler |
Restart-Service cmdlet 的工作方式与其他服务 cmdlet 相同,但我们将介绍它的一些更复杂的示例。在最简单的使用中,可以指定服务的名称:
PS> Restart-Service -Name spooler 警告:正在等待服务“Print Spooler (Spooler)”完成启动... 警告:正在等待服务“Print Spooler (Spooler)”完成启动... PS> |
您将注意到,系统会显示有关后台打印程序正在启动的重复警告消息。在执行需要占用一定时间的服务操作时,Windows PowerShell 将通知您它仍在尝试执行该任务。
如果要重新启动多个服务,可以先获得服务列表,并对它们进行筛选,然后执行重新启动:
PS> Get-Service | Where-Object -FilterScript {$_.CanStop} | Restart-Service 警告:正在等待服务“Computer Browser (Browser)”完成停止... 警告:正在等待服务“Computer Browser (Browser)”完成停止... Restart-Service :无法停止服务“Logical Disk Manager (dmserver)”,因为具有依赖它的服务。只有在设置了 Force 标志时才能停止该服务。 所在行:1 字符:57 + Get-Service | Where-Object -FilterScript {$_.CanStop} | Restart-Service <<<< 警告:正在等待服务“Print Spooler (Spooler)”完成启动... 警告:正在等待服务“Print Spooler (Spooler)”完成启动... |
Get-WmiObject 是用于执行常规系统管理任务的最重要 cmdlet。所有关键的子系统设置都是通过 WMI 公开的。此外,WMI 将数据视为有一个或多个项目的集合中的对象。由于 Windows PowerShell 还能处理对象,并且它的管道允许您以相同方式对待单个或多个对象,因此,通用 WMI 访问可让您用非常少的工作量执行一些高级任务。
以下示例演示如何通过对任意计算机使用 Get-WmiObject 来收集特定信息。我们用表示本地计算机的点值 (.) 指定 ComputerName 参数。您可以指定与可以通过 WMI 访问的任何计算机关联的名称或 IP 地址。若要检索有关本地计算机的信息,可以省略 -ComputerName .
我们首先介绍用于收集本地计算机的桌面相关信息的命令。
Get-WmiObject -Class Win32_Desktop -ComputerName . |
此命令将返回所有桌面的信息,无论它们是否正在使用。
请注意:
某些 WMI 类返回的信息可能非常详细,并且通常包含有关 WMI 类的元数据。由于这些元数据属性的名称大