文章目录
介绍
PowerShell
作为Windows
系统中的默认脚本,其实在开发中,我们用的很少。接下来的几篇文章都将PowerShell
的相关知识,本章介绍PowerShell
基本的知识。
安装及简介
从Windows Server 2008
、Windows Server 2008 R2
、Windows7
操作系统开始,我们已经可以使用第三版本的Windows PowerShell
。而Windows 10
默认安装的版本已经到了5.1
。具体可以通过在PowerShell
中输入$PSVersionTable
命令查看。
而如果要更新到最新的版本,可以访问此地址进行更新。
在Windows 10
上安装后,我们可以看到PowerShell
的控制台程序和集成脚本环境(ISE)。如上图所示的,打开控制台程序,我们可以直接输入命令后回车,即可看到相应的运行结果。但是ISE
界面更加的友好,后面可以看到使用此ISE
编辑命令和脚本可以提供更多的帮助,复制和黏贴等也更加的方便。但是ISE
相对的启动时间会较长,而通常也就几秒的差异。
如图,默认打开及分为三部分,分别是脚本编辑区域、命令管理器和控制台。在脚本编辑区域编辑的脚本命令不会马上执行,需要点击菜单栏上的运行按钮才会在控制台看到运行结果。
当然也可以通过点击【工具】->【选项】来配置窗口的相关属性,如字体大小、颜色等。同样PowerShell
控制台也可以进行相应的设置。这些相对简单,可以自行根据自己的喜好进行调整,这里就不过多的介绍了。
使用帮助系统
Command 对比 Cmdlet
PowerShell包含了多种类型的可执行命令,有些叫Cmdlet,有些叫函数,还有一些被称为工作流等。他们的共同点都是命令,所有这些命令都在帮助系统囊括的范围内。Cmdlet的概念是Powershell中独有的,你可运行的大多数命令都属于Cmdlet。但在谈论更通用的可执行工具时,我们使用“命令”来表示,从而保证一致性。
更新帮助
在使用帮助系统之前,最好是更新到最新的版本,可以通过Update-Help
命令进行更新(最好是通过管理员身份运行)。
微软的PowerShell帮助文件已经在https://github.com/powershell开源。该网址是查看最新源码的好地方,该部分帮助可能在PowerShell中无法下载。
查看帮助
更新好后我们可以输入下面命令观察一下。
如上,Windows
的PowerShell
提供了Get-Help
这个Cmdlet
命令访问帮助系统。你可以看到很多示例都是使用“Help
”或者“Man
”(来自UNIX,指代Manual)关键字来代替Get-Help
。Help
和Man
都不是原始的Cmdlet
命令,而是对核心Cmdlet
命令封装后的函数。
Help
的工作原理类似Get-Help
,但是它可以把输出的信息通过管道传递给More
命令。(Man
是Help
的别名或者昵称,因此也可使用More
命令)所有我们可以使用Help Get-Content
命令,也可以更友好的使用Help Get-Content | More
命令。
使用帮助系统查找命令
和大多数命令一样,Get-Help
命令有几个参数。其中最重要的是-Name
。该参数指定你想要访问帮助的主题名称,并且它是一个位置参数,所以你无需输入-Name
,只需要提供要查找的命令名称。它也支持通配符(*
),这让帮助系统更容易查找命令。
如你想查看操作系统日志,但不知道命令,可通过下面的方式进行搜索
Help *log*
Help *event*
另外一种,你大概知道命令的一部分,那可以输入“Help Get-Eve
”然后通过Tab
键进行自动补全,如果不是你需要的,可以继续按Tab
键,帮助系统会循环查找以“Get-Eve
”开头的所有命令。
帮助详解
参数集和通用参数
如上红框中标识的就是参数集,这表示,此Get-EventLog
命令有两个参数集,你可能已经注意到,有些参数是这两个参数集共有的,它们是通用参数。
可选和必选参数
PowerShell
的帮助稳定把可选参数放到一个方括号中。如,[-ComputerName <System.String[]>]
表示-ComputerName
是可选参数。几乎所有的Cmdlet
命令都最少有一个可选参数。
对于必须的参数,如果没有输入值的情况下,如下所示。控制台会提示你继续输入必须的参数后才会继续运行。
位置参数
PowerShell
设计者知道有些参数会被频繁的使用,而你不希望不断的输入参数名称。通常来说,参数是具有位置的。着意味着只要你把参数值放在正确的位置,你就可以值提供这个参数值,而不需要输入具体的参数名称。
下面介绍使用位置参数时的几个技巧。
-
位置参数可以同时出现指定和不指定参数名称的情况,但是位置参数必须处在正确的位置。如:
Get-EventLog -newest 20 -Log Application
是正确的。Application
会被匹配到-Log
参数,因为这是第一个位置的参数值 -
指定参数名称总是合法的
-
如果使用多个位置参数,不要忘了它们的位置
我们的建议是:总是使用参数名称
使用Help Get-EventLog -Full
命令可以查看具体的参数说明,通用可以把-Full
改为-ShowWindow
,其会提供一个窗口来显示详细的说明详细。
参数值
帮助文档通用给你提供了每个参数的数据类型。有些参数被称为开关参数,无需任何输入值。如:[-AsString]
。
-AsString [<SwitchParameter>]
以字符串而非对象的形式返回输出。
是否必须? False
位置? False
默认值
是否接收管道输入? False
是否接收通配符? False
通过[<SwitchParameter>]
可以确定这是一个开关参数,并需要任何输入。开关参数位置可随便放置,但必须输入参数名(或缩写)并总是可选的。
其他参数希望获得的数据类型,通常会跟在参数名后面,并使用空格与参数名分开。在缩写语法中,用尖括号表明。如[-LogName] <string>
。除了string
,还有Int
、Int32
、Int64
、Datetime
等等。
另外,如[-ComputerName <string[]>]
表示参数后可以跟多个值,即string
后的方括号表示数组、集合。
Get-EventLog Security -ComputerName Server-R2
Get-EventLog Security -ComputerName Server-R2,DC4,Files02
再次说明,任何一个单一值中如果包含了空格,就必须使用引号。但是作为一个整体的列表,不需要使用银行,只有单一值才需要。以下内容合法。
Get-EventLog Security -ComputerName 'Server-R2','DC4','Files02'
另外一种提供列表值的方式是将其放入一个文本文件中,每个值一列。如下:
Server-R2
DC4
Files02
可以使用Get-Content
命令来进行获取,具体如下:
Get-EventLog Security -ComputerName (Get-Content names.txt)
发现命令示例及访问在线帮助
其实在使用-Full
参数中是可以查看的,但是我们也可以使用-Example
参数替换-Full
参数,直接查看命令的示例。
Help Get-EventLog -Example
PowerShell
的帮助文档是有人编写的,这意味着它们并不一定准确。除了使用Update-Help
命令外,可以使用Help
命令的-Online
参数查看在线的实时帮助信息。
Help Get-EventLog -Online
运行命令
Cmdlet
命名规则应该以标准的动词开始,比如Get
、Set
、New
或Pause
。以可以运行Get-Verb
查看运行使用的动词列表。对于有些命令,其命名非常的长,不方便记忆,所以我们可以使用命令的别名或者叫昵称。通过以下命令可以查看。
Get-Alias -Definition Get-Service
结果如下:
CommandType Name Version Source
----------- ---- ------- ------
Alias gsv -> Get-Service
而使用Help gsv
和使用Help Get-Service
的效果是一样的。
另外,参数也可简化或者使用别名。如可以使用-comp
代替-ComputerName
,也可以输入-comp
后按下Tab
键来完成参数名称的补全。当然也可以通过以下命令获取参数的昵称或者别名。
(Get-Command Get-EventLog | select -ExpandProperty parameters).computername.aliases
由此命令可以知道-ComputerName
的别名是-Cn
。
当然如ping
等命令也可以使用PowerShell
进行执行。但是对于一些第三方的程序,仅仅需要在外部命令名称后面加上两个破折号和一个百分号。比如我们想尝试使用命令行工具sc.exe
查询一个服务,可以使用以下形式。
使用提供程序
一个PowerShell
提供程序,或者说PSProvider
,其本质上是一个适配器。它可以接收某些数据存储,并使得这些介质看起来像是磁盘驱动器一样。使用以下命令查看当前Shell
总已经存在的提供程序。
以下是一些常见的功能描述。
-
ShouldProcess——这部分提供程序支持
-WhatIf
和-Confirm
参数,保证我们在正式执行这部分脚本之前可以对它们进行测试 -
Filter——在
Cmdlet
中操作提供程序的数据是,支持-Filter
参数 -
Credentials——该提供程序允许使用可变更的凭据连接数据存储
-
Transactions——该提供程序支持事务,也就是允许你在该提供程序中将多个变更作为一个原子操作进行提交或者全部回滚
你也可以使用某些提供程序创建一个PSDrive
。其可以通过一个特定的提供程序连接到某些存储数据的介质。
大多数情况下,操作PSDrive
的Cmdlet
名称部分都会包含“Item”。
在使用提供程序时,需要熟悉几个Cmdlet
命令。
-
Set-Location:作用和
cmd.exe
中的cd
是一样的 -
New-Item:创建新的项,可以用来新建文件夹、文件、注册表项以及其他项,所以必须告诉它你希望创建的类型是什么
PowerShell
中也包含MKDir命令,其是一个函数,并不是一个别名。它也调用了New-Item,只是隐式赋予了-Type Directory
这个参数
大多数分项的Cmdlet
都包含了-Path
属性。默认情况下,该属性支持通配符输入。 “*
”通配符代表0个或者多个字符;“?
”通配符代表单个字符。有这些情况下,比如注册表的某些项名称中包含了“*
”或“?
”,如果此时需要查询名称中带有*
或者?
,就需要使用-LiteralPath
参数,而不是-Path
参数。
看下面一个使用的例子。
Set-Location -Path HKCU:
Set-Location -Path SoftWare
Get-ChildItem
Set-Location -Path Microsoft
Set-Location -Path .\Windows
Get-ChildItem
Set-ItemProperty -Path DWM -PSProperty EnableWindowColorization -Value 0
管道:连接命令
PowerShell
通过管道(pipline)把命令互相连接起来。管道通过传递一个命令,把其输出作为另一个Cmdlet
的输入,是的第二个命令可以通过第一个的结果作为输入并联合起来运行。
查看以下案例,文件保存在当前目录下。分别输出为csv
和xml
格式的文件。
Get-Process | Export-CSV procs-csv.csv
Get-Process | Export-CliXML procs-xml.xml
接下来我们,看下使用Diff
命令来比较下文件内容。Diff
是Compare-Object
命令的别名。通过Help Diff
查看帮助文档,我们重点关注三个属性:-ReferenceObject
,-DifferenceObject
和-Property
。具体看以下例子(生成xml
文件后可以考虑打开几个新软件在执行第二条命令)。
Get-Process | Export-CliXML reference.xml
Diff -reference (Import-CliXML reference.xml) -difference (Get-Process) -property Name
接下来看一个通过管道输出到文件的例子。
Dir > DirectoryList.txt
Dir | Out-File DirectoryList.txt
符合“>
”是PowerShell
向后兼容旧版本cmd
命令的一个快捷方式。实际上还是执行第二条命令的。但是使用Out-File
,通过其提供的一些参数可以定制替代的字符编码(UTF8
等)、追加内容到现有文件等。默认情况下,其创建的文件有80
列宽。
如果是单独的使用Dir
命令,实际上是执行了“Dir | Out-Default | Out-Host
”,Out-Host
是输出到显示器上。以Out
开头的命令中还有一个比较实用的是输出到打印机,即Out-Printer
(只能在Windows
系统中使用)。
如果需要以html
形式输出的,查看以下示例。
Get-Service | ConvertTo-HTML | Out-File services.html
注意:以ConvertTo开头的命令,只是进行文本的转换,并不会保存到磁盘上
接下来的例子是通过管道来修改系统——终止进程和停止服务。
# 绝对不能执行
Get-Service | Stop-Service
Get-Process -name Notepad | Stop-Process
# 执行提示
Get-Process | Stop-Process -confirm
Get-Process | Stop-Process -whatif
最后要说明的是,通过Export-CSV
等命令保存的文件,如果通过Get-Content
获取并显示,则只是获取到了原始文本,即不包括文本格式,而如果通过对应的Import-CSV
后去文件内容并显示,则相对比较友好了。所以建议只有文本文件考虑使用Get-Content
命令。
对象:数据的另一个名称
PowerShell
中通过Get-Member
命令来了解对象,其别名是Gm
。
Get-Process | Gm
在查看Gm
的输出结果中,你会注意到一些不同的属性。
- 脚本属性
- 属性
- NoteProperty
- 别名属性
很多对象都支持一个或多个方法。进程对象包含了一个Kill
方法,它会终止进程。而要终止一个进程,可以通过3种方式。其中一个办法是获取对象并执行Kill
方法,另两种如下:
Get-Process -Name Notepad | Stop-Process
Stop-Process-Name Notepad
PowerShell
提供了Sort-Object
命令来进行排序,可简写为sort
。如对进程列表的虚拟内存(Virtual Memory
,VM
)的消耗由高到低进行排序。
Get-Process | Sort-Object -Property VM
通过Help
命令,我们可以发现Sort-Object
命令有一个参数:-Descending
,其可以反向进行排序,简写为-desc
。
既然可以进行排序,那肯定也是可以选择我们需要的对象属性的。PowerShell
提供了Select-Object
命令,简写为select
。同时也可以通过Where-Object
进行条件的过滤。
Get-Process | ConvertTo-HTML | Out-File test1.html
Get-Process | Select-Object -Property Name,ID,VM,PM | ConvertTo-HTML | Out-File test2.html
PowerShell
管道在最后一个命令执行之前总是传递对象。在最后一个命令执行时,PowerShell
将会查看管道中所包含的对象,并根据不同的配置文件决定哪一个属性被用于构建展示在屏幕上的最终结果。
Get-Process | Sort-Object -Property VM -Desc | Gm
Get-Process | Sort-Object -Property VM -Desc | Select Name,ID,VM | Gm
掌握PowerShell
的一个关键点是在任意时间点知道当前管道中的对象类型。而Gm
将会帮助你实现这一点。
下面列出了一些注意点。
- 请记住,
PowerShell
帮助文件不包含有关对象属性的信息。你必须将对象利用管道传递给Gm
从而查看属性列表 - 请记住,你可以在产生结果的任意管道末尾添加
Gm
命令 - 请注意输入的整洁性。请在管道操作符两侧加入空格
- 请记住,管道中在不同阶段可以包含不同类型的对象。请考虑当前的管道中的对象类型是什么,并把精力集中在下一个命令对当前类型的对象所做的操作
深入理解管道
我们先来看看下面的例子,通过此列子我们来了解PowerShell
中通过ByValue
进行管道输入的方法。
Get-Content .\remote.txt | Get-Service
当前用ByValue
这种方式实现管道参数绑定时,PowerShell
会确认命令A
产生的数据对象类型,然后查看命令B
中哪个参数可以接收经由管道传来对象的类型。
如下,你会看到Get-Content
命令产生结果对象的类型是System.String
。通过查看帮助信息,可以到达Get-Service
中的确也存在可以从ByValue
管道中接收String
类型数据的参数。
PowerShell
只允许使用一个参数接收ByValue
管道返回对象类型。也就意味着,由-Name
参数接收了来自ByValue
管道返回的String
类型数据,那么其他参数就无法再接收该数据。
而使用ByPropertyName
进行管道传输的方法通用需要将命令A
输出结果传递给命令B
的参数。不同的是通过该方法,命令B
的多个参数可以被同时使用。看下面的例子。Shell
对该功能的实现非常简单:仅仅是寻找能够匹配参数名称的属性名称。
Get-Service -Name s* | Stop-Process
在该示例中,-Name
参数可以接收来自ByPropertyName
管道的输出结果,所以这个连接可以正常工作。
接下来看一个通过管道显示自定义属性的例子。
Get-Process | Select-Object -Property *, @{name='myName'; expression={$_.ProcessName}},@{label="myId";expression={$_.Id}}
除了显示自定义的属性外,还可以提取单个属性的值,查看以下例子。通过gm
命令先查看具体的属性有哪些,然后可通过Select-Object
的-ExpandProperty
参数来提取具体的属性值。甚至还可以转成列表html
等形式进行显示。
Get-Process | gm
Get-Process | Select-Object -ExpandProperty ProcessName
格式化及如何正确使用
默认的格式化文件你可以在PowerShell
的安装目录中找到一个名为“*.format.ps1xml
”的文件。其中进程对象的格式化目录在“DotNetTypes.format.ps1xml
”中。可以通过下面的方式查看。
cd $pshome
notepad DotNetTypes.format.ps1xml
对于大部分以Out
开头的命令,都会自动出发格式化系统,以便找到所需的格式化指令。
在PowerShell
中,有个用于格式化的Cmdlets
。我们将介绍日常使用最多的 3 种。首先是“Format-Table
”,其别名为“Ft
”。
Format-Table
常用的参数有:
- -AutoSize:使用此参数,可以强制结果集仅保存足够的列空间,使得表格更加紧凑,但是会使得
Shell
花费额外的时间来生成结果 - -Property:该参数接收一个逗号分隔的列表,该列表包含期望显示的属性值
- -GroupBy:该参数会导致每当指定的属性值发生变化时,生成一个新的列头集合。该参数只有第一次对某个对象的特定属性排序时才能生效
- -Wrap:如果
Shell
需要把列的信息截断,会在列尾带上省略号(...
)以便表示信息被截断。该参数使得Shell
可以换行显示剩余信息,这使你的表变长,但会保留你期望显示的所有消息
有时候你所需要展示的信息过多无法适应表格宽度,这时候使用列表就很恰当。是时候使用“Format-List
”了,其别名是:“Fl
”。其也包含了-Property
属性,实际上,Fl
是另一个用于展示对象属性的方式,和Gm
不同。
Get-Service | Fl *
最后一个Cmdlet
是“Format-Wide
”,别名是“Fw
”,用于展示一个宽列表。它仅展示一个属性的值,所有它的“-Property
”参数仅接受一个属性名称,而不是接受列表,并不接受通配符。
默认情况下,“Format-Wide
”会查找对象的“Name
”属性,因为“Name
”是广泛使用的属性并且通常包含有用信息,该命令默认输出结果只有两列,但是“-Columns
”参数可以用于指定输出更多列。
“Format-Table
”和“Format-List
”都能使用通用的结构创建自定义列或自定义表条目。可以通过提供与属性名称不同的列头创建自定义列。
Get-Service | Format-Table @{name="ServiceName";expression={$_.Name}},Status,DisplayName
甚至使用更加复杂的数学表达式。
Get-Process | Format-Table Name, @{name="VM(MB)";expression={$_.VM / 1mb -as [int]}} -AutoSize
PowerShell
中的斜线是除法操作,另外其能够识别KB
、MB
、GB
、TB
和PB
等缩写-as
操作符可以帮助我们将数据结果从浮点型转换成整型(如指定[int]
)
一旦格式化完成某些对象,你就必须决它的去向。
如果命令最后是Format-
开头的Cmdlet
,其会传递给Out-Default
,然后将结果传递给Out-Host
,最后显示结果到屏幕上。当然也可以通过管道输出到以Out-
开头的Cmdlet
,即Out-File
和Out-Printer
。只有这三个以Out-
开头的Cmdlet
才可以跟在以Format-
开头的Cmdlet
后面。
请记住,Out-File
和Out-Printer
都有默认的输出列宽,可以通过-Width
参数控制宽度输出。
“Out-GridView
”提供另一种形式的输出结果。但是从技术角度来说,这并不是真正意义上的格式化。实际上,“Out-GridView
”完全绕过了格式化子系统。它不需要调用以“Format-
”开头的Cmdlet
,不生产格式化指令,不会在控制台窗口输出文本结果。“Out-GridView
”不接受“Format-
” Cmdlet
输出,仅接受其他Cmdlets
输出的对象。“Out-GridView
”可能无法在非Windows
系统中生效。
过滤和比较
Shell
提供了两种方式缩小结果集,它们都被归结为过滤。第一种方式:尝试指定Cmdlet
命令值检索指定的内容。第二种方式:采用迭代的方法,通过第一个Cmdlet
获取所有结果,并使用第二个Cmdlet
过滤掉不想要的东西。
按道理,应该使用第一种方式:我们称之为尽可能提前过滤,也可称之为“左过滤”。“左过滤”意味着尽可能把过滤条件放置在左侧或者靠近命令的开始部分。越早过滤不需要的对象,就越能减轻其他Cmdlets
命令的工作,并且能减少不必要的信息通过网络传递到你的电脑。
左过滤的缺点是每个Cmdlet
都可以通过自己的方式指定过过滤,并且每个Cmdlet
都会有不同的过滤方式。例如Get-Service
,你只能通过Name
属性过滤服务。但是使用Get-ADComputer
,你可以根据computer
对象可能存在的任何活动目录属性进行过滤。
当无法通过要给Cmdlet
就可以完成你所需要的所有过滤时,你可以使用一个叫做Where-Object
(它的别名是Where
)的核心PowerShell
命令。而这就可能会使用到PowerShell
中的比较操作符。
- -eq——相等
- -ne——不等于
- -ge——大于等于
- -le——小于等于
- -gt——大于
- -lt——小于
对于字符串的比较,如果需要区分大小写,可以使用下面的集合:-ceq
,-cne
,-cgt
,-clt
,-cge
,-cle
。
如果想一次比较多个对象,可以使用布尔运算符-and
和-or
。通常在每个子表达式两边加上括号,使得表达式更容易阅读的。
另一种布尔运算发-not
对true
和false
取反。PowerShell
中对于了$False
和$True
表似false
和true
的布尔值。例如,需要测试要给进程是否没有响应,可以这样(使用$_
作为当前进程的容器):
-not $_.Responding
上面的运行返回True,这就按时这该进程 “没有响应”
当你需要比较文本字符串时,还有其他几个有用的比较运算符。
- -like接收
*
作为通配符,所以可以比较:"Hello" -like "*ll*"
(返回true)。它的反义运算符是-notlike
。它们不区分大小写。区分大小写可以使用-clike
和-cnotlike
- -match用于文本字符串与正则表达式进行比较。
-notmatch
是个逻辑上的反义词。并且-cmatch
和-cnotmatch
提供了区分大小写的语法
Get-Service | Where-Object -filter { $_.Status -dq 'Running' }
Get-Service | Where { $_.Status -dq 'Running' }
-filter参数是一个位置参数,这意味着你经常看到很多命令没有显示指定该参数
我们现在想为你简单介绍PowerShell
迭代命令行模型或者称为PSICLM
。PSICLM
的核心思想在于你不需要一开始就创建一个大而复杂的命令行,而是从简单的开始。
比方说,你想计算正在使用虚拟内容排名前十的进程所占用的虚拟内存总和。如果排名前十的进程种包含PowerShell
进程,而又不想在结果种包含PowerShell
进程,快速罗列出几个需要的步骤。
- 获取进程列表
- 排除
PowerShell
进程 - 按照虚拟内存进行排序
- 只保存前
10
或者最后10
个,这取决于我们的排序方式 - 把剩下进程的虚拟内存相加
可以按照如下命令方式逐步添加:
Get-Process | Where-Object -FilterScript { $_.Name -notlike 'powerShell*' }
Get-Process | Where-Object -FilterScript { $_.Name -notlike 'powershell*' } | Sort-Object VM -descending
Get-Process | Where-Object -FilterScript { $_.Name -notlike 'powershell*' } | Sort-Object VM -descending | Select-Object -First 10
Get-Process | Where-Object -FilterScript { $_.Name -notlike 'powershell*' } | Sort-Object VM -descending | Select-Object -First 10 | Measure-Object -Property VM -Sum
变量:一个存放资料的地方
介绍
PowerShell
并没有对变量有太多的限制。比如,你不需要在使用变量前对其进行显示声明或定义,你也可以更改变量值的类型。PowerShell
中所有的东西都被认为是对象,即使是一个简单的字符串。
$var = "SERVER-R2"
需要注意的是,美元符($
)并不是变量名称的一部分,其只是告诉Shell
接下来的是一个变量名,并且将要赋值给这个变量。
下面我们看看关于变量及其名称的一些注意事项。
- 变量名通常包含字母、数字和下划线,最常见的形式是以字母或下划线开头
- 变量名称可以包含空格,但是名称必须被花括号包住。比如
${My Variable}
表示一个变量名称“My Variable
”,个人不建议使用空格的变量名 - 变量不会驻留在
Shell
会话之间。当关闭Shell
时,所有你创建的变量都会被清除 - 变量名称可以很长——长到你可以不用考虑它到底多长。但是请确保变量名称的可读性
PowerShell
用户通常不需要使用前缀名来表示变量存放的是什么
如果需要查看变量内容,可以使用美元符加上变量名称。你可以在几乎所有地方使用变量来替代值。
Get-WmiObject Win32_ComputerSystem -ComputerName SERVER-R2
Get-WmiObject Win32_ComputerSystem -ComputerName $var
使用变量:关于引号有趣的技巧
PowerShell
会把所有包在单引号中的东西认为是一个文本字符串。如下面的例子。
$var = 'Whate does $var contain?'
$var
# 输出:Whate does $var contain?
但是在双引号中又是另一番情景。
$computername = 'Server-R2'
$phrase = "The computer name is $computername"
$phrase
# 输出:The computer name is Server-R2
PowerShell
自动在双引号中搜索美元符,然后用变量的值替代所有被找到的变量。这种替代操作仅发生在Shell
初次解析字符串时。如果后面变量的值改变了,之前的$phrase
变量的值不变。
关于PowerShell
双引号的另一个窍门是转义字符,这个字符是重音符(`)。看下面的例子,它消除了任何在转义符之后又特殊意义字符的含义,或者在某些情况下增加了字符的特殊意义。
# 消除特殊含义
$computername = 'Server-R2'
$phrase = "`$computername contains $computername"
$phrase
# 输出:$computername contains Server-R2
# 增加特殊意义 ,这里`n的意义是回车换行
$phrase = "`$computername `ncontains `n$computername"
$phrase
# 输出:
# $computername
# contains
# Server-R2
在一个变量中存储多个对象
一种方式是用逗号分隔符列表,PowerShell
认为这些列表是对象的集合
$computername = 'Server-R2','server1','localhost'
$computername
# 输出:
# Server-R2
# server1
# localhost
注意:逗号是在单引号外面,如果是在里面就是一个包含3个计算机名称的单一变量了
你可以在某个时刻访问多值单一变量(一个变量存储多个值)的独立元素。只需要在中括号中指定你要访问的对象的索引号即可。可以从0
开始,第二个值的索引号是1
,以此类推。也可以从-1
开始访问对的最后一个值,-2
为倒数第二个值等。
$computername[0]
# 输出:Server-R2
$computername[1]
# 输出:server1
$computername[-1]
# 输出:localhost
$computername[-2]
# 输出:server1
$computername.count
# 输出:3
你同样可以访问变量内部对象的属性和方法,就像变量自身的属性和方法一样。首先看下单一对象的变量。
$computer ='Server-R2'
$computer.length
# 输出:9
$computer.toupper()
# 输出:SERVER-R2
$computer.tolower()
# 输出:server-r2
$computer.replace('R2','2008')
# 输出:server-2008
$computer
# 输出:Server-R2
而当一个变量包含多个值时,如果相应访问其属性和方法,可以参考下面的例子。
$computername[0].toupper()
# 输出:SERVER-R2
再次提醒,方法会产生新的字符串结果,不会更改变量中的原有值。如果要更改,则需要重新赋值。
$computername[1].replace('server','client')
# 输出:client1
$computername[1] = $computername[1].replace('server','client')
$computername
# 输出:
# Server-R2
# client1
# localhost
在与多个对象交互的时候,还可以考虑使用ForEach-Object
命令。下面的列子的效果和上面的一样。
$computername = $computername | ForEach-Object { $_.ToLower() }
同样也可以将其通过管道传递给Select-Object
对属性做类似的事情。
在PowerShell v3
及之后的版本中对对象的方法和属性的访问做了一些调整。看下面的例子。
$service = Get-Service
$service.name
# 上面的写法,等价于下面的方式实现
Get-Service | ForEach-Object { Write-Output $_.Name }
Get-Service | Select-Object -ExpandProperty Name
这里可以延申一下双引号的技巧使用,比如上面的$service
变量,如何你只想要得到第一个服务名称,该怎么办?可以将命令放入一个表达式中。
$service = Get-Service
$firstname = "The first name is $($service[0].name)"
$firstname
# 输出:The first name is AelookupSvc
而在Powershell v3
及以后的版本中也有一个很酷的功能,可参考下图理解。
声明变量类型
假设你像在变量中放入一个数字,并对其进行计算,该怎么办?这里我们就要在声明变量的时候同时告诉Shell
变量的类型。通过在变量首次使用前使用[]
,明确定义一个数据类型“int
”。
[int] $number = Read-Host "Enter a number"
Enter a number: 100
$number = $number * 10
通过在声明的时候约束变量的类型,也可以避免不必要的麻烦。比如你定义了要给int
类型的变量,如果你输入的字符串,则Shell
会报错。
下面看一下最常用的数据类型清单。
- [int]——整型数字
- [single] 和 [double]——单精度和多精度浮点型数字
- [string]——字符串
- [char]——仅单个字符
- [xml]——一个
XML
文档。不管你如何解析里面的值,都要确保它包含有效的XML
标记(比如[xml] $doc = Get-Content MyXml.xml
) - [adsi]——一个活动目录服务接口(
ADSI
)查询。Shell
会执行查询并把结果对象存入变量(如[adsi] $user="WinNT:\\MYDOMAIN\Administrator,user"
)
和变量相关的命令
- New-Variable
- Set-Variable
- Remove-Variable
- Get-Variable
- Clear-Variable
除了Remove-Variable
之外,其他命令可能都用不上。该命令对需要删除的变量很有用(也可以使用del
删除变量)。基本不建议使用这些Cmdlet
命令,如果需要使用,请提取查询好相关的帮助文档信息。
$LASTEXITCODE变量
PowerShell允许调用外部可执行程序,比如ping.exe。外部程序允许结束后返回一个退出码(或者返回码),通常,0表示成功,其他数字表示失败。使用方式参考下面代码。
ping.exe www.baidu.com
$LASTEXITCODE
# 输出: 0
总结
以上是对PowerShell
基本知识的介绍,如果需要更多的知识,可以进入下一篇的知识深入部分进行了解。