前言

文档是参考《Windows PowerShell实战指南》(第3版),进行整理成册。

英文名:《Learn Windows PowerShell in a Month of Lunches》, Third Edition

image.png
书中的相关代码下载:https://www.manning.com/(找到本书后进行下载)
本书作者的YouTube频道:

PowerShell.org频道:https://www.youtube.com/powershellorg
Petro IT知识库:https://petri.com/
PowerShell社区:https://powershell.org/
PowerShell跨平台版本:http://github.com/PowerShell/PowerShell

如果想要检查最新的PowerShell可用版本或下载PowerShell,请访问http://msdn.microsoft.com/owershell。该官方PowerShell主页,有一个指向最新版本Windows管理框架(WMF)安装包的链接,该安装包用于安装PowerShell与其相关功能。

初识PowerShell

Tab键一般有4种补全场景:(Tab 和 Shift + Tab)

  • 补全命令:如输入“Get-S”,然后按几下Tab键,再按Shift+Tab组合键。
  • 遍历当前目录文件:如输入“Dir”,按空格键,然后输入“C:\”,再按Tab键。
  • 遍历可用参数:
    • 输入“Set-Execu”,按Tab键,然后输入一个空格和横杠(-),再开始按Tab键;
    • 可以看到PowerShell循环显示当前命令的所有可用参数。
  • 遍历参数值:
    • 再次输入“Set-Execu”,按Tab键,再按空格键,然后输入“-E”,再次按Tab键;
    • 然后按一次空格键,再按Tab键。PowerShell会循环显示关于这些参数的合法值。

查看版本:$PSVersionTable
显式指定运行v2版本:PowerShell.exe –version 2.0

  1. PS C:\Users\Administrator> PowerShell.exe version 2.0
  2. Windows PowerShell
  3. Copyright (C) 2009 Microsoft Corporation. All rights reserved.
  4. PS C:\Users\Administrator> $PSVersionTable
  5. Name Value
  6. ---- -----
  7. CLRVersion 2.0.50727.9151
  8. BuildVersion 6.1.7600.16385
  9. PSVersion 2.0
  10. WSManStackVersion 2.0
  11. PSCompatibleVersions {1.0, 2.0}
  12. SerializationVersion 1.1.0.1
  13. PSRemotingProtocolVersion 2.1

新版本的Windows默认会安装新版的PowerShell,但可能会包含PowerShell v2引擎。如果需要,可以在PowerShell中运行Add-WindowsFeature powershell –v2来安装v2引擎。

使用帮助

Windows的PowerShell提供了Get-Help这个Cmdlet命令访问帮助系统。你可能看到很多示例(特别是在互联网)都是使用“Help”或“Man”(来自UNIX,指代Manual)关键字来代替Get-Help。Man和Help都不是原生的Cmdlet命令,而是对核心Cmdlet命令进行封装后的函数。
Help的工作原理类似Get-Help,但它可以把输出的信息通过管道传送给More命令。

  • 相当于:Get-Help Get-Content | More

微软的PowerShell帮助文件已经在http://github.com/powershell开源。该网址是查看最新源码的好地方,该部分帮助可能在PowerShell中无法下载。

常用命令

查看命令本机帮助信息:help Get-Service

  • 支持正则查找:help *log*

查看命令在线帮助信息:help Get-Service -Online
查看命令帮助示例信息:help Get-EventLog -examples
查看命令指定参数帮助信息:help Get-EventLog -Parameter newest

  • Help invoke* -Parameter AsJob
  • Help * -Parameter AsJob

查看详细帮助信息:

  • help Get-Service -full
  • help Get-EventLog -detailed

通过GUI查看帮助:help Get-EventLog -ShowWindow(前提是底层帮助XML文件的质量)

更新命令帮助文档:Update-Help(这些文件存储在System32这个目录下,因此Shell必须在更高特权下运行)
更新指定模块:Update-Help -Module Microsoft.PowerShell*
下载帮助文档至本地:Save-Help 'D:\(tmp\'

  • 可将下载的文档存放至服务器,本机若未联网,可直接访问该服务器。
  • Update-Help -SourcePath \\Server01\Share\PSHelp

    帮助详解

    下面以Get-EventLog的语法帮助部分为例: ```powershell PS C:\Users\Administrator> help Get-EventLog

名称 Get-EventLog

摘要 Gets the events in an event log, or a list of the event logs, on the local computer or remote computers.

语法 Get-EventLog [-LogName] [[-InstanceId] ] [-After ] [-AsBaseObj ect] [-Before ] [-ComputerName ] [-EntryType {Error | Information | FailureAu dit | SuccessAudit | Warning}] [-Index ] [-Message ] [-Newest ] [- Source ] [-UserName ] []

  1. Get-EventLog [-AsString] [-ComputerName <System.String[]>] [-List] [<CommonParameters>]
  1. 该命令在语法部分出现了两次,这表示这个命令提供了两个不同的参数集。有些参数是这两个参数集共享的,如都包含-ComputerName参数。
  2. - 若使用所有参数集中共有的参数,Shell通常会选择第一个参数集。
  3. - 命令不能跨参数集使用参数,如选择使用-List参数,那么够使用的其他参数就只能是-AsString和-ComputerName
  4. 在每个PowerShellCmdlet参数的结尾都有`[<Common-Parameters>]`。不管你以何种方式使用Cmdlet,这泛指每个Cmdlet命令,都是使用的一组包含8个参数的集合。
  5. <a name="W7BAE"></a>
  6. ### 可选和必选参数
  7. PowerShell的帮助文档把可选参数放到一个方括号中。例如,`[-ComputerName <string[]>]`表示整个-ComputerName参数是可选的。你可以不使用该参数,因为在没有为该参数指定一个具体值的时候,Cmdlet会默认为本地计算机。<br />必选参数放到一个尖括号中,如`[-LogName] <System.String>`。如果不为必选参数输入值,在运行时,会进行提示。
  8. <a name="rtxiY"></a>
  9. ### 位置参数
  10. 位置参数意味着只要你把参数值放在正确的位置,就可以只提供这个参数值,而不需要输入具体的参数名。<br />比如,查看Get-EventLog的第一个参数集的前两个参数。
  11. ```powershell
  12. Get-EventLog [-LogName] <System.String> [[-InstanceId] <System.Int64[]>]

第一个参数:-LogName,它是必选参数。因为它的参数名称和参数值不在一个方括号里面。
第二个参数:-InstanceId,它是可选的。

  • 因为它的参数名称与参数值位于同一个方括号内。在方括号内,-InstanceId本身又处在一个方括号里,意味着它同时还是一个位置参数。
  • 它出现在第二个位置,所以我们省略这个参数名称,就必须在该位置提供一个参数值。
    1. Get-ChildItem [[-Path] <System.String[]>] [[-Filter] <System.String>] [-Attributes {Archive | C
    2. ompressed | Device | Directory | Encrypted | Hidden | IntegrityStream | Normal | NoScrubData |
    3. NotContentIndexed | Offline | ReadOnly | ReparsePoint | SparseFile | System | Temporary}] [-Dep
    4. th <System.UInt32>] [-Directory] [-Exclude <System.String[]>] [-File] [-Force] [-Hidden] [-Incl
    5. ude <System.String[]>] [-Name] [-ReadOnly] [-Recurse] [-System] [-UseTransaction] [<CommonParam
    6. eters>]
    在上述语法中,-Path和-Filter参数是位置参数,这是由于参数名称被中括号给括了起来。
    image.png
    上述帮助明显解释了-Path参数在位置1。对于位置参数来说,你无须输入参数名称——仅需要在正确的位置提供参数值,例如:
    1. PS C:\> Get-ChildItem -Path c:/
    2. # 等同于
    3. PS C:\> Get-ChildItem c:/

范例:

  1. Get-EventLog -newest 20 -Log Application # -Log是-LogName缩写
  2. Get-EventLog Application -InstanceId 0 -Newest 10
  3. # 在容易使人混淆的命令行中,建议显式指定参数名称,不要省略
  4. # move C:\devlist.txt d:\
  5. move -Path C:\devlist.txt -Destination d:\
  6. move Destination d:\ -Path C:\devlist.txt

参数值

帮助文档同样给你提供了每个参数的数据类型。有些参数被称为开关参数,无需任何输入值。如Get-EventLog [-AsString],详细语法如下:
image.png
通过[<SwitchParameter>]可以确认这是一个开关参数,并不需要任何输入值。开关参数的位置可以随意放置,你必须输入参数名(或者至少是一个缩写)。

其他参数希望获得的数据类型,通常会跟在参数名称之后,并使用空格与参数名称分开。在缩写语法里面,输入的类型使用尖括号表明,如[-LogName] <System.String>

通常的输入类型

  • string:一系列字母和数字,有些时候也会包含空格符。
    • 如果出现空格符,那么全部字符串必须包含在引号内。
    • 如:"C:\Program Files (x86)"
  • Int、Int32或Int64:一个整数类型(整个数字不包含小数)。
  • DateTime:通常,基于你本地计算机的时区配置,字符串被解释成的日期会有所不同。
    • 在美国,通过的日期格式为10-10-2010,即月-日-年。

对于有些值包含多个方括号,如[-ComputerName <System.String[]>]。string后面的方括号,并不意味着某些东西是可选的。事实上,string[]意味着该参数可以接受数组、集合,或者是一个列表类型的字符串。
下面以查看Security日志为例:

  1. Get-EventLog Security # 查看本机
  2. Get-EventLog Security -ComputerName vpn-server
  3. Get-EventLog Security -ComputerName vpn-server,dc1,'dns-server'

PowerShell把以逗号为分隔符的列表作为数组值对待。任何一个单一值中如果包含了空格,就必须使用引号。但是作为一个整体的列表,不需要使用引号,只有单一值才需要使用引号。

另外一种提供列表值的方式,是把它们输入到一个文本文件中,每一个值一行。

  1. vpn-server
  2. dc1
  3. 'dns-server'

接着,可以使用Get-Content来读取该文件的内容,并且发送这些内容到-computerName参数中。

  1. Get-EventLog Security -ComputerName (Get-Content name.txt)

对于接受多个值的参数,你可以输入第一个值并按回车键,继续输入直到完成,最后空白处按回车键,这将告诉PowerShell已经完成输入。

访问“关于”主题

PowerShell的帮助系统包含许多背景主题,可以用来帮助定位指定的Cmdlet命令。这些背景主题通常被称为“关于”主题,因为它们都是以“about_”开头的。

  • 查看关于数组的帮助主题信息:help *array*help about_arrays ```powershell PS C:\Users\Administrator> help about*

Name Category Module Synopsis


about_Aliases HelpFile about_Alias_Provider HelpFile about_Arithmetic_Operators HelpFile about_Arrays HelpFile about_Assignment_Operators HelpFile about_Automatic_Variables HelpFile about_Break HelpFile about_Certificate_Provider HelpFile about_CimSession HelpFile about_Classes HelpFile ——-More——-

  1. 前面介绍过,所有的Cmdlet命令都提供一个通用参数集。那么,怎样才能更多了解这些常见的参数?<br />执行`help *common*`,这只会在帮助主题中匹配到一条记录:`About_common_parameters`。该主题将会自动显示,因为只有唯一一条配置的主题。浏览显示的帮助主题,你会发现如下8个通用参数。<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/635565/1653190950255-e0ce7355-892c-43d1-96e0-2e305b09ca47.png#clientId=u0dd2614c-1757-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=211&id=u58f67ee8&margin=%5Bobject%20Object%5D&name=image.png&originHeight=271&originWidth=254&originalType=binary&ratio=1&rotation=0&showTitle=false&size=14426&status=done&style=none&taskId=u63d8c75a-c7d7-43a6-9033-9ec4131f39f&title=&width=198)
  2. <a name="CocFQ"></a>
  3. ## 查找命令
  4. Help这个命令一样,Get-Command接受通配符,意味着你可以运行`Gcm *event*` 查看所有名称包含“event”的命令。不管怎么样,这个返回的列表将不止包含Cmdlet命令,还会包含一些不一定有用的外部命令,如netevent.dll。<br />一个比较好的方式是使用“-名词”或者“-动词”参数。因为只有Cmdlet名的名称有名词和动词,返回的结果将会限制为Cmdlet命令。
  5. - `Get-Command -noun *event*`将会返回一个关于事件命令的列表;
  6. - 查找文件和打印机相关命令:`gcm -Noun file,printer`
  7. - `Get-Command -verb Get`将会返回一个具有检索能力的列表。
  8. 以上两个参数也可结合使用:
  9. - 查找可以向事件日志写入数据的命令:`gcm -Noun eventlog -Verb write`
  10. <a name="onVTD"></a>
  11. ### 根据命令类型查找
  12. 你也可以使用`-CommandType`参数来指定命令的类型。比如`Get-Command *log* -type Cmdlet` ,将会返回一个所有命令名称包含“log”的命令列表,并且这个列表不会包括任何其他扩展应用程序或者扩展命令。
  13. ```powershell
  14. # -CommandType 等同于 -type
  15. PS C:\Users\Administrator> Get-Command *log* -CommandType Cmdlet
  16. CommandType Name Version Source
  17. ----------- ---- ------- ------
  18. Cmdlet Clear-EventLog 3.1.0.0 Microsoft.PowerShell.Management
  19. Cmdlet Disable-AppBackgroundTaskDiagnosticLog 1.0.0.0 AppBackgroundTask
  20. Cmdlet Enable-AppBackgroundTaskDiagnosticLog 1.0.0.0 AppBackgroundTask
  21. Cmdlet Export-BinaryMiLog 1.0.0.0 CimCmdlets
  22. PS C:\Users\Administrator> Get-Command log* -type Application
  23. CommandType Name Version Source
  24. ----------- ---- ------- ------
  25. Application logagent.exe 12.0.19... C:\windows\system32\logagent.exe
  26. Application logman.exe 10.0.19... C:\windows\system32\logman.exe
  27. Application logoff.exe 10.0.19... C:\windows\system32\logoff.exe
  28. Application LogonUI.exe 10.0.19... C:\windows\system32\LogonUI.

Cmdlet命名惯例

Cmdlet是一个原生的PowerShell命令行工具。该术语仅仅存在于PowerShell和类似C#的.Net Framework语言中。

微软已经为Cmdlet建了一个命名惯例。因此同样的命名规则也应该被用于函数和工作流。虽然微软并没有强制要求,但开发人员应该遵循该惯例。规则应该以标准的动词开始,比如Get、Set、New或Pause。

你可以运行Get-Verb,查看允许使用的动词列表。

  1. PS C:\> Get-Verb | more
  2. Verb Group
  3. ---- -----
  4. Add Common
  5. Clear Common
  6. Close Common
  7. Copy Common
  8. Enter Common
  9. Exit Common
  10. Find Common
  11. Format Common
  12. Get Common
  13. Hide Common
  14. Join Common
  15. Lock Common
  16. -- More --

由于PowerShell允许开发人员自己命名名词,因此并没有一个“Get-Noun”的Cmdlet来显示所有名词。

运行命令

别名

cmdlet和参数都有别名。

命令别名

查看命令别名:

PS C:\> Get-Alias -Definition "Get-Service"

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           gsv -> Get-Service

你可以使用New-Alias创建自定义别名,使用Export-Alias导出别名列表。

当创建一个别名时,其生命周期只能持续到当前的Shell会话结束。一旦关闭窗口,别名就会不复存在。这也是你需要导出别名的原因,以便后续重新导入。

参数别名

尽管参数的别名不在帮助文件或任何方便查阅的地方而难以识别,但参数也拥有别名。比如说,Get-EventLog命令有-ComputerName参数。可以运行下述命令,查阅该参数别名。

PS C:\> (Get-Command Get-EventLog | select -ExpandProperty parameters).ComputerName.Aliases
Cn

数据结果展示了-Cn是-computerName的别名,所以你可以运行下述命令。

PS C:\Windows\system32> Get-EventLog -LogName Security -Cn im20211010 -Newest 10

Show-Command

PowerShell v3(以及更新版本)提供的一个非常棒的特性是Show-Command commlet。

Show-Command将成为你的助手,该命令允许指定你无法用对的命令名称,并以图形化的方式将命令的参数名称展示出来。

如图所示,参数集分布于不同的选项卡(在前一章学到的),因此不同参数集之间的参数不会搞混——选择一个选项卡并仅一次只使用一个选项卡。
image.png
可以单击运行执行命令,或单击复制将完成后的命令复制到剪贴板,返回Shell,将命令粘贴(右击控制台,或是在ISE中使用Ctrl+V组合键)到Shell中进行查看。

Show-Command一次只能展示一个命令。因此,当希望了解多个命令时,只能逐个使用该命令。

对命令扩展的支持

大约400个Cmdlet被集成到Windows客户端操作系统中,上千个被集成到Windows服务器版本的操作系统中,并且你还能添加更多——类似ExchangeServer、Sharepoint Server和SQL Server都包含数以百计的额外Cmdlet。

包括Ping、Nslookup、Ipconfig、Net等。由于这些都不是原生PowerShell Cmdlet,因此你可以按照原来使用这些命令的方法继续使用这些命令。PowerShell将会在后台启动Cmd.exe。

New-PSDrive命令

Net Use命令在PowerShell中也能正常工作。但PowerShell v3证实微软开始寻找合适的时机推出PowerShell风格的方式来完成这些传统任务。
从PowerShell v3开始,现在你可以发现New-PSDrive命令多了一个-Persisit参数,该参数决定是否启用文件系统提供程序。这样一来,新的磁盘将会在文件资源管理器中被查看到。

Test-Connection命令

关于Ping命令,在PowerShell可以使用Test-Connection代替。原生的Test-Connection Cmdlet相比之前的提供了更多选项和更灵活的输出方式。

外部命令支持

当一个外部命令拥有很多参数时,PowerShell在大多数场景下无法工作。但可以提供类型下面的命令,从而确保运行一个命令且其参数可以准确无误。
image.png
以名为vcbMounter.exe的外部命令为例,该命令接受6个参数。

  • -h:用于指定主机名称。
  • -u:用于指定用户名。
  • -p:用于指定密码。
  • -s:用于指定服务器名称。
  • -r:用于指定区域。
  • -t:用于指定备份类型。

我们所做的是将不同的元素——可执行路径和名称,以及所有的参数值放入$容器。然后使用调用操作符(&),将可执行程序的名称以及所有参数名称与参数值传递给该操作符。任何可以在PowerShell中运行的命令行工具,都可以使用这种方式在PowerShell中调用。

另一种办法

仅需要在外部命令名称之后加两个破折号。如果你这么做,PowerShell甚至不会解析该命令,仅仅是将该命令传递到Cmd.exe中。这意味着你基本上可以使用Cmd.exe的语法在PowerShell中运行任何命令,而不用担心该命令在PowerShell中解析的实现细节。

PS C:\> C:\Windows\System32\sc.exe --% qc bits
[SC] QueryServiceConfig 成功

SERVICE_NAME: bits
        TYPE               : 20  WIN32_SHARE_PROCESS
        START_TYPE         : 3   DEMAND_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Windows\System32\svchost.exe -k netsvcs -p
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Background Intelligent Transfer Service
        DEPENDENCIES       : RpcSs
        SERVICE_START_NAME : LocalSystem

# 加破折号后,PowerShell不再解析破折号后的命令        
PS C:\> $n="bits"
PS C:\> C:\Windows\System32\sc.exe --% qc $n
[SC] OpenService 失败 1060:

指定的服务未安装。