PowerShell 基础
PowerShell 是一种跨平台的自动化任务解决方案,由命令行shell、脚本语言和配置管理框架组成。PowerShell可以在 Windows、Linux 和 macOS 上运行。
PowerShell 是新式的命令shell,包括其他常用 shell 的基本功能,且能接受并返回.NET对象 。可通过函数、类、脚本和模块进行扩展,同时对常用数据格式提供内置支持(如 CSV, JSON, XML ) 。
PowerShell 命令称为 cmdlet
(读作 command-let)。 除了 cmdlet 外,使用 PowerShell 还可以在系统上运行任何可用命令 。cmdlet 是本机 PowerShell 命令,而不是独立的可执行文件。 cmdlet 收集在 PowerShell 模块中,可按需加载。 可以用任何编译的 .NET 语言或 PowerShell 脚本语言本身来编写 cmdlet 。
1. 参考资料
2. Visual Studio Code 集成 PowerShell
在VSCode中安装 PowerShell
扩展
全局设置中增加配置
{
...
"[powershell]" : {
"files.encoding" : "utf8bom" ,
"files.autoGuessEncoding" : true ,
"editor.renderWhitespace" : "all" ,
"editor.renderControlCharacters" : true ,
"files.trimTrailingWhitespace" : true
} ,
"powershell.integratedConsole.suppressStartupBanner" : true ,
"powershell.integratedConsole.showOnStartup" : true ,
"powershell.integratedConsole.focusConsoleOnExecute" : true ,
"powershell.debugging.createTemporaryIntegratedConsole" : true
}
重启 VSCode,新建或打开 .ps1
文件输入脚本,就可以打断点调试了。
3. 变量
在powershell中变量名均是以美元符 $
开始,剩余字符可以是数字、字母、下划线的任意字符,并且powershell变量名大小写不敏感($a
和$A
是同一个变量)。
某些特殊的字符在powershell中有特殊的用途,一般不推荐使用这些字符作为变量名。当然你硬要使用,请把整个变量名后缀用 花括号 ${变量名}
括起来。
赋值操作符为 =
,几乎可以把任何数据赋值给一个变量,甚至一条 cmdlet
命令。
变量的作用域
- `$global` 全局变量,在所有的作用域中有效,如果你在脚本或者函数中设置了全局变量,即使脚本和函数都运行结束,这个变量也任然有效。
- `$script` 脚本变量,只会在脚本内部有效,包括脚本中的函数,一旦脚本运行结束,这个变量就会被回收。
- `$private` 私有变量,只会在当前作用域有效,不能贯穿到其他作用域。
- `$local` 默认变量,可以省略修饰符,在当前作用域有效,其它作用域只对它有只读权限。
定义变量
$a =10
$b =4
$msg ="保存文本"
$ {"I" like $ }="mossfly"
$item =Get-ChildItem .
New-Variable num -Value 100 -Force -Option readonly
new-variable num -Value "strong" -Option constant
new-variable name -Value "me" -Description "This is my name"
[byte ]$b =101
[XML ]$xml =(Get-Content .xxxx.xml)
$xml .Note.Note
文本
使用引号可以定义字符串,如果想让自己定义的字符串原样输出,可以使用单引号。
$text ='$fei $(tai) $env:windir 大白博客 (20+2012)'
$site ="飞苔博客 Powershell博客"
$text ="$site $ (get-date) $env:windir "
文本中的特殊字符
"系统目录位于:$env:windir "
"默认安装程序目录位于:$env:ProgramFiles "
"机器名为:$env:computername "
"当前日期:$ (get-date)"
"1GB=$ (1gb/1kb)KB"
转义字符
| 转义字符 | 描述 |
| --- | --- |
| `n | 换行符 |
| `r | 回车符 |
| `t | 制表符 |
| `a | 响铃符 |
| `b | 退格符 |
| `' | 单引号 |
| `" | 双引号 |
| `0 | Null |
| ` | 反引号本身 |
'The site of my blog is"www.mossfly.com"'
“My blog site is`"www.mossfly.com`""
# 在字符串中输出换行符
“The site of my blog is `"www.mossfly.com`",`n大白博客"
定义多行文本
这里要注意开始和结束的标记必须另起一行。
@"
这首诗用来评价陶渊明的诗歌再好不过了
一语天然万古新,豪华落尽见真淳。
南窗白日羲皇上,未害渊明是晋人。
"@
用户交互
如果要提示用户输入可以使用 read-host
。read-host
不会自动解析变量。,不过可以通过ExpandString方法解析。
PS E:> $name =Read-Host "请输入您的用户名"
请输入您的用户名: Mosser Lee
PS E:> "您输入的用户名为:$name "
您输入的用户名为:Mosser Lee
PS E:> $inputPath =Read-Host "请输入文件路径"
请输入文件路径: $env:windir
PS E:> $inputPath
$env:windir
PS E:> $ExecutionContext .InvokeCommand.ExpandString($inputPath )
C:windows
接受敏感数据
PS E:> $pwd =Read-Host -AsSecureString "请输入密码"
请输入密码: ******
PS E:> $pwd
System.Security.SecureString
PS E:> [Runtime.InteropServices.Marshal ]::PtrToStringAuto([Runtime.InteropServices.Marshal ]::SecureStringToBSTR($pwd ))
abc123
询问用户名和密码
使用 Get-Credential
命令,该命令会弹出一个安全对话框,一旦用户输入完毕,就会返回一个Credential对象包含用户名和密码。
$cre =Get-Credential myUserName
$pwd =[Runtime.InteropServices.Marshal ]::PtrToStringAuto([Runtime.InteropServices.Marshal ]::SecureStringToBSTR($cre .Password))
"$ ($cre .UserName), 您的密码: $pwd "
字符串处理
参考:
格式化
"{0} diskettes per CD" -f (720 mb/1.44 mb)
500 diskettes per CD
"Date: {0:d}" -f (Get-Date )
Date: 2013 /5 /31
"Date: {0:D}" -f (Get-Date )
Date: 2013 年5 月31
dir | ForEach-Object { "{0,-20} = {1,10} Bytes" -f $_ .name, $_ .Length }
$date = Get-Date
Foreach ($format in "d" ,"D" ,"f" ,"F" ,"g" ,"G" ,"m" ,"r" ,"s" ,"t" ,"T" , `
"u" ,"U" ,"y" ,"dddd, MMMM dd yyyy" ,"M/yy" ,"dd-MM-yy" ) {
"PowerShell 日期格式, 使用 $format : {0}" -f $date .ToString($format ) }
生成 GUID
PS > $guid = [GUID ]::NewGUID()
PS > Foreach ($format in "N" ,"D" ,"B" ,"P" ) {
>> "GUID with $format : {0}" -f $GUID .ToString($format )}
>>
GUID with N : e1a5d98f4227470b84c2b37a6a8fb894
GUID with D : e1a5d98f-4227-470b-84c2-b37a6a8fb894
GUID with B : {e1a5d98f-4227-470b-84c2-b37a6a8fb894 }
GUID with P : (e1a5d98f-4227-470b-84c2-b37a6a8fb894 )
替换成目标文本
-replace
操作符有三种实现方式,其它文本操作符也类似地有三种实现方式,像 -replace
,-ireplace
,-creplace
,i前缀表示字符串大小写不敏感,c前缀表示字符串大小写敏感。
"Hello Carl" -replace "Carl" , "Eddie"
Hello Eddie
"Hello Carl" -creplace "carl" , "eddie"
Hello Carl
合并字符串
验证是否相等
"Power" -eq "power"
"Power" -ceq "power"
验证包含关系
验证不包含关系
"PoserShell" -notlike "ps"
"PoserShell" -cnotlike "PO*"
验证模式匹配
"PoserShell" -match "P*"
"Hello" -cmatch "[ao]"
"Hello" -notmatch "[ao]"
"Hello" -cnotmatch "[ao]"
数组
$nums1 =2 ,0 ,1 ,2
$nums2 =1 ..5
$array =1 ,"2012世界末日" ,([System.Guid ]::NewGuid()),(get-date )
$a =@ ()
$a =,"moss"
$a .Count
$array [0 ]
$array [($array .Count -1 )]
$result =ls
$result [0 ,3 ,5 ,12 ]
$books ="元素1" ,"元素2" ,"元素3"
$books +="元素4"
$num =1 ..4
$num =$num [0 ..1 ]+$num [3 ]
$chs =@ ("A" ,"B" ,"C" )
$chsBak =$chs
$chsNew =$chs .Clone()
$chs .Equals($chsBak )
[int []] $nums =@ ()
哈希表
$stu =@ { Name = "小明" ;Age="12" ;sex="男" }
$stu ["Name" ]
$stu .Count
$stu .Keys
$stu .Values
$stu =@ { Name = "小明" ;Age="12" ;sex="男" ;Books="三国演义" ,"围城" ,"哈姆雷特" }
$Student =@ {}
$Student .Name="令狐冲"
$Student .School="华山派"
$stu .Name="赵强"
$stu .Remove("Name" )
计算变量
PowerShell也能自动识别计算机容量单位,包括KB,MB,GB,TB,PB
$value =80 kb*800 *30 /1 gb
$value =10 GB/(80 KB*5 )/30
同时给多个变量赋值
交换变量的值
$Value1 = 10
$Value2 = 20
$value1 ,$value2 =$value2 ,$value1
查看正在使用的变量
ls variable:
Get-ChildItem variable:
ls variable:value*
验证变量是否存在
验证一个变量是否存在,仍然可以象验证文件系统那样,使用cmdlet Test -Path。因为变量存在变量驱动器中。
Test-Path variable:value1
判断变量是否是数组
"abac" -is [array ]
$str ="字符串"
$str .ToCharArray() -is [array ]
删除变量
在控制台中输出变量
$result
$msg
$books ="元素1" ,"元素2" ,"元素3"
$books [($books .Count )..0 ]
Dir | Format-Table
Dir | Format-Table FullName,Mode
$column1 = @ {expression="Name" ; width=30 ;label="filename" ; alignment="left" }
$column2 = @ {expression="LastWriteTime" ; width=40 ;label="last modification" ; alignment="right" }
ls | Format-Table $column1 , $column2
对象
$obj =New-Object object
Add-Member -InputObject $obj -Name Color -Value "Red"
Add-Member -InputObject $obj -Name Weight -Value "55"
$obj | Add-Member NoteProperty Blades 3
$obj | Add-Member NoteProperty Manufacturer ABC
Add-Member -memberType ScriptMethod -In $obj -name cut -Value { "I'm whittling now" }
Add-Member -in $obj ScriptMethod screw { "Phew...it's in!" }
$obj | Add-Member ScriptMethod corkscrew { "Pop! Cheers!" }
$obj .cut()
$obj .screw()
$obj .corkscrew()
[System.DateTime ] | Get-Member -static -memberType *Method
[DateTime ]$date ="1999-9-1 10:23:44"
加载C#程序集
自定义一个简单的 C#
类库编译为Test.dll。
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
namespace Test
{
public class Student
{
public string Name { set ; get ; }
public int Age { set ; get ; }
public Student (string name, int age )
{
this .Name = name;
this .Age = age;
}
public override string ToString ()
{
return string .Format("Name={0};Age={1}" , this .Name,this .Age);
}
}
}
在Powershell中加载这个dll并使用其中的Student类的构造函数生成一个实例,最后调用ToString()方法。
$TestDLL =ls .Test.dll
[reflection.assembly ]::LoadFile($TestDLL .FullName)
$stu =New-Object Test.Student('Mosser' ,22 )
$stu .ToString()
查看可用的COM对象
每一个COM对象都有存储在注册表中的唯一标识符,想遍历访问可用的COM对象,可是直接访问注册表。
Dir REGISTRY::HKEY_CLASSES_ROOTCLSID -include PROGID -recurse | foreach {$_ .GetValue("" )}
DAO.DBEngine.36
DAO.PrivateDBEngine.36
DAO.TableDef.36
DAO.Field.36
DAO.Index.36
PS C:Powershell> Dir REGISTRY::HKEY_CLASSES_ROOTCLSID -include PROGID -recurse
| foreach {$_ .GetValue("" )} | select -First 10
DAO.DBEngine.36
DAO.PrivateDBEngine.36
DAO.TableDef.36
DAO.Field.36
DAO.Index.36
DAO.Group.36
DAO.User.36
DAO.QueryDef.36
DAO.Relation.36
file
......
使用 COM 对象
一旦得到了COM对象的ProgID,就可以使用New-Object创建COM对象,只需要指定参数为 -comObject
。
PS C:Powershell> New-Object -ComObject DAO.Relation.36
Properties : System.__ComObject
Name :
Table :
ForeignTable :
Attributes : 0
Fields : System.__ComObject
PartialReplica :
获得对象的属性和方法
COM对象的和.NET对象相似,任然可是使用Get-Member 得到该对象的所有熟悉和方法
$DBEng =New-Object -ComObject DAO.PrivateDBEngine.36
$DBEng | Get-Member -me *method
$DBEng | Get-Member -me *property
常用的COM对象
WScript.Shell
WScript.Network
Scripting.FileSystemObject
InternetExplorer.Application
Word.Application
Shell.Application
$wshell =New-Object -ComObject WScript.shell
$path =[environment ]::GetFolderPath('Desktop' )
$link =$wshell .CreateShortcut(“$path /Powershell.lnk”)
$link | Get-Member
$link .TargetPath='Powershell.exe'
$link .Description="启动Powershell"
$link .WorkingDirectory=$PROFILE
$link .IconLocation='Powershell.exe'
$link .Save()
自动化变量
Powershell 自动化变量 是那些一旦打开Powershell就会自动加载的变量。
这些变量一般存放的内容包括:
用户信息:例如用户的根目录 $home
配置信息: 例如powershell控制台的大小,颜色,背景等。
运行时信息:例如一个函数由谁调用,一个脚本运行的目录等。
可以通过 Get-Help about_Automatic_variables
查看自动化变量的帮助信息
PS > Get-Help about_Automatic_variables
Name Valueiables
---- ----- ~~~~~~
? Truet_Automatic_variables in a help file in this session. To download updated help topics type : "Update-Help" . To get help online, search for the help
^ rary at https://go.microsoft.com/fwlink/?LinkID=107116 .
$
args {}
ConfirmPreference High
DebugPreference SilentlyContinue
EnabledExperimentalFeatures {}
Error {Get-Help could not find about_Automatic_variables in a help file in this session. To download updated help topics type : "Update-Help" . To get help online, searc…
ErrorActionPreference Continue
ErrorView ConciseView
ExecutionContext System.Management.Automation.EngineIntrinsics
...
详细说明
$$
包含会话所收到的最后一行中的最后一个令牌。
$?
包含最后一个操作的执行状态。如果最后一个操作成功,则包含 TRUE,失败则包含 FALSE。
$^
包含会话所收到的最后一行中的第一个令牌。
$_
包含管道对象中的当前对象。在对管道中的每个对象或所选对象执行操作的命令中,可以使用此变量。
$Args
包含由未声明参数和/或传递给函数、脚本或脚本块的参数值组成的数组。在创建函数时可以声明参数,方法是使用 param 关键字或在函数名称后添加以圆括号括起、逗号分隔的参数列表。
$ConsoleFileName
包含在会话中最近使用的控制台文件 (.psc1) 的路径。在通过 PSConsoleFile 参数启动 Windows PowerShell 或使用 Export-Console cmdlet 将管理单元名称导出到控制台文件时,将填充此变量。在使用不带参数的 Export-Console cmdlet 时,它自动更新在会话中最近使用的控制台文件。可以使用此自动变量确定要更新的文件。
$Error
包含错误对象的数组,这些对象表示最近的一些错误。最近的错误是该数组中的第一个错误对象 ($Error[0]
)。
$Event
包含一个 PSEventArgs 对象,该对象表示一个正在被处理的事件。此变量的值是 Get-Event cmdlet 返回的同一个对象。因此,可以在 Action 脚本块中使用 $Event
变量的属性(例如 Event.TimeGenerated)
$EventSubscriber
包含一个 PSEventSubscriber 对象,该对象表示正在被处理的事件的事件订阅者。
此变量只在事件注册命令的 Action 块内填充。此变量的值
是 Get-EventSubscriber cmdlet 返回的同一个对象。
$ExecutionContext
包含一个 EngineIntrinsics 对象,该对象表示 Windows PowerShell 主机的执行上下文。可以使用此变量来查找可用于 cmdlet 的执行对象。
$False
包含 FALSE。可以使用此变量在命令和脚本中表示 FALSE,而不是使用字符串”false”。如果该字符串转换为非空字符串或非零整数,则可将该字符串解释为 TRUE。
$ForEach
包含 ForEach-Object 循环的枚举数。可以对 $ForEach
变量的值使用枚举数的属性和方法。此变量仅在运行 For 循环时存在,循环完成即会删除。
$Home
包含用户的主目录的完整路径。此变量等效于 %homedrive%%homepath%
环境变量。
$Host
包含一个对象,该对象表示 Windows PowerShell 的当前主机应用程序。可以使用此变量在命
令中表示当前主机,或者显示或更改主机的属性,如 $Host.version
、$Host.CurrentCulture
$Input
一个枚举数,它包含传递给函数的输入。$Input
变量区分大小写,只能用于函数和脚本块。(脚本块本质上是未命名的函数。)在函数的 Process 块中,$Input
变量包含当前位于管道中的对象。在 Process 块完成后,$Input
的值为 NULL
。如果函数没有 Process 块,则 $Input
的值可用于 End
块,它包含函数的所有输入。
$LastExitCode
包含运行的最后一个基于 Windows 的程序的退出代码。
$Matches
与 -match
和 -not match
运算符一起使用。将标量输入提交给 -match
或 -notmatch
运算符时,如果检测到匹配,则会返回一个布尔值,并使用由所有匹配字符串值组成的哈希表填充 $Matches
自动变量。
$MyInvocation
包含一个对象,该对象具有有关当前命令(如脚本、函数或脚本块)的信息 。可以使用该对象中的信息(如脚本的路径和文件名 ($myinvocation.mycommand.path
) 或函数的名称
($myinvocation.mycommand.name
))来标识当前命令。对于查找正在运行的脚本的名称,这非常有用。
$PID
包含承载当前 Windows PowerShell 会话的进程的进程标识符 (PID)。
$Profile
包含当前用户和当前主机应用程序的 Windows PowerShell 配置文件的完整路径。可以在命令中使用此变量表示配置文件。例如,可以在命令中使用此变量确定是否已创建某个配置文件:
也可以在命令中使用此变量创建配置文件:
new-item -type file -path $pshome -force
此外,还可以在命令中使用此变量在记事本中打开配置文件:
$PSBoundParameters
包含活动参数及其当前值的字典。只有在声明参数的作用域(如脚本或函数)中,此变量才有值。可以使用此变量显示或更改参数的当前值,也可以将参数值传递给其他脚本或函数。
$PsCmdlet
包含一个对象,该对象表示正在运行的 cmdlet 或高级函数。
$PsCulture
包含操作系统中当前所用的区域性的名称。区域性确定数字、货币和日期等项的显示格式。这是系统的 System.Globalization.CultureInfo.CurrentCulture.Name 属性的值。要获取系统
的 System.Globalization.CultureInfo 对象,请使用 Get-Culture cmdlet。
$PSDebugContext
在调试期间,此变量包含有关调试环境的信息。在其他时间,此变量包含 NULL 值。
$PsHome
包含 Windows PowerShell 的安装目录的完整路径
$PSScriptRoot
包含要从中执行脚本模块的目录。通过此变量,脚本可以使用模块路径来访问其他资源。
$Pwd
包含一个路径对象,该对象表示当前目录的完整路径。
$ShellID
包含当前 shell 的标识符。
$SourceArgs
包含表示正在被处理的事件的事件参数的对象。此变量只在事件注册命令的 Action
块内填充。此变量的值也可在 Get-Event 返回的 PSEventArgs (System.Management.Automation.PSEventArgs) 对象的 SourceArgs 属性中找到。
$SourceEventArgs
包含一个对象,该对象表示从正在被处理的事件的 EventArgs 中派生出的第一个事件参数。此变量只在事件注册命令的 Action 块内填充。
$This
在定义脚本属性或脚本方法的脚本块中,This 变量引用要扩展的对象。
$True
包含 TRUE。可以在命令和脚本中使用此变量表示 TRUE。
环境变量
PowerShell 可以直接操作环境变量。$env:
中的环境变量只是机器环境变量的一个副本,即使你更改了它,下一次重新打开时,又会恢复如初。(.NET方法更新环境变量除外)。
我们可以将受信任的文件夹列表追加到环境变量的末尾,这样就可以直接通过相对路径执行这些文件下的文件或者脚本,甚至省略扩展名都可以。
读取特殊的环境变量
通过环境变量读取Windows操作系统的安装路径,和默认应用程序的安装路径。
PS > $env:windir
C:\Windows
PS > $env:ProgramFiles
C:\Program Files
插入到文本:
PS > "My computer name $env:COMPUTERNAME "
My computer name MYHome-test-01
查找环境变量
Powershell把所有环境变量的记录保存在 env:
虚拟驱动中,因此可以列出所有环境变量。一旦查出环境变量的名字就可以使用 $env:name
访问了。
PS > ls env:
Name Value
---- -----
ALLUSERSPROFILE C:\ProgramData
APPDATA C:\User\sv-test \Home\AppData\Roaming
CommonProgramFiles C:\Program Files\Common Files
创建新的环境变量
创建新环境变量的方法和创建其它变量一样,只需要指定env:
虚拟驱动器即可
$env:TestVar1 ="This is my environment variable"
$env:TestVar2 ="Hollow, environment variable"
del env:TestVar2
$env:OS ="Redhat Linux"
环境变量更新生效
.NET方法 [environment]::SetEnvironmentvariable
操作可以立刻生效。
下面的例子对当前用户设置环境变量,经测试,重新打开powershell仍然存在。
PS > [environment ]::SetEnvironmentvariable("Path" , ";c:\powershellscript" , "User" )
PS > [environment ]::GetEnvironmentvariable("Path" , "User" )
;c:\powershellscript
4. 管道、重定向
管道
把上一条命令的输出作为下一条命令的输入。
例如通过ls获取当前目录的所有文件信息,然后通过 Sort -Descending
对文件信息按照Name降序排列,最后将排序好的文件的Name和Mode格式化成Table输出。
PS C:\PStest> ls | sort -Descending Name | Format-Table Name,Mode
Name Mode
---- ----
d.txt -a---
c.txt -a---
b.txt -a---
ABC d----
a.txt -a---
输出结果
参考:格式化管道结果
吸收输出结果
有的命令无论执行成功或失败都会有输出,有时不需要这些输出时可以使用 | Out-Null
,这条命令的作用和 >$null
一样。
md ABD >$null
md ABE | Out-Null
导出 csv
Get-Service | Export-Csv a.csv
导出 html
Get-Service | ConvertTo-Html -Title "ls result" | Out-File a.html
导出 json
Get-Service | ConvertTo-Json | Out-File a.json
重定向
把命令的输出保存到文件中,>
为覆盖,>>
追加。
PS C:\PStest> "Powershell Routing" >test.txt
PS C:\PStest> Get-Content .\test.txt
Powershell Routing
PS C:\PStest> "Powershell Routing" >>test.txt
PS C:\PStest> "Powershell Routing" >>test.txt
PS C:\PStest> "Powershell Routing" >>test.txt
PS C:\PStest> "Powershell Routing" >>test.txt
PS C:\PStest> "Powershell Routing" >>test.txt
PS C:PStest\> Get-Content .\test.txt
Powershell Routing
Powershell Routing
Powershell Routing
Powershell Routing
Powershell Routing
Powershell Routing
PS C:\PStest>
5. 外部命令
Powershell 能够像CMD一样很好的执行外部命令。
启动CMD控制台
启动CMD控制台键入cmd或者cmd.exe,退出cmd可以通过命令 exit
。
PS C:\PS> cmd
Microsoft Windows [Version 6.1 .7601 ]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\PS>exit
PS C:\PS>
查找可用的Cmd控制台命令
Cmd.exe 通过 /c
来接收命令参数,在Cmd中help可以查看可用的命令,所以可以通过 Cmd /c help
查找可用的Cmd控制台命令
PS C:\PS> "ls"
ls
PS C:\PS> &"ls"
Directory: C:\PS
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2011 /11 /23 17 :25 ABC
-a--- 2011 /11 /23 17 :36 14 a.txt
-a--- 2011 /11 /23 17 :25 0 b.txt
PS C:\PS> "cmd.exe"
cmd.exe
PS C:\PS> &"cmd.exe"
Microsoft Windows [Version 6.1 .7601 ]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
powershell "& 'C:\xxx\xxx.ps1'"
6. 别名
查看可用的别名
可以通过 ls alias:
或者 Get-Alias
ls alias:
dir alias: | where {$_ .Definition.Startswith("Remove" )}
Set-Alias -Name Edit -Value notepad
Edit
Export-Alias alias.ps1
Import-Alias -Force alias.ps1
7. 条件判断
运算符
运算符
描述
-eq
等于
-ne
不等于
-gt
大于
-ge
大于等于
-lt
小于
-le
小于等于
-contains
包含
-notcontains
不包含
-not
求反, 布尔 逆
-and
和
-or
或
-xor
异或
-like
字符串包含, 支持通配符 ( ?, *)
可以将比较表达式直接输入进Powershell控制台,然后回车,会自动比较并把比较结果返回。
PS C:Powershell> (3 ,4 ,5 ) -contains 2
False
PS C:Powershell> (3 ,4 ,5 ) -contains 5
True
PS C:Powershell> (3 ,4 ,5 ) -notcontains 6
True
PS C:Powershell> 2 -eq 10
False
PS C:Powershell> "A" -eq "a"
True
PS C:Powershell> "A" -ieq "a"
True
PS C:Powershell> "A" -ceq "a"
False
PS C:Powershell> 1 gb -lt 1 gb+1
True
PS C:Powershell> 1 gb -lt 1 gb-1
False
比较数组和集合
1 ,2 ,3 ,4 ,3 ,2 ,1 -eq 3
1 ,2 ,3 ,4 ,3 ,2 ,1 -ne 3
1 ,9 ,4 ,5 -contains 9
1 ,9 ,4 ,5 -contains 10
1 ,9 ,4 ,5 -notcontains 10
Where-Object 条件过滤
Get-Process | select -First 1 | fl *
Get-Process | Where-Object {$_ .Name -eq "notepad" }
Get-Process | Where-Object {$_ .Name -eq "iexplore" }
Get-Process | Where-Object {$_ .company -like '*Microsoft*' } | select Name,Description,Company
Get-Service | ? {$_ .Name -like "B*" }
IF-ELSEIF-ELSE 条件
语句模板:
If (条件满足){
如果条件满足就执行代码
}
Else
{
如果条件不满足
}
示例:
if ($n -gt 15 ) {"$n 大于 15 " }
if ($n -gt 5 ) {"$n 大于 5 " }
if ($n -lt 0 ){"-1" } elseif ($n -eq 0 ){"0" } else {"1" }
Switch 条件
基本语法
switch ($value ) {
1 {"Beijing" }
2 {"Shanghai" }
3 {"Tianjin" }
4 {"Chongqing" }
{$_ -gt 10 } {"大于10" }
Default {"没有匹配条件" }
}
测试取值范围
使用 Switch 时缺省的比较运算符为 -eq
。 等于,你也可以自己定制比较条件,将条件放在花括号中,必须保证条件表达式的返回值为布尔类型 $True
或 $False
。
$value =18
switch ($value )
{
{$_ -lt 10 } {"小于10" }
10 {"等于10" }
{$_ -gt 10 } {"大于10" }
}
多个条件匹配
$value =2
switch ($value )
{
{$_ -lt 5 } { "小于5" }
{$_ -gt 0 } { "大于0" }
{$_ -lt 100 }{ "小于100" }
Default {"没有匹配条件" }
}
Break 关键字
如果碰到匹配条件时只处理一次,可以使用 Break
关键字
$value =99
switch ($value )
{
{$_ -lt 5 } { "小于5" ; break }
{$_ -gt 0 } { "大于0" ; break }
{$_ -lt 100 } { "小于100" ; break }
Default {"没有匹配条件" }
}
比较字符串
$domain ="www.mossfly.com"
switch ($domain )
{
"Www.moSSfly.com" {"Ok 1" }
"www.MOSSFLY.com" {"Ok 2" }
"WWW.mossfly.COM" {"Ok 3" }
}
Ok 1
Ok 2
Ok 3
大小写敏感
Switch有一个 -case
选项,一旦指定了这个选项,比较运算符就会从 -eq
切换到 -ceq
,即大小写敏感比较字符串。
$domain ="www.mossfly.com"
switch -case ($domain )
{
"Www.moSSfly.com" {"Ok 1" }
"www.MOSSFLY.com" {"Ok 2" }
"www.mossfly.com" {"Ok 3" }
}
使用通配符
在Switch语句后要指定 -wildcard
选项
$domain ="www.mossfly.com"
switch -wildcard ($domain )
{
"*" {"匹配'*'" }
"*.com" {"匹配*.com" }
"*.*.*" {"匹配*.*.*" }
}
匹配'*'
匹配*.com
匹配*.*.*
正则表达式
给Switch关键字指定选项-regex
选项
$mail ="www@mossfly.com"
switch -regex ($mail )
{
"^www" {"www打头" }
"com$ " {"com结尾" }
"d{1,3}.d{1,3}.d{1,3}.d{1,3}" {"IP地址" }
}
同时处理多个值
Switch支持对集合所有元素进行匹配,下面的例子使用Powershell Switch语句演示打印水仙花数:
$value =100 ..999
switch ($value )
{
{[Math ]::Pow($_ %10 ,3 )+[Math ]::Pow( [Math ]::Truncate($_ %100 /10 ) ,3 )+[Math ]::Pow( [Math ]::Truncate($_ /100 ) , 3 ) -eq $_ } {$_ }
}
8. 循环
ForEach-Object 循环
Powershell管道就像流水线,对于数据的处理是一个环节接着一个环节,如果你想在某一环节对流进来的数据逐个细致化的处理,可是使用 ForEach-Object,$_
代表当前的数据 (当然也允许通过 $_.
调用该对象支持的方法)。
Get-WmiObject Win32_Service | ForEach-Object {
if ($_ .ProcessId -gt 3000 )
{ "{0}({1})" -f $_ .DisplayName,$_ .ProcessID}
}
Get-Process iexplore | ForEach-Object {$_ .kill()}
ForEach 循环
foreach为遍历集合、数组或对象的关键字。
$array =7 ..10
foreach ($n in $array )
{
$n *$n
}
foreach ($file in dir c:\windows)
{
if ($file .Length -gt 1 mb)
{
$File .Name
}
}
For 循环
$sum =0
for ($i =1 ;$i -le 100 ;$i ++)
{
$sum +=$i
}
$sum
$sum =0
$i =1
for (;$i -le 100 ;)
{
$sum +=$i
$i ++
}
$sum
For循环的特殊应用: 判断域名
for ($domain ="" ;!($domain -like "www.*.*" );$domain =Read-Host "Input domain" )
{
Write-Host -ForegroundColor "Green" "Please give a valid domain name."
}
Please give a valid domain name.
Input domain: www
Please give a valid domain name.
Input domain: mossfly.com
Please give a valid domain name.
逐行读取文本文件
for ($file =[IO.File ]::OpenText("c:autoexec.bat" ) ; !($file .EndOfStream);$line =$file .ReadLine() )
{
$line ;
}
$file .Close()
REM Dummy file for NTVDM
Do While 循环
Do和While可能产生死循环,为了防止死循环的发生,你必须确切的指定循环终止的条件。指定了循环终止的条件后,一旦条件不满足就会退出循环。
do { $n =Read-Host } while ( $n -ne 0 )
$n =5
while ($n -gt 0 )
{
$n
$n =$n -1
}
Switch 循环
在Powershell中由于Switch支持集合,所以也可以使用它进行循环处理。有时对集合的处理,在循环中还须条件判断,使用Switch循环可以一部到位。
$nums = 10 ..7
Switch ($nums )
{
Default { "n= $_ " }
}
$nums = 10 ..7
Switch ($nums )
{
{($_ % 2 ) -eq 0 } {"$_ 偶数" }
{($_ % 2 ) -ne 0 } {"$_ 奇数" }
}
终止当前循环
使用continue
关键字,可是终止当前循环,跳过continue
后其它语句,重新下一次循环。
$n =1
while ($n -lt 6 )
{
if ($n -eq 4 )
{
$n =$n +1
continue
}
else
{
$n
}
$n =$n +1
}
跳出循环语句
跳出循环语句使用break
关键字。
$n =1
while ($n -lt 6 )
{
if ($n -eq 4 )
{
break
}
$n
$n ++
}
9. 函数和脚本
函数语法
Function FuncName (args [])
{
code;
}
Function cd .. { cd ..}
cd ..
Function Ping2 { PING.EXE -n 1 $args }
Ping2 www.mossfly.com
更新函数
$function:MyPing | Out-File myPing.ps1
$function:MyPing { PING.EXE -n 1 $args }
删除函数
参数
函数的参数有3个特性:
任意参数:内部变量 $args
接受函数调用时接受的参数,`$args 是一个数组类型。
命名参数:函数的每一个参数可以分配一个名称,在调用时通过名称指定对应的参数。
预定义参数:函数在定义参数时可以指定默认值,如果调用时没有专门指定参数的值,就会保持默认值。
function sayHello
{
if ($args .Count -eq 0 )
{
"No argument!"
}
else
{
$args | foreach {"Hello,$ ($_ )" }
}
}
sayHello
sayHello LiLi
sayHello LiLi Lucy Tom
function StringContact ($str1 ,$str2 )
{
return $str1 +$str2
}
StringContact moss fly
StringContact -str1 word -str2 press
function stringContact ($str1 ="moss",$str2 ="fly")
{
return $str1 +$str2
}
stringContact Good Luck
function subtract ([int]$value1 ,[int]$value2 )
{
return $value1 -$value2
}
function subtract ([double]$value1 ,[double]$value2 )
{
return $value1 -$value2
}
subtract 8.1 7.9
function DayOfWeek ([datetime]$date )
{
return $date .DayOfWeek
}
Switch 参数
Powershell函数最简单的参数类型为布尔类型,除了使用Bool类型,也可以使用Switch关键字。
下面的函数逆转字符串,但是可以通过$try
参数进行控制,如果没有指定$try
的值,默认值为$false
function tryReverse ( [switch]$try , [string]$source )
{
[string ]$target =""
if ($try )
{
for ( [int ]$i = $source .length -1 ; $i -ge 0 ;$i -- )
{
$target += $source [$i ]
}
return $target
}
return $source
}
tryReverse -source www.mossfly.com
tryReverse -try $true -source www.mossfly.com
返回值
如果一个函数返回一个值,像其它编程语言一样,这个值包括她的类型信息会直接返回。但是如果遇到多个返回值,Powershell会将所有的返回值自动构造成一个Object数组。可以通过索引访问数组。
function Square ([double]$num )
{
return $num *$num
}
Square 9.87
$value =Square 9.87
function gbMeasure ($amount )
{
"$amount GB=$ ($amount ) GB"
"$amount GB=$ ($amount *1gb/1mb) MB"
"$amount GB=$ ($amount *1gb/1kb) KB"
"$amount GB=$ ($amount *1gb) B"
}
gbMeasure 1
$result =gbMeasure 1
$result [3 ]
Return语句
Powershell会将函数中所有的输出作为返回值,但是也可以通过return语句指定具体的我返回值。
Return 语句会将指定的值返回,同时也会中断函数的执行,return后面的语句会被忽略。
function test ($num )
{
1
9
return 10
4
6
}
test
消除返回值
如果要过滤注释,只输出,不作为返回值,可以使用 Write-Host
命令。还可以使用 Write-Debug
命令,只在调试模式下输出。
Write-debug
的行为受 $DebugPreference
的影响,$DebugPreference
值默认为 SilentlyContinue
,此时 Write-debug
不会输出任何信息。
$DebugPreference
可选的配置如下:
SilentlyContinue
:调试关闭
Stop
: 输出调试信息,终止脚本执行
Continue
: 输出调试信息,继续执行脚本
Inquire
:输出调试信息,询问用户是否继续执行。
Function Test ()
{
Write-Host "Try to calculate."
"3.1415926"
Write-Host "Done."
}
$value =Test
$value
Function Test ()
{
Write-Debug "Try to calculate."
"3.1415926"
Write-Debug "Done."
}
$value =Test
$DebugPreference ="Continue"
$value =Test
$value
$DebugPreference ="SilentlyContinue"
$value =Test
使用 Write-Debug
有两个优势,首先调试信息会自动高亮显示 ,便于分析。其次,这些调试信息只会在调试模式开启时输出 ,控制起来更加方便。当然最重要的是这些临时信息无论什么时候也不会混淆在返回值。
抑制错误信息
Function ErrorTest ()
{
$ErrorActionPreference ="SilentlyContinue"
Stop-Process -Name "www.mossfly.com"
$ErrorActionPreference ="Continue"
}
ErrorTest
查看支持的函数
dir function: | ft -AutoSize
(dir function:).count
查看函数内部定义
如果你想深入查看函数的内部定义可以直接访问 Function (不带括号)。
常用预定义函数
- `Clear-Host` 清除屏幕的缓存
- `help` , `man` 查看命令的帮助文档
- `mkdir` , `md` 通过new-Item创建子目录
- `more` 分屏输出管道结果
- `prompt` 返回提示文本
- `TabExpansion` Tab键的自动完成提示
- `X` : 调用Set-Location定位到指定的驱动器根目录
自定义Prompt
在控制台的任何位置输出文本(自定义光标的位置),因为控制台的内容存放在控制台屏幕的缓存中,因此你可以逐个访问内容的每一行或每一个字符。你甚至可以在控制台的屏幕的任何位置输出你想要输出的信息,接下来的函数会演示这个功能。要完成这个功能,需要使用$Host.UI.Rawui
, 光标的位置通过屏幕的横坐标(X)和纵坐标(Y)确定,下面的函数会首先记住当前光标的位置,然后在横坐标上增加60个占位符,然后重置光标的位置至当前位置,最后通过prompt函数回复光标的原始位置。
function prompt
{
$curPos = $host .ui.rawui.CursorPosition
$newPos = $curPos
$newPos .X+=60
$host .ui.rawui.CursorPosition = $newPos
Write-Host ("{0:D} {0:T}" -f (Get-Date )) -foregroundcolor Yellow
$host .ui.rawui.CursorPosition = $curPos
Write-Host ("PS " + $ (get-location ) +">" ) -nonewline -foregroundcolor Green
" "
}
PS E:mossfly.com> function prompt
>> {
>> $curPos = $host .ui.rawui.CursorPosition
>> $newPos = $curPos
>> $newPos .X+=60
>> $host .ui.rawui.CursorPosition = $newPos
>> Write-Host ("{0:D} {0:T}" -f (Get-Date )) -foregroundcolor Yellow
>> $host .ui.rawui.CursorPosition = $curPos
>> Write-Host ("PS " + $ (get-location ) +">" ) -nonewline -foregroundcolor Gre
en
>> " "
>> }
>>
PS E:mossfly.com> 2012 年2 月28 日 8 :54 :01
使用窗口标题栏
控制台的标题栏有一部分空间,可以放置一些有用的信息,比如当前哪个用户登录在控制台,可以通过设置$host.UI.RawUI.WindowTitle
来自定义控制台标题栏的文本。
管道函数
Function MarkEXE
{
begin
{
$oldcolor = $host .ui.rawui.ForegroundColor
}
process
{
If ($_ .name.toLower().endsWith(".exe" ))
{
$host .ui.Rawui.ForegroundColor = "red"
}
Else
{
$host .ui.Rawui.ForegroundColor = $oldcolor
}
$_
}
end
{
$host .ui.Rawui.ForegroundColor = $oldcolor
}
}
Dir c: -recurse | MarkEXE
脚本传参
传递给一个函数或者一个脚本的参数都保存在$args
变量中。
For ($i =0 ;$i -lt $args .Count; $i ++)
{
Write-Host "parameter $i : $ ($args [$i ])"
}
.MyScript.ps1 www moss fly com
parameter 0 : www
parameter 1 : moss
parameter 2 : fly
parameter 3 : com
在脚本中使用参数名
输入以下的脚本 (其中param给参数指定名称。):
param ($Directory ,$FileName )
"Directory= $Directory "
"FileName=$FileName "
执行脚本:
PS E:> .MyScript.ps1 -Directory $env:windir -FileName config.xml
Directory= C:windows
FileName=config.xml
PS E:> .MyScript.ps1 -FileName config.xml -Directory $env:windir
Directory= C:windows
FileName=config.xml
验证参数
param (
[string ]$Name =$ (throw "Parameter missing: -name Name" ) ,
[int ]$Age =$ (throw "Parameter missing: -age x as number" )
)
"Name= $Name "
"Age=$Age "
管道脚本
如果你在脚本中使用管道,脚本收集上一个语句的执行结果,默认保存在$input
自动变量中。但是直到上一条语句完全执行彻底,管道脚本才会执行。
低速顺序模式
foreach ($element in $input )
{
if ($element .Extension -eq ".exe" )
{
Write-Host -fore "red" $element .Name
}
else
{
Write-Host -fore "Green" $element .Name
}
}
ls $env:windir | .pipeline.ps1
ls $env:windir -Recurse | .pipeline.ps1
高速流模式
begin
{
Write-Host "管道脚本环境初始化"
}
process
{
$ele =$_
if ($_ .Extension -ne "" )
{
switch ($_ .Extension.tolower())
{
".ps1" {"脚本文件:" + $ele .name}
".txt" {"文本文件:" + $ele .Name}
".gz" {"压缩文件:" + $ele .Name}
}
}
}
end
{
Write-Host "管道脚本环境恢复"
}
ls | .pipeline2.ps1
管道脚本环境初始化
文本文件:a.txt
压缩文件:Metrol.tar.gz
脚本文件:MyScript.ps1
脚本文件:pipeline.ps1
脚本文件:PSLib.ps1
管道脚本环境恢复
自动执行脚本之profile
profile用来保存一些基本的初始化工作。有四种不同的profile:
所有用户 $pshome\profile.ps1
所有用户(私有) $pshome\Microsoft.PowerShell_profile.ps1
当前用户 $((Split-Path $profile -Parent)+ “\profile.ps1”)
当前用户(私有) $profile
notepad $ ((Split-Path $profile -Parent ) + “profile.ps1”)
Set-Alias edit notepad.exe
edit $ ((Split-Path $profile -Parent ) + “profile.ps1”)
10. 错误处理
试运行 :模拟操作
如果你想知道一个确定的命令会产生什么影响,你可以进行试运行。这时,Powershell不会执行任何对系统有影响的操作,只会告诉你如果没有模拟运行,可能产生什么影响和后果。通过 -whatif
参数。事实上,许多cmdltes都支持试运行。
让自己的脚本和函数也支持模拟运行,只需要进行简单的整合。多增加一个switch参数。
function MapDrive ([string]$driveletter , [string]$target , [switch]$whatif )
{
If ($whatif )
{
Write-Host "WhatIf: creation of a network drive " + "with the letter $ {driveletter}: at destination $target "
}
Else
{
New-PSDrive $driveletter FileSystem $target
}
}
MapDrive k 127.0 .0.1 c$ -whatif
WhatIf: creation of a network drive
with letter k: at destination 127.0 .0.1 c$
MapDrive k 127.0 .0.1 c$
Name Provider Root
---- -------- ----
k FileSystem 127.0 .0.1 c$
识别和处理异常
$ ?中的错误状态
$ ?变量会保存上一步操作是否成功或者失败,也就是告诉你是否发生了错误。可以写一段脚本进行测试。
Remove-Item "文件不存在" -ErrorAction "SilentlyContinue"
If (!$ ?)
{
"删除文件操作失败" ;
break
};
"删除文件成功!"
使用Traps
使用Traps可以捕获异常,在捕获到异常时,可以在做相应的处理。例如我们在Powershell自动化工作中,出现了异常可以发一封邮件给管理员。
Trap { "自动化工作发生异常,正在发邮件联系管理员给管理员!" }
1 /$null
自动化工作发生异常,正在发邮件联系管理员给管理员!
尝试除以零。
所在位置 D:\Documents\Desktop\IIS\power-shell-demo \demo.3 .ps1:2 字符: 1
+ 1 /$null
+ ~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Trap [System.DivideByZeroException ] {
"除数为空!" ;
Continue
}
Trap [System.Management.Automation.ParameterBindingException ] {
"参数不正确!" ;
Continue
}
Trap [System.Net.WebException ]{
"网络异常!"
Continue
}
1 /$null
Dir -MacGuffin
$wc = new-object System.Net.WebClient
$wc .DownloadFile("http://www.mossfly.com/powershell.txt" ,"e:ps.txt" )
Traps异常发生时使用break中断脚本执行
Trap { "异常发生,我想终止脚本!" }
stop-service -name "NoSuchService" -ErrorAction "Stop"
Traps异常发生时,使用Continue 继续执行
Trap { "异常发生,我要继续执行!" }
stop-service -name "NoSuchService" -ErrorAction "Continue"
Write-Host "继续执行"
查看异常的详细信息
Trap 到异常后,Powershell会自动将该异常保存在 $_
变量中。
Trap
{
Write-Host $_ .Exception.Message;
Continue
};
Stop-Process -Name "NoSuchProcess"
错误记录:详细错误
dir "NoSuchDirectory" 2 > Error.txt
Get-Content Error.txt
抛出自定义异常信息
Function Func-Test ($a ,$b )
{
if ($b -eq $null )
{
throw "参数b 不能为空!"
}
"{0}+{1}={2}" -f $a ,$b ,($a +$b )
}
Func-Test -a 10
Function Func-Test ($a ,$b =$ (throw "参数B 不能为空!") )
{
"{0}+{1}={2}" -f $a ,$b ,($a +$b )
}
Func-Test -a 10 -b 9
Func-Test -a 10
函数中捕获异常
Function Test-Func
{
Trap { "Trap 到异常了." }
1 /$null
Get-Process "NoSuchProcess"
Dir MossFly:
}
Test-Func
Function Test-Func
{
Trap {
"Trap到了异常: $ ($_ .Exception.Message)" ;
Break
}
1 /$null
Get-Process "NoSuchProcess" -ErrorAction Stop
Dir MossFly: -ErrorAction Stop
}
Test-Func
function Caller
{
Trap
{
"Trap Error: $ ($_ .Exception.Message)" ;
Continue
}
Test-Func
}
function Test-Func
{
1 /$null
Get-Process "nosuchthing" -ea Stop
Dir xyz: -ea Stop
}
Caller
function test-func
{
Trap {"Trap Error: $ ($_ .Exception.Message)" ; Continue }
&{
1 /$null
Get-Process "nosuchthing" -ea Stop
Dir xyz: -ea Stop
}
}
test-func
断点执行
$DebugPreference ="inquire"
Write-Debug "输入一行调试信息" ;
Write-Host "伦敦奥运会女子体操决赛"
还可以通过 Set-PSDebug -step
进行单步跟踪,Powershell会每只行一段代码,就会向用户询问是否继续执行。
设置进度条的显示模式
《官方文档》
Write-Progress
[-Activity] <String >
[[-Status] <String >]
[[-Id] <Int32>]
[-PercentComplete <Int32>]
[-SecondsRemaining <Int32>]
[-CurrentOperation <String >]
[-ParentId <Int32>]
[-Completed]
[-SourceId <Int32>]
[<CommonParameters>]
显示 For 循环的进度
for ($i = 1 ; $i -le 100 ; $i ++ )
{
Write-Progress -Activity "Search in Progress" -Status "$i % Complete:" -PercentComplete $i
Start-Sleep -Milliseconds 250
}
显示嵌套 For 循环的进度
此示例显示两个嵌套 For 循环的进度,每个循环由一个进度条表示。
Write-Progress
第二个进度条的命令包含将其与第一个进度条区分开来的Id参数。
如果没有Id参数,进度条将相互叠加,而不是一个在另一个下方显示。
for ($I = 1 ; $I -lt 101 ; $I ++ )
{
Write-Progress -Activity Updating -Status 'Progress->' -PercentComplete $I -CurrentOperation OuterLoop
for ($j = 1 ; $j -lt 101 ; $j ++ )
{
Write-Progress -Id 1 -Activity Updating -Status 'Progress' -PercentComplete $j -CurrentOperation InnerLoop
}
}
显示嵌套流程的每个级别的进度
您可以使用ParentId参数来缩进输出以显示每个步骤的进度中的父/子关系。
foreach ( $i in 1 ..10 ) {
Write-Progress -Id 0 "Step $i "
foreach ( $j in 1 ..10 ) {
Write-Progress -Id 1 -ParentId 0 "Step $i - Substep $j "
foreach ( $k in 1 ..10 ) {
Write-Progress -Id 2 -ParentId 1 "Step $i - Substep $j - iteration $k " ; start-sleep -m 150
}
}
}
Step 1
Processing
Step 1 - Substep 2
Processing
Step 1 - Substep 2 - Iteration 3
Processing
11. 命令发现和脚本块
发现命令
使用 Get-Command
命令可以查看当前作用域支持的所有命令。如果你想查看关于 LS 命令的信息,请把它传递给Get-Command。
PS C:> Get-command LS
CommandType Name Definition
----------- ---- ----------
Alias ls Get-ChildItem
查看更详细的信息
事实上,Get-Command
返回的是一个对象CommandInfo,ApplicationInfo,FunctionInfo,或者CmdletInfo;
如果一条命令可能指向两个实体,get-command也会返回,例如more。
PS C:> Get-Command more
CommandType Name Definition
----------- ---- ----------
Function more param ([string[]]$paths ) ...
Application more.com C:windowsSYSTEM32more.com
一个命令指向多个实体时,Powershell 中有一个机制,就是函数永远处在最高的优先级。
function ipconfig () {
return "我是自定义函数的 ipconfig"
}
ipconfig
del Function:ipconfig
ipconfig
调用操作符 "&"
如果你之前将Powershell命令存储在了一个字符串中,或者一个变量中。此时,调用操作符 &
就可以将字符串直接解释成命令并执行,如果在Powershell控制台中,你只须要输入即可。
调用操作符只能接受单个命令
调用操作符不能接受全部的Powershell脚本或命令,只能接受单个的一条命令。
直接执行一个CommandInfo对象
$command =Get-Command tasklist
& $command
优先级
可能存在别名,命令,函数的的名称一样,那Powershell会不会纠结到底执行哪个呢?当然不会,因为它们之间是有一个优先级的。从高到底,依次为:
Alias(1)
Function(2)
Filter(2)
Cmdlet(3)
Application(4)
ExternalScript(5)
Script (...)
怎样突破优先级的限制执行指定的命令呢?方法都是大同小异,通过特定信息过滤到指定的CommandInfo对象,然后直接使用我们本篇的调用操作符。
$command =Get-Command -Name ping | where {$_ .CommandType -eq "Application" }
& $command
语句块
脚本块是一种特殊的命令模式。一个脚本块可以包含许多的 Powershell命令和语句。它通常使用大括号定义。最小最短的脚本块,可能就是一对大括号,中间什么也没有。可以使用之前的调用操作符 &
执行脚本块:
PS E:> & {"当前时间:" + (get-date ) }
当前时间:08 /08 /2012 22 :30 :24
将命令行作为整体执行
PS E:> & {$files =ls ;Write-Host "文件数:" $files .Count }
文件数: 29
执行表达式 Invoke-Expression
Invoke-Expression
,这条命令的逻辑就是将一条字符串传递给调用操作符。
需要注意,在传递给 invoke-expression
的字符串使用了单引号,单引号可以防止变量被替换。如果上面的命令使用了双引号,会先去解释 $_.name
,但是当前作用域中,$_.Name
为 null
,所以结果不是期望的。
PS E:> Invoke-Expression 'Get-Process | Where-Object { $_.Name -like "e*"}'
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
332 29 12280 24264 154 1.40 3236 egui
386 32 78624 85508 183 1884 ekrn
284 22 8980 17048 99 1920 EvtEng
1000 89 55520 83280 355 23.24 2848 explorer
管道中的foreach-object语句块
管道中的foreach-object本身后面也会带语句块,针对数组中的每一个元素分别传递给语句块处理。
Get-Process | ForEach-Object { $_ .name }
函数本身是一个已命名的语句块
Function SayHello ([string]$people ="everyone")
{
write-host "Hello, $people ”
}
#通过函数调用
SayHello " Mosser"
Hello, Mosser
#通过语句块调用
$func =function:SayHello
$scriptblocks
param([string]$people =" everyone")
write-host " Hello, $people ”
& $scriptblocks
Hello, everyone
传递参数给语句块
定义和传递参数一次性完成,有点匿名函数的味道。
& { param ($people ="everyone" ) write-host "Hello, $people ” } " Mosser"
Hello, Mosser
Begin, Process, End 管道语句块
get-process | select -last 5 | & {
begin {
"开始准备环境"
}
process
{
$_ .Name
}
end {
"开始清理环境"
}
}
开始准备环境
wlcommsvc
WLIDSVC
WLIDSVCM
WmiPrvSE
XDict
开始清理环境
验证变量
& { $value1 = 10 ; $global:value2 = 20 }
$value1
$value2
执行上下文
Powershell 提供了一个非常特别的自动化变量,$ExecutionContext
。这个对象主要包含两个属性:InvokeCommand 和 SessionState.
InvokeCommand 处理变量
在Powershell控制台中遇到三个比较特殊的字符:
| 特殊字符 | 定义 | 内部方法 |
| --- | --- | --- |
| `"` | 处理字符串中的变量 | ExpandString() |
| `&` | 执行命令集 | InvokeScript() |
| `{}` | 创建一个新的代码块 | NewScriptBlock() |
$site = '大白博客'
$text = "我的个人网站 $site "
$text
$site = '大白博客'
$text = '我的个人网站 $site'
$executioncontext .InvokeCommand.ExpandString($text )
脚本块和命令
$blockStr ='$write=Get-Process WindowsLiveWriter "$($write.Name) 占用内存: $($write.WorkingSet/1mb) MB"'
$block = $executioncontext .InvokeCommand.NewScriptBlock($blockStr )
& $block
$cmd ='3*3*3.14'
$executioncontext .InvokeCommand.InvokeScript($cmd )
Invoke-Expression $cmd
SessionState 环境对象
SessionState是一个用来表现Powershell环境的对象, 同样可以通过自动化变量 $ExecutionContext
访问这些信息。
$executioncontext .SessionState | Format-List *
PSVariable
PSVariable
, 可以取出和更新Powershell中所有的变量.
$value = "Test"
$executioncontext .SessionState.PSVariable.GetValue("value" )
Test
$executioncontext .SessionState.PSVariable.Set("value" , 100 )
$value
100
管理驱动器
$executioncontext .SessionState.Drive.Current
$executioncontext .SessionState.Drive.GetAll() | ft -
$executioncontext .SessionState.Drive.GetAllForProvider("FileSystem" )
路径操作
SessionState的Path包含几个特殊的方法,基本可以覆盖各种常用的路径操作了。
CurrentLocation() 当前路径。 对应的命令 Get-Location
PopLocation() 获取存储的路径。 对应的命令 Pop-Location
PushCurrentLocation() 存储路径。对应的命令 Push-Location
SetLocation() 定位路径。对应的命令 Set-Location
GetResolvedPSPathFromPSPath() 相对路径转换成绝对路径。对应的命令 Resolve-Location
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?