Windows PowerShell 学习笔记其一(特性介绍)

PowerShell 是一个跨平台的自动化和配置工具(框架),在处理结构化数据(如 JSON、CSV、XML 等)、REST API对象模型方面做了大量针对性的优化。
它是一个基于任务的命令行终端,同时也是一个构建在 .NET 上的脚本语言。对于自动化系统管理任务有极大的帮助。

其基本特性如下

  • PowerShell 可以与基础的 Windows 命令和应用完美整合
  • 引入了一种新的命令形式(cmdlets),使用 Verb-Noun 形式的语法,对比普通命令有更高的灵活度
  • PowerShell 能够“理解”对象,可以直接处理结构化的数据对象,区别于普通 Shell 的“纯文本”
  • 可以同多种技术直接整合使用。如 .NET、COM、WMI、XML 和活动目录等
  • 简单化 data store 的管理(使用和管理文件同样的技术)
结构化命令(Cmdlets)

PowerShell 引入了一种名为 Cmdlets 的新型命令。所有的 cmdlets 命令都以 Verb-Noun 的形式命名,如 Get-ProcessGet-ContentStop-Process 等。

1
2
3
4
5
6
7
8
9
PS C:\Users\starky> Get-Process -Name chrome

Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
285 36 80040 93808 620 104.61 1384 chrome
201 16 9000 7296 121 0.05 3572 chrome
1061 73 57324 99924 550 145.21 4052 chrome
221 17 8864 7952 131 0.08 5832 chrome
260 30 209528 154748 534 118.55 6408 chrome

在交互式的命令行环境下,可以使用 <TAB> 键自动补全命令和参数。
如上述命令也可以这样输入:
Get-Pr<TAB> -N<TAB> c<TAB>

大部分 Verb-Noun 形式的命令手动输入时仍显得有些长,所以 PowerShell 为所有常用的命令提供了简短的别名
Get-Process 的别名即为 gps

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
PS C:\Users\starky> gps -n explorer

Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
841 56 36280 35632 279 6.36 2552 explorer


PS C:\Users\starky> Get-Alias

CommandType Name ModuleName
----------- ---- ----------
Alias % -> ForEach-Object
Alias ? -> Where-Object
Alias ac -> Add-Content
Alias asnp -> Add-PSSnapin
Alias cat -> Get-Content
Alias cd -> Set-Location
Alias chdir -> Set-Location
Alias clc -> Clear-Content
Alias clear -> Clear-Host
Alias clhy -> Clear-History
Alias cli -> Clear-Item
Alias clp -> Clear-ItemProperty
Alias cls -> Clear-Host
Alias clv -> Clear-Variable
Alias cnsn -> Connect-PSSession
Alias compare -> Compare-Object
Alias copy -> Copy-Item
Alias cp -> Copy-Item
Alias cpi -> Copy-Item
Alias cpp -> Copy-ItemProperty
Alias curl -> Invoke-WebRequest
...

上述命令中,gpsGet-Process 命令的别名,-n 选项等同于 -Name。实际上 -n 选项此处也可以省略(默认即根据名称筛选进程)。

对象的深度整合

PowerShell 可以直接处理复杂的结构化数据和功能完整的对象。如以下命令用于创建一个简单的字符串:

1
2
PS C:\Users\starky> "Hello World"
Hello World

事实上刚刚创建的 “Hello World” 字符串是一个具有完整功能的对象(来源于 .NET 框架),可以通过 . 符号访问其属性:

1
2
PS C:\Users\starky> "Hello World".Length
11

所有的 PowerShell 命令都会将其输出内容作为对象,同时该对象可以被赋值给任意一个变量。如 Get-Process cmdlet 会生成一个 System.Diagnostics.Process 对象。

1
2
3
4
5
PS C:\Users\starky> notepad
PS C:\Users\starky> $process = Get-Process notepad
PS C:\Users\starky> $process.kill()
PS C:\Users\starky> Get-Process notepad
Get-Process : 找不到名为“notepad”的进程。请验证该进程名称,然后再次调用 cmdlet。

管理员作为“第一等级”用户

PowerShell 始终将管理员执行的任务作为关注的焦点,比如在终端中可以直接完成此种类型的计算:

1
2
PS C:\Users\starky> 40GB / 650MB
63.0153846153846

借助于 .NET 框架提供的支持,PowerShell 还可以作为一个强大的“日历”应用:

1
2
PS C:\Users\starky> [DateTime]::IsLeapYear(2008)
True

1
2
3
4
5
6
7
8
PS C:\Users\starky> [DateTime]::Now

2019年2月18日 21:32:03


PS C:\Users\starky> $result = [DateTime] "06/21/2019" - [DateTime]::Now
PS C:\Users\starky> $result.TotalDays
122.102253218295
组合命令

可以使用管道符(|)将一个命令的输出重定向至另一个命令作为输入,和 Bash 中管道符的使用一样。如:
Get-Item Path1\* | Move-Item -Destination Path2
上述命令将 Path1 中的所有文件移动到 Path2 目录下。

更复杂的形式如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PS C:\Users\starky> Get-Process | Where-Object { $_.Handles -ge 1000 } | Sort-Object Handles | Format-Table Handles,Name,Desciption -Auto

Handles Name Description
------- ---- -----------
1023 dwm 桌面窗口管理器
1025 chrome Google Chrome
1096 SkypeApp SkypeApp
1107 Microsoft.Photos Microsoft.Photos.exe
1126 svchost Windows 服务主进程
1236 svchost Windows 服务主进程
1425 SearchUI Search and Cortana application
1437 lsass Local Security Authority Process
1712 chrome Google Chrome
2592 explorer Windows 资源管理器
3410 System

通过 Get-Process 命令获取当前所有进程的信息,使用 Where-Object { $_.Handles -ge 1000 } 命令筛选出 Handles 在 1000 以上的对象,Sort-Object Handles 命令用来通过 Handles 属性排序,Format-Table ... 命令用来对输出结果进行格式化。

通过别名的简化,上述命令也可以使用如下的形式:
gps | ? { $_.Handles -ge 1000 } | sort Handles | ft Handles,Name,Description -Auto

“发现”命令

可以通过 Get-Command cmdlet 进行模糊搜索,查询可能用到的命令,如需要使用“进程”相关的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
PS C:\Users\starky> Get-Command *process*

CommandType Name Version Source
----------- ---- ------- ------
Function Get-AppvVirtualProcess 1.0.0.0 AppvClient
Function Start-AppvVirtualProcess 1.0.0.0 AppvClient
Cmdlet ConvertTo-ProcessMitigationPolicy 1.0.11 ProcessMitigations
Cmdlet Debug-Process 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Enter-PSHostProcess 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Exit-PSHostProcess 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Get-Process 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Get-ProcessMitigation 1.0.11 ProcessMitigations
Cmdlet Get-PSHostProcessInfo 3.0.0.0 Microsoft.PowerShell.Core
Cmdlet Set-ProcessMitigation 1.0.11 ProcessMitigations
Cmdlet Start-Process 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Stop-Process 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Wait-Process 3.1.0.0 Microsoft.PowerShell.Management
Application qprocess.exe 10.0.17... C:\Windows\system32\qprocess.exe

如需要获取某个命令的具体帮助信息,可以使用 Get-Help cmdlet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
PS C:\Users\starky> Get-Help Stop-Process

名称
Stop-Process

摘要
Stops one or more running processes.


语法
Stop-Process [-Id] <Int32[]> [-Confirm] [-Force] [-PassThru] [-WhatIf] [<CommonParameters>]

Stop-Process [-InputObject] <Process[]> [-Confirm] [-Force] [-PassThru] [-WhatIf] [<CommonParameters>]

Stop-Process [-Confirm] [-Force] -Name <String[]> [-PassThru] [-WhatIf] [<CommonParameters>]


说明
The Stop-Process cmdlet stops one or more running processes. You can specify a process by process name or process I
D (PID), or pass a process object to Stop-Process . Stop-Process works only on processes running on the local compu
ter.

On Windows Vista and later versions of the Windows operating system, to stop a process that is not owned by the cur
rent user, you must start Windows PowerShell by using the Run as administrator option. Also, you are prompted for c
onfirmation unless you specify the Force parameter.


相关链接
Online Version: http://go.microsoft.com/fwlink/?LinkId=821642
Debug-Process
Get-Process
Start-Process
Stop-Process
Wait-Process

备注
若要查看示例,请键入: "get-help Stop-Process -examples".
有关详细信息,请键入: "get-help Stop-Process -detailed".
若要获取技术信息,请键入: "get-help Stop-Process -full".
有关在线帮助,请键入: "get-help Stop-Process -online"

PowerShell 可以直接操作从 .NET 框架中引入的数据对象,通过将某个对象传递给 Get-Member cmdlet,可以获取绑定于该对象的属性方法等:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PS C:\Users\starky> "Hello World" | Get-Member


TypeName:System.String

Name MemberType Definition
---- ---------- ----------
...
IndexOf Method int IndexOf(char value), int IndexOf(char value, int startIndex), int IndexOf...
IndexOfAny Method int IndexOfAny(char[] anyOf), int IndexOfAny(char[] anyOf, int startIndex), i...
Insert Method string Insert(int startIndex, string value)
IsNormalized Method bool IsNormalized(), bool IsNormalized(System.Text.NormalizationForm normaliz...
LastIndexOf Method int LastIndexOf(char value), int LastIndexOf(char value, int startIndex), int...
LastIndexOfAny Method int LastIndexOfAny(char[] anyOf), int LastIndexOfAny(char[] anyOf, int startI...
Normalize Method string Normalize(), string Normalize(System.Text.NormalizationForm normalizat...
PadLeft Method string PadLeft(int totalWidth), string PadLeft(int totalWidth, char paddingChar)
PadRight Method string PadRight(int totalWidth), string PadRight(int totalWidth, char padding...
Remove Method string Remove(int startIndex, int count), string Remove(int startIndex)
Replace Method string Replace(char oldChar, char newChar), string Replace(string oldValue, s...
Split Method string[] Split(Params char[] separator), string[] Split(char[] separator, int...
StartsWith Method bool StartsWith(string value), bool StartsWith(string value, System.StringCom...
Substring Method string Substring(int startIndex), string Substring(int startIndex, int length)
...

后台运行

PowerShell 可以通过 Start-Job 将指定命令以后台任务的形式运行。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
PS C:\Users\starky> Start-Job { while($true) { Get-Random; Start-Sleep 5 } } -Name Sleeper

Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
2 Sleeper BackgroundJob Running True localhost while($true) { Get-Ra...


PS C:\Users\starky> Receive-Job Sleeper
2013662643
790182770
1345543150
PS C:\Users\starky> Stop-Job Sleeper
PS C:\Users\starky> Get-Job

Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
2 Sleeper BackgroundJob Stopped True localhost while($true) { Get-Ra...

其中 Receive-Job 用于获取后台任务的命令输出,Stop-Job 用于停止任务的运行,Get-Job 用于获取当前会话已绑定的所有任务。此外还有 Remove-Job 用于将活动任务从列表里移除。

除了使用 Start-Job cmdlet 生成后台任务,还可以通过在很多 cmdlets 后面加上 -AsJob 选项将其指定为后台运行。

脚本语言

PowerShell 实际上不只是一个简单的交互式终端,同时也是一种强大的脚本语言。所以支持众多的编程特性,如:

1
2
3
4
PS C:\Users\starky> $handleCount = 0
PS C:\Users\starky> foreach($process in Get-Process) { $handleCount += $process.Handles }
PS C:\Users\starky> $handleCount
69841

甚至如下的形式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PS C:\Users\starky> $webClient = New-Object System.Net.WebClient
PS C:\Users\starky> $content = $webClient.DownloadString("http://blogs.msdn.com/PowerShell/rss.aspx")
PS C:\Users\starky> $content.Substring(0,500)
<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>

<channel>
<title>PowerShell Team Blog</title>
<atom:link href="https://blogs.msdn.microsoft.com/powershell/feed/" rel="s

整合其他技术

PowerShell 也支持操作 WMI(Windows Management Instrumentation)和 CIM 对象:

1
2
3
4
5
6
7
8
PS C:\Users\starky> Get-CimInstance Win32_Bios


SMBIOSBIOSVersion : D5CN31WW
Manufacturer : LENOVO
Name : D5CN31WW
SerialNumber : PF0F77WR
Version : LENOVO - 1

又如操作 COM 对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PS C:\Users\starky> $firewall = New-Object -com HNetCfg.FwMgr
PS C:\Users\Administrator> $firewall.LocalPolicy.CurrentProfile


Type : 1
FirewallEnabled : True
ExceptionsNotAllowed : False
NotificationsDisabled : False
UnicastResponsesToMulticastBroadcastDisabled : False
RemoteAdminSettings : System.__ComObject
IcmpSettings : System.__ComObject
GloballyOpenPorts : System.__ComObject
Services : System.__ComObject
AuthorizedApplications : System.__ComObject

Providers

PowerShell 可以通过 Providers 像浏览目录那样浏览系统中的 data store。如浏览注册表的某个分支:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
PS C:\Users\starky> Set-Location HKCU:\Software\Microsoft\Windows
PS HKCU:\Software\Microsoft\Windows> Get-ChildItem


Hive: HKEY_CURRENT_USER\Software\Microsoft\Windows


Name Property
---- --------
AssignedAccessConfiguration
CurrentVersion
DWM Composition : 1
ColorizationColor : 3288365271
ColorizationColorBalance : 89
ColorizationAfterglow : 3288365271
ColorizationAfterglowBalance : 10
ColorizationBlurBalance : 1
EnableWindowColorization : 0
ColorizationGlassAttribute : 1
AccentColor : 4292311040
ColorPrevalence : 0
EnableAeroPeek : 1
AlwaysHibernateThumbnails : 0
UseDpiScaling : 0
Shell
TabletPC
Windows Error Reporting LastQueuePesterTime : 131873467252566492
Winlogon


PS HKCU:\Software\Microsoft\Windows> Set-Location CurrentVersion\Run
PS HKCU:\Software\Microsoft\Windows\CurrentVersion\Run> Get-ItemProperty .


OneDrive : "C:\Users\Administrator\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /background
Lantern : "C:\Users\Administrator\AppData\Roaming\Lantern\lantern.exe" -startup
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion
PSChildName : Run
PSDrive : HKCU
PSProvider : Microsoft.PowerShell.Core\Registry

即使用 Set-Location(或 cd)和 Get-ChildItem(或 dir )像浏览本地目录一样浏览访问注册表。

同样的方式也适用于系统里的证书库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PS C:\users\starky> Set-Location cert:\CurrentUser\Root
PS Cert:\CurrentUser\Root> Get-ChildItem


PSParentPath:Microsoft.PowerShell.Security\Certificate::CurrentUser\Root

Thumbprint Subject
---------- -------
CDD4EEAE6000AC7F40C3802C171E30148030C072 CN=Microsoft Root Certificate Authority, DC=microsoft, DC=com
BE36A4562FB2EE05DBB3D32323ADF445084ED656 CN=Thawte Timestamping CA, OU=Thawte Certification, O=Thawte, L=Durbanvill...
A43489159A520F0D93D032CCAF37E7FE20A8B419 CN=Microsoft Root Authority, OU=Microsoft Corporation, OU=Copyright (c) 19...
92B46C76E13054E104F230517E6E504D43AB10B5 CN=Symantec Enterprise Mobile Root for Microsoft, O=Symantec Corporation, ...
8F43288AD272F3103B6FB1428485EA3014C0BCFE CN=Microsoft Root Certificate Authority 2011, O=Microsoft Corporation, L=R...
...

参考书籍

Windows PowerShell Cookbook, 3rd Edition