PowerShell 编程:条件、循环及 .NET 交互全解析
1. 条件语句
条件语句在 PowerShell 中能改变脚本的执行流程,常见的条件语句有
if
、
elseif
和
else
语句,以及
switch
语句。
1.1 if、elseif 和 else 语句
if
、
elseif
和
else
语句的基本语法如下:
if(condition)
{
statement block
}
elseif(condition)
{
statement block
}
else
{
statement block
}
如果
condition
计算结果为
$true
,PowerShell 会执行对应的语句块;若为
$false
,则会依次计算后续的
elseif
条件,直到找到匹配的条件。若所有条件都不匹配,会执行
else
语句块。
示例代码:
$textToMatch = Read-Host "Enter some text"
$matchType = Read-Host "Apply Simple or Regex matching?"
$pattern = Read-Host "Match pattern"
if($matchType -eq "Simple")
{
$textToMatch -like $pattern
}
elseif($matchType -eq "Regex")
{
$textToMatch -match $pattern
}
else
{
Write-Host "Match type must be Simple or Regex"
}
1.2 switch 语句
switch
语句的语法有两种形式:
switch options expression
{
comparison value { statement block }
-or-
{ comparison expression } { statement block }
(...)
default { statement block }
}
或
switch options -file filename
{
comparison value { statement block }
-or
{ comparison expression } { statement block }
(...)
default { statement block }
}
PowerShell 计算
switch
语句时,会将
expression
与
switch
主体中的语句进行比较。
switch
语句支持多种选项,如下表所示:
| 选项 | 含义 |
| ---- | ---- |
| -casesensitive (-c) | 区分大小写的匹配。只有当前输入项与比较值完全匹配(大小写敏感)时,才会执行关联的语句块。 |
| -exact (-e) | 精确匹配。当前输入项与比较值完全匹配(不区分大小写)时,执行关联的语句块,这是默认模式。 |
| -regex (-r) | 正则表达式匹配。当前输入项与比较值指定的正则表达式匹配(不区分大小写)时,执行关联的语句块。 |
| -wildcard (-w) | 通配符匹配。当前输入项与比较值指定的通配符匹配(不区分大小写)时,执行关联的语句块。通配符支持
?
(任意单个未指定字符)、
*
(零个或多个未指定字符)、
[a-b]
(a - b 范围内的任意字符)、
[ab]
(指定字符 a 或 b)。 |
示例代码:
$myPhones = "(555) 555-1212","555-1234"
switch -regex ($myPhones)
{
{ $_.Length -le 8 } { "Area code was not specified"; break }
{ $_.Length -gt 8 } { "Area code was specified" }
"\((555)\).*" { "In the $($matches[1]) area code" }
}
输出结果:
Area code was specified
In the 555 area code
Area code was not specified
2. 循环语句
循环语句能让 PowerShell 多次执行一组语句,常见的循环语句有
for
、
foreach
、
while
、
do … while
和
do … until
语句。
2.1 for 语句
for
语句的基本语法如下:
:loop_label for (initialization; condition; increment)
{
statement block
}
PowerShell 执行
for
语句时,先执行
initialization
表达式,然后计算
condition
。若
condition
为
$true
,则执行语句块,接着执行
increment
表达式,只要
condition
为
$true
,就会继续执行语句块和
increment
语句。
示例代码:
for($counter = 0; $counter -lt 10; $counter++)
{
Write-Host "Processing item $counter"
}
2.2 foreach 语句
foreach
语句的基本语法如下:
:loop_label foreach (variable in expression)
{
statement block
}
PowerShell 执行
foreach
语句时,会执行
expression
给出的管道,为表达式产生的每个项,将其赋值给
variable
,然后执行语句块。
示例代码:
$handleSum = 0;
foreach($process in Get-Process |
Where-Object { $_.Handles -gt 500 })
{
$handleSum += $process.Handles
}
$handleSum
2.3 while 语句
while
语句的基本语法如下:
:loop_label while(condition)
{
statement block
}
PowerShell 执行
while
语句时,先计算
condition
表达式。若为
$true
,则执行语句块,只要
condition
为
$true
,就会继续执行语句块。
示例代码:
$command = "";
while($command -notmatch "quit")
{
$command = Read-Host "Enter your command"
}
2.4 do … while 和 do … until 语句
do … while
和
do … until
语句的基本语法如下:
:loop_label do
{
statement block
} while(condition)
或
:loop_label do
{
statement block
} until(condition)
PowerShell 执行
do … while
或
do … until
语句时,先执行语句块。在
do … while
语句中,只要
condition
为
$true
,就会继续执行语句块;在
do … until
语句中,只要
condition
为
$false
,就会继续执行语句。
示例代码:
$validResponses = "Yes","No"
$response = ""
do
{
$response = read-host "Yes or No?"
} while($validResponses -notcontains $response)
"Got it."
$response = ""
do
{
$response = read-host "Yes or No?"
} until($validResponses -contains $response)
"Got it."
3. 流程控制语句
PowerShell 支持
break
和
continue
语句来控制循环内的流程。
3.1 break 语句
break
语句会停止当前循环的执行,PowerShell 会从当前循环语句的末尾继续执行。
示例代码:
for($counter = 0; $counter -lt 5; $counter++)
{
for($counter2 = 0; $counter2 -lt 5; $counter2++)
{
if($counter2 -eq 2)
{
break
}
Write-Host "Processing item $counter,$counter2"
}
}
输出结果:
Processing item 0,0
Processing item 0,1
Processing item 1,0
Processing item 1,1
Processing item 2,0
Processing item 2,1
Processing item 3,0
Processing item 3,1
Processing item 4,0
Processing item 4,1
若指定标签,如
break outer_loop
,则会停止该标签对应的循环。
示例代码:
:outer_loop for($counter = 0; $counter -lt 5; $counter++)
{
for($counter2 = 0; $counter2 -lt 5; $counter2++)
{
if($counter2 -eq 2)
{
break outer_loop
}
Write-Host "Processing item $counter,$counter2"
}
}
输出结果:
Processing item 0,0
Processing item 0,1
3.2 continue 语句
continue
语句会跳过当前语句块的剩余部分,然后继续当前循环的下一次迭代。
示例代码:
for($counter = 0; $counter -lt 5; $counter++)
{
for($counter2 = 0; $counter2 -lt 5; $counter2++)
{
if($counter2 -eq 2)
{
continue
}
Write-Host "Processing item $counter,$counter2"
}
}
输出结果:
Processing item 0,0
Processing item 0,1
Processing item 0,3
Processing item 0,4
Processing item 1,0
Processing item 1,1
Processing item 1,3
Processing item 1,4
Processing item 2,0
Processing item 2,1
Processing item 2,3
Processing item 2,4
Processing item 3,0
Processing item 3,1
Processing item 3,3
Processing item 3,4
Processing item 4,0
Processing item 4,1
Processing item 4,3
Processing item 4,4
若指定标签,如
continue outer_loop
,则会继续该标签对应循环的下一次迭代。
示例代码:
:outer_loop for($counter = 0; $counter -lt 5; $counter++)
{
for($counter2 = 0; $counter2 -lt 5; $counter2++)
{
if($counter2 -eq 2)
{
continue outer_loop
}
Write-Host "Processing item $counter,$counter2"
}
}
输出结果:
Processing item 0,0
Processing item 0,1
Processing item 1,0
Processing item 1,1
Processing item 2,0
Processing item 2,1
Processing item 3,0
Processing item 3,1
Processing item 4,0
Processing item 4,1
4. 工作流特定语句
在工作流中,PowerShell 支持
InlineScript
、
Parallel
、
Sequence
和
foreach -parallel
语句。
4.1 InlineScript
InlineScript
关键字定义一个 PowerShell 脚本岛,会作为一个单元调用,具有传统 PowerShell 脚本语义。
示例代码:
workflow MyWorkflow
{
## Method invocation not supported in a workflow
## [Math]::Sqrt(100)
InlineScript
{
## Supported in an InlineScript
[Math]::Sqrt(100)
}
}
4.2 Parallel/Sequence
Parallel
关键字指定语句块内的所有语句应并行运行,
Sequence
关键字用于将应作为一个单元运行的语句分组。
示例代码:
workflow MyWorkflow
{
Parallel
{
InlineScript { Start-Sleep -Seconds 2; "One thing run in parallel" }
InlineScript { Start-Sleep -Seconds 4; "Another thing run in parallel" }
InlineScript { Start-Sleep -Seconds 3; "A third thing run in parallel" }
Sequence
{
Start-Sleep -Seconds 1
"A fourth"
"and fifth thing run as a unit, in parallel"
}
}
}
4.3 Foreach -Parallel
Foreach -Parallel
类似于传统的
foreach
语句,但会并行处理集合的每个元素。
示例代码:
workflow MyWorkflow
{
$items = 1..10
foreach -parallel ($item in $items)
{
$sleep = Get-Random -Max 200
Start-Sleep -Milliseconds $sleep
$item
}
}
5. 与 .NET 框架交互
PowerShell 能借助 Microsoft 的 .NET 框架进行系统管理和应用开发,主要通过调用方法或访问属性来与 .NET 框架交互。
5.1 静态方法
调用类的静态方法,语法如下:
[ClassName]::MethodName(parameter list)
示例代码:
PS > [System.Diagnostics.Process]::GetProcessById(0)
输出结果:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
0 0 0 16 0 0 Idle
5.2 实例方法
调用对象实例的方法,语法如下:
$objectReference.MethodName(parameter list)
示例代码:
PS > $process = [System.Diagnostics.Process]::GetProcessById(0)
PS > $process.Refresh()
5.3 显式实现的接口方法
调用显式实现的接口方法,语法如下:
([Interface] $objectReference).MethodName(parameter list)
示例代码:
PS > ([IConvertible] 123).ToUint16($null)
5.4 静态属性
访问类的静态属性,语法如下:
[ClassName]::PropertyName
或
[ClassName]::PropertyName = value
示例代码:
PS > [System.DateTime]::Now
输出结果:
Sunday, July 16, 2006 2:07:20 PM
5.5 实例属性
访问对象的实例属性,语法如下:
$objectReference.PropertyName
或
$objectReference.PropertyName = value
示例代码:
PS > $today = [System.DateTime]::Now
PS > $today.DayOfWeek
输出结果:
Sunday
6. 了解类型
了解类和类型的主要途径有
Get-Member
cmdlet 和 .NET 框架文档。
6.1 Get-Member cmdlet
使用
Get-Member
cmdlet 了解给定类型支持的方法和属性,不同操作的结果如下表所示:
| 操作 | 结果 |
| ---- | ---- |
| [typename] | Get-Member -Static | 给定类型的所有静态方法和属性。 |
| $objectReference | Get-Member -Static | $objectReference 类型提供的所有静态方法和属性。 |
| $objectReference | Get-Member | $objectReference 类型提供的所有实例方法和属性。若 $objectReference 表示一个项的集合,PowerShell 会返回该集合包含的类型的实例和属性。要查看集合本身的实例和属性,使用 Get-Member 的 -InputObject 参数:Get-Member -InputObject $objectReference |
| [typename] | Get-Member | 表示此类型的 System.Runtime Type 对象的所有实例方法和属性。 |
6.2 .NET 框架文档
通过搜索功能可获取 .NET 框架类的文档,为快速找到成员文档,可在 MSDN 搜索词中添加 “members” 一词,如 “classname members”。类成员文档会列出构造函数、方法、属性等,用 S 图标表示静态方法和属性,点击成员名称可获取更多信息。
7. 类型快捷方式
指定类型名称时,PowerShell 允许对一些常见类型使用缩写形式,如下表所示:
| 类型快捷方式 | 完整类名 |
| ---- | ---- |
| [Adsi] | [System.DirectoryServices.DirectoryEntry] |
| [AdsiSearcher] | [System.DirectoryServices.DirectorySearcher] |
| [Float] | [System.Single] |
| [Hashtable] | [System.Collections.Hashtable] |
| [Int] | [System.Int32] |
| [IPAddress] | [System.Net.IPAddress] |
| [Long] | [System.Collections.Int64] |
| [PowerShell] | [System.Management.Automation.PowerShell] |
| [PSCustomObject] | [System.Management.Automation.PSObject] |
| [PSModuleInfo] | [System.Management.Automation.PSModuleInfo] |
| [PSObject] | [System.Management.Automation.PSObject] |
| [Ref] | [System.Management.Automation.PSReference] |
| [Regex] | [System.Text.RegularExpressions.Regex] |
| [Runspace] | [System.Management.Automation.Runspaces.Runspace] |
| [RunspaceFactory] | [System.Management.Automation.Runspaces.RunspaceFactory] |
| [ScriptBlock] | [System.Management.Automation.ScriptBlock] |
| [Switch] | [System.Management.Automation.SwitchParameter] |
| [Wmi] | [System.Management.ManagementObject] |
| [WmiClass] | [System.Management.ManagementClass] |
| [WmiSearcher] | [System.Management.ManagementObjectSearcher] |
| [Xml] | [System.Xml.XmlDocument] |
| [TypeName] | [System.TypeName] |
8. 创建类型实例
使用
New-Object
cmdlet 创建指定类型的实例,语法如下:
$objectReference = New-Object TypeName parameters
示例代码:
$webClient = New-Object Net.WebClient
$webClient.DownloadString("http://search.msn.com")
若类型为泛型类型,需将类型参数括在方括号中:
PS > $hashtable = New-Object "System.Collections.Generic.Dictionary[String,Bool]"
PS > $hashtable["Test"] = $true
许多类型需加载定义它们的库(程序集)后才能使用,使用
Add-Type
cmdlet 的
-AssemblyName
参数加载程序集。
示例代码:
PS > Add-Type -AssemblyName System.Web
PS > [Web.HttpUtility]::UrlEncode("http://www.bing.com")
输出结果:
http%3a%2f%2fwww.bing.com
9. 与 COM 对象交互
PowerShell 可像与 .NET 框架对象交互一样访问 COM 对象的方法和属性,使用
New-Object
的
-ComObject
参数(常缩写为
-Com
)结合 COM 对象的 ProgId 来交互。
示例代码:
PS > $shell = New-Object -Com Shell.Application
PS > $shell.Windows() | Select-Object LocationName,LocationUrl
10. 扩展类型
PowerShell 支持两种向任何类型添加自定义方法和属性的方式:
Add-Member
cmdlet 和自定义类型扩展文件。
10.1 Add-Member cmdlet
Add-Member
cmdlet 可动态向对象添加方法、属性等,支持的扩展类型如下表所示:
| 成员类型 | 含义 |
| ---- | ---- |
| AliasProperty | 定义为另一个属性别名的属性。 |
| CodeProperty | 由 System.Reflection.MethodInfo 定义的属性,此方法必须是公共、静态的,返回结果(非 void),并接受一个 PsObject 类型的参数。 |
| NoteProperty | 由提供的初始值定义的属性。 |
| ScriptProperty | 由提供的脚本块定义的属性,脚本块中 $this 指当前实例。 |
| PropertySet | 定义为一组属性快捷方式的属性,用于 Select-Object 等 cmdlet。 |
| CodeMethod | 由 System.Reflection.MethodInfo 定义的方法,此方法必须是公共、静态的,并接受一个 PsObject 类型的参数。 |
| ScriptMethod | 由提供的脚本块定义的方法,脚本块中 $this 指当前实例,$args 指输入参数。 |
示例代码:
# AliasProperty
PS > $testObject = [PsObject] "Test"
PS > $testObject | Add-Member "AliasProperty" Count Length
PS > $testObject.Count
4
# NoteProperty
PS > $testObject = [PsObject] "Test"
PS > $testObject | Add-Member NoteProperty Reversed tseT
PS > $testObject.Reversed
tseT
# ScriptProperty
PS > $testObject = [PsObject] ("Hi" * 100)
PS > $testObject | Add-Member ScriptProperty IsLong {
$this.Length -gt 100
}
PS > $testObject.IsLong
True
# PropertySet
PS > $testObject = [PsObject] [DateTime]::Now
PS > $collection = New-Object `
Collections.ObjectModel.Collection``1[System.String]
$collection.Add("Month")
$collection.Add("Year")
$testObject | Add-Member PropertySet MonthYear $collection
$testObject | select MonthYear
Month Year
----- ----
3 2010
# ScriptMethod
PS > $testObject = [PsObject] "Hello"
PS > $testObject | Add-Member ScriptMethod IsLong {
$this.Length -gt $args[0]
}
PS > $testObject.IsLong(3)
True
PS > $testObject.IsLong(100)
False
10.2 自定义类型扩展文件
除了
Add-Member
cmdlet,PowerShell 还支持配置文件,可用于自定义给定类型的所有对象,例如为所有字符串添加
Reverse()
方法或为所有类型添加
HelpUrl
属性。
PowerShell 编程:条件、循环及 .NET 交互全解析
11. 总结与应用建议
通过前面的介绍,我们已经全面了解了 PowerShell 在条件语句、循环语句、流程控制、工作流特定语句以及与 .NET 框架和 COM 对象交互等方面的知识。下面是一些在实际应用中的建议和总结。
11.1 条件与循环语句的应用
-
条件语句
:在需要根据不同情况执行不同操作时,
if-elseif-else和switch语句非常有用。例如,在脚本中根据用户输入的不同选项执行不同的任务。当条件较为简单且相互独立时,使用if-elseif-else语句;当需要对一个值进行多种匹配时,switch语句更为合适。 -
循环语句
:根据不同的需求选择合适的循环语句。
for语句适用于已知循环次数的情况;foreach语句适用于遍历集合中的每个元素;while和do-while、do-until语句适用于根据条件进行循环的情况,其中do-while和do-until至少会执行一次循环体。
下面是一个综合使用条件和循环语句的示例,用于统计一个数组中正数、负数和零的个数:
$numbers = -2, 0, 5, -1, 3, 0, -4
$positiveCount = 0
$negativeCount = 0
$zeroCount = 0
foreach ($number in $numbers) {
if ($number -gt 0) {
$positiveCount++
} elseif ($number -lt 0) {
$negativeCount++
} else {
$zeroCount++
}
}
Write-Host "Positive numbers: $positiveCount"
Write-Host "Negative numbers: $negativeCount"
Write-Host "Zero numbers: $zeroCount"
11.2 流程控制语句的应用
break
和
continue
语句可以帮助我们更灵活地控制循环的执行。
break
语句用于提前终止循环,而
continue
语句用于跳过当前循环的剩余部分,继续下一次循环。在嵌套循环中,使用标签可以指定要控制的具体循环。
例如,在一个二维数组中查找第一个大于 10 的元素,并输出其位置:
$matrix = @(
@(1, 2, 3),
@(4, 11, 6),
@(7, 8, 9)
)
:outerLoop for ($i = 0; $i -lt $matrix.Length; $i++) {
for ($j = 0; $j -lt $matrix[$i].Length; $j++) {
if ($matrix[$i][$j] -gt 10) {
Write-Host "First element greater than 10 found at position ($i, $j)"
break outerLoop
}
}
}
11.3 工作流特定语句的应用
在处理复杂的任务时,工作流特定语句如
InlineScript
、
Parallel
、
Sequence
和
foreach -parallel
可以提高脚本的执行效率。
InlineScript
用于在工作流中执行传统的 PowerShell 脚本;
Parallel
用于并行执行多个任务;
Sequence
用于将一组任务作为一个单元执行;
foreach -parallel
用于并行处理集合中的元素。
例如,模拟一个并行处理多个文件的工作流:
workflow ProcessFiles {
$files = "file1.txt", "file2.txt", "file3.txt"
foreach -parallel ($file in $files) {
InlineScript {
Write-Host "Processing file: $using:file"
Start-Sleep -Seconds 2
Write-Host "Finished processing file: $using:file"
}
}
}
ProcessFiles
11.4 与 .NET 框架和 COM 对象交互的应用
PowerShell 与 .NET 框架和 COM 对象的交互能力使得我们可以利用丰富的类库和功能。在需要进行系统管理、文件操作、网络编程等方面,与 .NET 框架交互可以提供强大的支持;而与 COM 对象交互则可以访问一些旧的应用程序和系统组件。
例如,使用 .NET 框架的
System.IO
类来创建一个文件并写入内容:
$filePath = "test.txt"
$fileContent = "This is a test file."
[System.IO.File]::WriteAllText($filePath, $fileContent)
Write-Host "File created and content written."
12. 流程图示例
下面是一个简单的 mermaid 流程图,展示了
if-elseif-else
语句的执行流程:
graph TD;
A[开始] --> B{条件1是否为真};
B -- 是 --> C[执行语句块1];
C --> D[结束];
B -- 否 --> E{条件2是否为真};
E -- 是 --> F[执行语句块2];
F --> D;
E -- 否 --> G[执行 else 语句块];
G --> D;
13. 总结
PowerShell 是一个功能强大的脚本语言,通过条件语句、循环语句、流程控制语句、工作流特定语句以及与 .NET 框架和 COM 对象的交互,我们可以实现各种复杂的任务。在实际应用中,根据具体需求选择合适的语句和方法,合理利用 PowerShell 的特性,可以提高脚本的效率和可维护性。
希望本文能够帮助你更好地掌握 PowerShell 的相关知识,并在实际工作中发挥作用。不断实践和探索,你将发现 PowerShell 在系统管理和自动化任务方面的巨大潜力。
以上就是关于 PowerShell 编程的全面介绍,如果你有任何问题或建议,欢迎留言讨论。
PowerShell条件循环与.NET交互
超级会员免费看

被折叠的 条评论
为什么被折叠?



