前言

本系列博文是《Windows PowerShell实战指南》的学习笔记。

Chapter 3 使用帮助系统

由于其他平台上的PowerShell功能没有Windows上完整,所以在未加特别说明的情况下,后面的截图等均基于Windows平台。

系统版本:

PowerShell版本:

  • 输入参数名时只需输入能区分它的前缀即可
  • 可选参数:参数名和参数值均在中括号内
  • 必选参数
  • 定位参数:参数名在中括号内,而参数值在小括号内(参数值必选),不必输入参数名,参数值的位置正确即可

建议刚开始一直输入参数名。

先执行括号里的命令:

Get-EventLog Application -computer (Get-Content names.txt)
# about 主题也有很多信息
help about*
# 如查看关于数组的内容
help Arrays
help about_core_commands

# 可以帮助查找有哪些可能有用的命令,比如找关于进程的
Get-Command *Process*

像下面这样的语法描述,即这个命令适应三种不同的语法规则(参数组合)。你输入的命令应该符合其中一种:

Chapter 4 运行命令

  • Cmdlet 是原生PowerShell命令行工具
  • 函数与其类似,但不是以.Net编写,而是以PowerShell自己的脚本语言编写
  • 工作流是嵌入PowerShell的工作流执行系统的一类特殊函数
  • 应用程序是任意类型的外部可执行程序(原cmd命令基本都可用)

Get-Verb查看可用动词:

PS /Users/rambo> Get-Verb
Enable      e           Lifecycle      Configures a resource to an available...
Verb        AliasPrefix Group          Description
----        ----------- -----          -----------
Add         a           Common         Adds a resource to a container, or attaches an item to another item
Clear       cl          Common         Removes all the resources from a container but does not delete the container
Close       cs          Common         Changes the state of a resource to make it inaccessible, unavailable, or unusable
Copy        cp          Common         Copies a resource to another name or to another container
Enter       et          Common         Specifies an action that allows the user to move into a resource
Exit        ex          Common         Sets the current environment or context to the most recently used context
Find        fd          Common         Looks for an object in a container that is unknown, implied, optional, or specified
Format      f           Common         Arranges objects in a specified form or layout
Get         g           Common         Specifies an action that retrieves a resource
...

PowerShell允许开发人员自己命名名词。

使用New-Alias创建自定义别名,其生命周期为当前Shell。所以如果以后要使用,则需要Export-Alias

Show-Command Get-Process以GUI方式显示命令的用法:

  • 显示最新的100个应用程序日志
Get-Eventlog -LogName Application -Newest 100

Chapter 5 使用提供程序

这一章的内容较为抽象。简略来说,文件系统、环境变量、PowerShell本身的变量、PowerShell的函数等等这些东西被抽象成Drives,而PSProvider作为访问这些数据介质的适配器。它向PSDrive提供服务。用户则使用Cmdlet去操作PSDrive呈现的数据。

我画了张图来表达自己对上面这些概念的理解(不一定对):

对于数据介质的一个更高级的抽象是“项”(Item)。无论文件系统中的文件、文件夹,还是注册表中的项,在PowerShell都被视为“项”。(注意,注册表和文件系统具有相同的分层结构)这样一来,为数据的访问和操作提供了统一的术语。而相关的Cmdlet也往往是包含Item字符的:

Get-Command -Noun *Item*

所以,在PowerShell的cd或者Set-Location具有了更广泛的含义,它不仅仅是像传统命令行或Bash那样切换工作目录,甚至可以从文件系统切换到注册表中。

一般每个项都有其属性。如文件夹:

再如注册表键:

但有的PSProvider并不具有项属性,如Environment

Get-PSProvider

Get-PSDrive

访问注册表并修改值:

最后别忘了改回默认值。

大部分Cmdlet都包含-Path,且默认情况下支持通配符。如果不希望自己输入的?*被当作通配符,可以使用-LiteralPath代替。

Chapter 6 管道:连接命令

格式化输出结果

输出结果到CSV (Comma-Separated Values):

Get-Process | Export-Csv procs.csv

相比直接在命令行中显示的内容,很明显输出到文件的内容更丰富。

之后可以在别处把procs.csv导入到PowerShell进行查看:

Import-Csv procs.csv | more

注意,与Get-Content相比,Import-Csv会去解析它的格式,以更有序的形式展示出来。

另外也可以导出为XML

Get-Process | Export-Clixml procs.xml

还有其他的各种导出导入:

还有一个对比功能蛮有趣:

Compare-Object或者diff

Compare-Object -ReferenceObject (Import-CliXML procs.xml) -DifferenceObject (Get-Process) -Property Name

=>表示不存在于ReferenceObject的进程,<=表示不存在于DifferenceObject的进程。另外注意小括号()的妙用。

输出到文件或打印机

dir > x.txt这种写法是为了向后兼容。实际上它是以管道实现:dir | Out-File x.txtOut-file默认一行80列)。

输出到HTML

Get-Process | ConvertTo-Html | Out-File procs.html

注意,ConvertTo-意味着只转换,不存储。Export则还会自动帮你存储。但是如果接下来还要用管道处理数据,那么ConvertTo更方便。

修改系统

Get-Process -Name notepad | Stop-Process

这个例子想要说明的是,带有相同名词(如上面的Process)的Cmdlet可以在彼此之间传递信息。

Stop-这种会修改系统的命令,都有impact level,这些level是不可修改的。同时,PowerShell有一个全局的$ConfirmPreference

如果命令的level大于等于全局的,则PowerShell会问你是否确定要这么做。当然,你也可以强制它每次问你一下,即使命令的level小于全局的:

-Confirm会询问,-WhatIf会告诉你将发生什么。

我们之前有提到PSProvider。再次看一下这张图片:

其中,带有ShouldProcessPSProvider支持-WhatIf-confirm参数。

另外,Filter指的是其支持-Filter参数;Credentials指的是“允许使用可变更的凭据连接数据存储。”,即-Credentials参数;Transactions说明其支持事务(即原子操作)。

Chapter 7 扩展命令

由于本章需要的某些模块在之前使用的Windows Server 2008中不存在,故本章采用如下版本的Windows Server 2012 R2PowerShell

本章学习PowerShell的两种扩展:

  • 管理单元
  • 模块

首先是管理单元。它类似于插件。这种方式正逐渐被微软遗弃。它使用的主要命令是:

Get-PSSnapin
Add-PSSnapin

深入学习模块:

模块不需要注册。PSModulePath定义了PowerShell期望存放模块的路径,路径下的模块会自动被查找:

(图中两个路径分别存放系统和个人的模块)

另外,PSModulePath不能在PowerShell中修改,需要到系统环境变量中修改。

测试:

首先移除所有模块:

之后查找一下network相关命令,可以发现还是可以找到,即使你没有加载那个模块。PowerShell会为你自动发现和加载:

如果模块不在前面的路径下,那么需要手动导入:Import-Module

插件和模块都可以添加PSDrive,所以在加载之后你可以使用Get-PSProvider查看新添加了哪些。

注:如果加载多个模块,其中包含相同命令,那么在使用命令时需要加上模块或插件前缀。例如:

MyCoolPowerShellSnapin\Get-User

小实验:清除DNS缓存

首先查看一下有哪些命令可以用:

发现很多都来自DnsClient模块。我们手动加载一下这个模块试一下(其实没有必要):

试一下Clear-DnsClientCache

Es klappt!

使用配置脚本

这个类似于Shell的profile,这里的主要目的是帮你自动加载插件和模块。

  • 在用户的Documents目录下新建目录WindowsPowerShell
  • 在其中新建文件profile.ps1
  • 在刚刚的文件中输入Add-PSSnapinImport-Module,一行一个命令的格式来加载插件和模块
  • 在PowerShell中修改执行策略(需要管理员身份)
Set-ExecutionPolicy RemoteSigned
  • 关闭当前PowerShell并重启

动手实验:运行网络故障诊断包

Get-Command搜索network没有找到有用的。看了英文版的题目才知道“网络故障诊断包”是Networking troubleshooting pack,那就找一下trouble吧:

Got it!

但是一开始不太会用这个东西,看一下帮助:

这个好像是声音相关的。那我看一下那个目录下都有什么:

太棒了。

然后把它传给Invoke-

不过,这个功能略鸡肋啊。

补充知识

注:在线教程

交互式

基本C语言中的算术运算符在这里都能用。另外0xdeadbeef这种十六进制也可以用。同时,它还能识别tb/gb/mb/kb,如1gb

通过字符串执行外部程序:

通过Get-Command | gm查看命令集的类型(目前我的环境上有三种):

  • System.Management.Automation.AliasInfo
  • System.Management.Automation.FunctionInfo
  • System.Management.Automation.CmdletInfo

通过函数来将带有常用参数的命令扩展为别名:

function test-conn { Test-Connection  -Count 2 -ComputerName $args}

注意,$args为占位符。

执行VBS脚本:

cscript.exe .\test.vbs

Powershell调用入口的优先级

  • 别名:控制台首先会寻找输入是否为一个别名,如果是,执行别名所指的命令。因此我们可以通过别名覆盖任意powershell命令,因为别名的优先级最高。
  • 函数:如果没有找到别名,会继续寻找函数,函数类似别名,只不过它包含了更多的powershell命令。因此可以自定义函数扩充cmdlet 把常用的参数给固化进去。
  • 命令:如果没有找到函数,控制台会继续寻找命令,即cmdlet,powershell的内部命令。
  • 脚本:没有找到命令,继续寻找扩展名为“.ps1”的Powershell脚本。
  • 文件:没有找到脚本,会继续寻找文件,如果没有可用的文件,控制台会抛出异常。

默认的安全设置禁止执行脚本:

变量

定义变量

  • 不需要显式声明
  • 可以自动创建变量
  • 字母不区分大小写
  • 变量的前缀为$
  • 几乎可以把任何数据赋值给变量,一切都是对象
  • 交换两变量的值非常简单

以上特性可以参照下图:

变量被存放在VariableDrive中:

验证变量是否存在:

(这与验证文件是否存在一样,关于原理可以参考Chapter 5 使用提供程序)

PowerShell提供5个管理变量的命令:

  • Clear-Variable
  • Remove-Variable
  • Set-Variable
  • Get-Variable
  • New-Variable

后两个比较有用。比如:

  • 创建只读变量

  • 创建常量

通过help about_scope可以详细了解。

自动化变量

自动化变量是那些一旦打开Powershell就会自动加载的变量:

可以通过

help about_Automatic_Variables

深入了解。

环境变量

关于环境变量:

借助.Net方法,可以使用户设置的环境变量在系统级别生效:

[environment]::SetEnvironmentvariable("myPath", ";c:\powershellscript", "User")

驱动器变量

可以通过${PATH}直接访问文件内容(其实这也是一切皆为“项”的体现):

甚至函数也可以:

$()子表达式: