[TOC]
0x00 PS 对象类(Object-Class) 描述:我们在学习C++和Java/PHP都遇到过面向对象编程,同样在PS也是基于对象来运行的脚本语言;
简单的说 对象=属性+方法
组成:
(1) 属性可以描述一个对象例如一把小刀拥有一些特殊的属性(颜色、制造商等)
,对象的属性可以被PS自动转换成文本,并且输出到控制;
只读属性:一个构造器中只有Get方法,没有Set方法
读写属性:一个构造器中只有Get/Set方法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 $Host | Get-Member -MemberType Property PS > $host .Version Major Minor Build Revision ----- ----- ----- -------- 2 0 -1 -1 PS > $host .Version.Major 5 PS > [System.Version]'2019.12.20.1234' Major Minor Build Revision ----- ----- ----- -------- 2019 12 20 1234 PS > $Host .CurrentCulture LCID Name DisplayName ---- ---- ----------- 2052 zh-CN 中文(中华人民共和国) PS > [System.Globalization.CultureInfo]'zh-tw' LCID Name DisplayName ---- ---- ----------- 1028 zh-TW 中文(繁体,中国台湾)
[TOC]
0x00 PS 对象类(Object-Class) 描述:我们在学习C++和Java/PHP都遇到过面向对象编程,同样在PS也是基于对象来运行的脚本语言;
简单的说 对象=属性+方法
组成:
(1) 属性可以描述一个对象例如一把小刀拥有一些特殊的属性(颜色、制造商等)
,对象的属性可以被PS自动转换成文本,并且输出到控制;
只读属性:一个构造器中只有Get方法,没有Set方法
读写属性:一个构造器中只有Get/Set方法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 $Host | Get-Member -MemberType Property PS > $host .Version Major Minor Build Revision ----- ----- ----- -------- 2 0 -1 -1 PS > $host .Version.Major 5 PS > [System.Version]'2019.12.20.1234' Major Minor Build Revision ----- ----- ----- -------- 2019 12 20 1234 PS > $Host .CurrentCulture LCID Name DisplayName ---- ---- ----------- 2052 zh-CN 中文(中华人民共和国) PS > [System.Globalization.CultureInfo]'zh-tw' LCID Name DisplayName ---- ---- ----------- 1028 zh-TW 中文(繁体,中国台湾)
(2) 方法定义了一个对象可以做什么事情例如打开计算机
,当你把一个对象输出在控制台时它的属性可能会被转换成可视的文本,但是它的方法却不可见
标准方法:几乎每个对象都有一些继承自父类的方法,这些方法并不是该对象所特有的方法,而是所有对象共有的方法。
Equals 比较两个对象是否相同
GetHashCode 返回一个对象的数字格式的指纹
GetType 返回一个对象的数据类型
ToString 将一个对象转换成可读的字符串1 2 3 4 5 6 7 8 9 10 11 12 13 PS > $Host | Get-Member -MemberType Method PS > $Host .get_Version() $Host .UI.WriteDebugLine("Hello 2012 !" ) [System.DateTime]::Parse("2012-10-13 23:42:55" )
Tips : Powershell将信息存储在对象中,每个对象都会有一个具体的类型;(例如简单的文本会以System.String类型存储,日期会以System.DateTime类型存储。)
Tips : 任何.NET对象都可以通过GetType()方法返回它的类型,该类型中有一个FullName属性,可以查看类型的完整名称(例如$date.GetType().FullName
)。
1.操作对象 描述: 通过New-Object可以创建一个对象,可以通过Add-member添加对象属性,通过下面示例也能学习到调用属性和方法,并且删除我们创建的对象。
基础实例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 PS > $obj = New-Object object PS > $obj PS > Add-Member -MemberType NoteProperty -InputObject $obj -Name Color -Value "Red" PS > Add-Member -MemberType NoteProperty -InputObject $obj -Name Name -Value "WeiyiGeek" PS > $obj PS > Add-member -MemberType ScriptMethod -InputObject $obj script {"I'm is function, $obj .name " } PS > Add-Member -memberType ScriptMethod -InputObject $obj -Name fun -Value { "I'm whittling now" } PS > $obj | Add-Member ScriptMethod corkscrew { "Pop! Cheers!" } PS > $obj | get-Member PS > $obj PS > $obj .Name PS > $obj .script() PS > $obj .fun() PS > $pocketknife .corkscrew() PS > $pocketknife .corkscrew PS > -Path $obj PS > $obj .Delete() PS > -Path $obj
2.对象属性 描述:一个对象的属性用来存储数据,反过来这些数据又可以存储其它对象。例如$host
有两个比较特别的属性UI和PrivateData
。
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 $Host PS C:Powershell> $Host .UI PS C:Powershell> $Host .UI.RawUI $host .ui.rawui.ForegroundColor = "White" PS C:Powershell> $Host .UI.RawUI.KeyAvailable PS C:Powershell> $Host .UI.RawUI.KeyAvailable=$false PS > $obj =New-Object PSobject PS > $obj | Add-Member -MemberType NoteProperty -Name AddTime -Value (get-date) PS > $obj | Add-Member -MemberType ScriptProperty -Name CurrentTime -Value {get-date} PS > $obj PS C:\Users\WeiyiGeek> $obj .AddTime PS C:\Users\WeiyiGeek> $obj .CurrentTime
3.对象方法 描述:每一个类型都可以包含一些静态的方法,可以通过方括号和类型名称
得到类型对象本身;
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $Host .GetType() [System.DateTime] | Get-Member -static -memberType *Method $method =$Host .UI | Get-Member WriteLine$method .Definition $method .Definition.Replace(")," ,")`n" )
Tips : 必须知道这个方法的功能,因为有的命令可能比较危险,例如错误地修改环境变量。
4.对象实例 描述: 可以采用类似于Java声明实例化对象类的流程来实现创建对象。
Q:为什么支持上面的方法?
答: 原因是String类中包含一个 Void .ctor(Char, Int32)
构造函数 查看命令: [String].GetConstructors() | foreach {$_.tostring()}
示例3.通过类型转换创建对象即(通过类型转换可以替代New-Object
)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 [DateTime]$date ="1999-9-1 10:23:44" $date .GetType().FullNameSystem.DateTime [char[]]"weiyigeek" [int[]][char[]]"weiyigeek"
示例3.使用.net对象类型进行实例创建1 2 3 4 5 6 7 8 9 10 11 12 13 $LocalName ="c:\PS\Index.php" $DownUrlFile ="https://weiyigeek.com/Index.php" if (!-Path $LocalName ){ $webClient =New-Object Net.WebClient;$webClient .DownloadFile($DownUrlFile ,$LocalName ) if (-Path $LocalName ){ Write-Ouput "下载完成" } } (New-Object Net.WebClient).DownloadFile($DownUrlFile ,$LocalName )
5.加载DLL程序集 描述: 在Powershell中加载这个自定义C#类库编译生成的dll,并使用其中的Student类的构造函数生成一个实例,最后调用ToString()方法。
6.使用COM对象 描述: 作为.NET对象的补充Powershell可以加载和访问COM对象。
Tips : 常用的COM对象中有:
WScript.Shell,
WScript.Network,
Scripting.FileSystemObject,
InternetExplorer.Application,
Word.Application,
Shell.Application
Step 1.每一个COM对象都有存储在注册表中的唯一标识符,想遍历访问可用的COM对象,可是直接访问注册表。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Get-ChildItem REGISTRY::HKEY_CLASSES_ROOT\CLSID -include PROGID -recurse | foreach {$_ .GetValue("" )} | select -First 10 Get-ChildItem REGISTRY::HKEY_CLASSES_ROOT\CLSID -include PROGID -recurse | foreach {$_ .GetValue("" )} | Select-String "WScript"
Step 2.怎样使用COM对象得到了COM对象的ProgID,就可以使用使用New-Object创建COM对象查看其
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 PS > $WS =New-Object -ComObject WScript.Network.1 PS > $WS | Get-Member -me *method PS C:\Users\WeiyiGeek> $WS .EnumNetworkDrives() PS C:\Users\WeiyiGeek> $WS .EnumPrinterConnections() PS > $WS | Get-Member -me *property PS C:\Users\WeiyiGeek> $WS .UserDomain PS C:\Users\WeiyiGeek> $WS .UserName
Step3.使用WScript.shell COM对象和它的方法CreateShortcut()
做桌面上创建一个Powershell快捷方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 PS> $shell =New-Object -ComObject WScript.shell PS> $link =$shell .CreateShortcut("$path /Powershell.lnk" ) PS> $link .Description="启动Powershell" PS> $link .TargetPath='Powershell.exe' PS> $link .IconLocation='Powershell.exe' PS> $link .WorkingDirectory=$PROFILE PS> $link .Save() PS> $link $link | get-memberTypeName:System.__ComObject TargetPath Property string TargetPath () {get} {set } $link .TargetPath()$link .TargetPath="cmd.exe"
Tips : COM对象的和.NET对象相似,所以可是使用Get-Member
得到该对象的所有熟悉和方法:
0x01 PS 脚本(Script) 描述: 做过开发的人都知道写得代码量越大其可读性就越差,解决的最好方式就是在写脚本时融入函数(Function)
和类库(Class)
的概念。
函数:把实现一些小功能的代码写成一个函数,不仅可以增强代码的可读性,还可以很方便的重用。一旦你创建了一个实现特定功能的函数,也可以下次在其它脚本中使用。
类库:把需要的函数嵌入进类库中,就不用每次在执行脚本时拷贝函数,并且还可以在需要时扩充它。另外以函数的方式构建类库,还可以让你更专注特定功能的具体实现,降低脚本开发的复杂度。
基础示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 param ([int]$n =$(throw "请输入一个正整数" ))Function Factorial([int]$n ){ $total =1 for ($i =1 ;$i -le $n ;$i ++) { $total *=$i } return $total } Factorial $n PS C:\Users\WeiyiGeek> .\test.ps1 PS C:\Users\WeiyiGeek> .\test.ps1 3 6 param ([int]$n =$(throw "请输入一个正整数" )). .PSLib.ps1 Factorial $n PS E:> .MyScript.ps1 10
Tips :脚本在执行时先加载类库中的函数(加载函数类库和执行脚本类似
), 只需要在前面增加一个句号中间有空格。
Tips: 我们可以将类库脚本集中存放常常有两种方式, 但是最好在当前用户的私人目录中存放脚本相对来说比较安全:
1.一种方法是和工作脚本存放在一起可以使用相对路径。
2.一种方法是分开存放,加载时就得使用绝对路径了。
1 2 3 PS C:\Users\WeiyiGeek> cd $env:APPDATA PS C:\Users\WeiyiGeek\AppData\Roaming> cd $env:APPDATA \PSLib PS C:\Users\WeiyiGeek>copy .PSLib.ps1 $env:APPDATA \PSLib
脚本参数 描述: 在Powershell的脚本中,可以使用自定义的参数列表,通常将参数放在Param()
中
基础语法&参数: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [Cmdletbinding()] param ([Parameter(Mandatory=$True )] [Alias('DT' )] [ValidateSet(2 ,3 )] [int]DiskType [Boolean] ) Mandatory 设置为True表示该参数强制输入 Alias 是为该参数设置了一个别名 ValidateSet 是为该参数设置了一个可用值列表 [数据类型] 指定该变量的类型
基础示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [Cmdletbinding()] param ([Parameter(Mandatory=$True )][String]$Name , [Alias('DT' )]$AliasDt , [ValidateSet(1 ,2 ,8 ,9 )]$Scope , [ValidateSet("My" ,"Love" ,"Computer" )]$ScopeStr , [Int]$DiskType , [Boolean]$Flag ) Write-Host $Name $DiskType $Flag Write-Host $AliasDt $DT Write-Host $Scope $ScopeStr .\ScriptArgs.ps1 -Name "WeiyiGeek" -AliasDt "PowerShell" -DiskType 1024 -Flag 0 -Scope 1 -ScopeStr Computer
Tips : 同时在脚本中使用write-verbose输出详细信息,在运行脚本的时候可以使用-verbose就能输出相关信息
脚本选择 描述: 这里使用$host.UI.PromptForChoice()方法
进行功能的实现,可以先看看方法的定义$host.ui.PromptForChoice
;
简单示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $SwitchUser = ([System.Management.Automation.Host.ChoiceDescription]"&Switchuser" )$LoginOff = ([System.Management.Automation.Host.ChoiceDescription]"&LoginOff" )$Lock = ([System.Management.Automation.Host.ChoiceDescription]"&Lock" )$Reboot = ([System.Management.Automation.Host.ChoiceDescription]"&Reboot" )$Sleep = ([System.Management.Automation.Host.ChoiceDescription]"&Sleep" )$Selection = [System.Management.Automation.Host.ChoiceDescription[]]($SwitchUser ,$LoginOff ,$Lock ,$Reboot ,$Sleep )$Answer =$Host .UI.PromptForChoice("接下来做什么事呢?" ,'请选择:' ,$selection ,1 )Write-Host -NoNewline "您选择的是:" switch ($Answer ){ 0 {"切换用户" } 1 {"注销" } 2 {"锁定" } 3 {"重启" } 4 {"休眠" } default {"正在完成操作请稍等!" } }
执行结果:1 2 3 4 接下来做什么事呢? 请选择: [S] Switchuser [L] LoginOff [L] Lock [R] Reboot [S] Sleep [?] 帮助 (默认值为“L”): S 您选择的是:切换用户
脚本异常处理
使用Write-Debug有两个优势,首先调试信息会自动高亮显示,便于分析。其次,这些调试信息只会在调试模式开启时输出,控制起来更加方便。当然最重要的是这些临时信息无论什么时候也不会混淆在返回值。
抑制错误信息 函数中的错误信息,也有可能作为返回值的一部分,因为默认这些错误信息会直接输出。 27 Function ErrorTest() {
#该进程不存在
Stop-Process -Name "www.mossfly.com"
} ErrorTest
Stop-Process : 找不到名为“www.mossfly.com”的进程。请验证该进程名称,然后再次调用 cmdlet。 所在位置 C:UsersbaozhenDesktoptest.ps1:6 字符: 17
Stop-Process <<<< -Name “www.mossfly.com"
CategoryInfo : ObjectNotFound: (www.mossfly.com:String ) [Stop-P rocess], ProcessCommandException
FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell. Commands.StopProcessCommand
很明显,类似这样的错误提示信息,对调试程序很重要,但如果你觉得它不重要,特意要隐藏,可以使用$ErrorActionPreference进行设置。
Function ErrorTest() { #从这里开始隐藏所有的错误信息 $ErrorActionPreference=”SilentlyContinue” Stop-Process -Name “www.mossfly.com" #该进程不存在 }
#错误信息不会输出 ErrorTest 但是上面的做法并不明智,因为这样可能错过其它错误提示。所以最好的方式是处理完后,对$ErrorActionPreference进行复位。 Function ErrorTest() {
#从这里开始隐藏所有的错误信息
$ErrorActionPreference="SilentlyContinue"
Stop-Process -Name "www.mossfly.com"
#该进程不存在
#恢复$ErrorActionPreference,错误开始输出
$ErrorActionPreference="Continue"
2/0
} ErrorTest 试图除以零。
所在位置 行:9 字符: 7
2/ <<<< 0
CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
FullyQualifiedErrorId : RuntimeException
PowerShell: Try…Catch…Finally 实现方法https://www.cnblogs.com/digjim/archive/2012/06/22/2558458.html
Powershell错误处理,try catch finallyhttps://www.cnblogs.com/micro-chen/p/5941660.html