Powershell使用真实的对象工作

来源 https://www.pstips.net/powershell-work-with-reallife-objects.html

每一个Powershell命令都会返回一个对象,但是返回的对象不易操作,因为控制台解释器会自动将对象转换成可视的文本,这样就会丢失绝大多数对象的信息。

在变量中存储结果

不要将结果在控制台输出可以防止对象转换成文本。控制台是一个不安全的地方,任何对象输出后都会自动转换成文本,最安全的方式是将对象保存在变量中。如果想将对象输出为文本,可以在控制台输入变量名。

PS C:Powershell> $FileList=dir
PS C:Powershell> $FileList 目录: C:Powershell Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2011/12/19 17:43 8956 a.ccs
-a--- 2011/12/19 18:02 46411 a.csv

事实上述存储在$FileList变量中的并不是真实的对象,而是一个对象数组,数组可以通过索引访问得到真实的对象。

PS C:Powershell> $obj=(dir)[0]
PS C:Powershell> $obj 目录: C:Powershell Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2011/12/19 17:43 8956 a.ccs

使用对象的属性

可以使用Get-Member得到一个对象所有的属性:

PS C:Powershell> $obj=(dir)[0]
PS C:Powershell> $obj | Get-Member -MemberType Property TypeName: System.IO.FileInfo Name MemberType Definition
---- ---------- ----------
Attributes Property System.IO.FileAttributes Attributes {get;set;}
CreationTime Property System.DateTime CreationTime {get;set;}
CreationTimeUtc Property System.DateTime CreationTimeUtc {get;set;}
Directory Property System.IO.DirectoryInfo Directory {get;}
DirectoryName Property System.String DirectoryName {get;}
Exists Property System.Boolean Exists {get;}
Extension Property System.String Extension {get;}
FullName Property System.String FullName {get;}
IsReadOnly Property System.Boolean IsReadOnly {get;set;}
LastAccessTime Property System.DateTime LastAccessTime {get;set;}
LastAccessTimeUtc Property System.DateTime LastAccessTimeUtc {get;set;}
LastWriteTime Property System.DateTime LastWriteTime {get;set;}
LastWriteTimeUtc Property System.DateTime LastWriteTimeUtc {get;set;}
Length Property System.Int64 Length {get;}
Name Property System.String Name {get;}

如果属性的定义列中包含{get;set}表明该属性可以被更新:

PS C:Powershell> $obj.LastAccessTime

2011年12月19日 17:43:37

PS C:Powershell> $obj.LastAccessTime=Get-Date
PS C:Powershell> $obj.LastAccessTime 2012年1月11日 14:21:01

Powershell特殊属性

Powershell中 可以给一个对象增加属性,增加的属性仍然可以通过Get-Member的标签辨别,因为对象的正常属性标签名为:Property,新增加的属性标签多了一个前缀,如ScriptProperty和NoteProperty。
一个NoteProperty包含了静态的数据。一个ScriptProperty中包含了一段脚本,通过脚本计算出属性的值。
下面的例子新建一个对象$obj,给$obj增加两个属性一个为NoteProperty,一个为ScriptProperty,输出$obj ,CurrentTime属性会自动更新,AddTime则不会。

PS C:Powershell> $obj=New-Object PSobject
PS C:Powershell> $obj | Add-Member -MemberType NoteProperty -Name AddTime -Value (get-date)
PS C:Powershell> $obj | Add-Member -MemberType ScriptProperty -Name CurrentTime -Value {get-date}
PS C:Powershell> $obj AddTime CurrentTime
------- -----------
2012/1/11 14:35:38 2012/1/11 14:36:35 PS C:Powershell> $obj AddTime CurrentTime
------- -----------
2012/1/11 14:35:38 2012/1/11 14:36:44

MemberType包括:
AliasProperty:另外一个属性的别名
CodeProperty:通过静态的.Net方法返回属性的内容
Property:真正的属性
NoteProperty:随后增加的属性
ScriptProperty:通过脚本执行返回一个属性的值
ParameterizedProperty:需要传递参数的属性

调用对象的方法

同样可以通过Get-Memeber获得一个对象支持的所有方法:

PS C:Powershell> $obj= (dir)[0]
PS C:Powershell> $obj | Get-Member -me method TypeName: System.IO.FileInfo Name MemberType Definition
---- ---------- ----------
AppendText Method System.IO.StreamWriter AppendText()
CopyTo Method System.IO.FileInfo CopyTo(string destFileName), System.IO.FileInfo CopyTo(strin...
Create Method System.IO.FileStream Create()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
CreateText Method System.IO.StreamWriter CreateText()
Decrypt Method System.Void Decrypt()
Delete Method System.Void Delete()
Encrypt Method System.Void Encrypt()
Equals Method bool Equals(System.Object obj)
GetAccessControl Method System.Security.AccessControl.FileSecurity GetAccessControl(), System.Security....
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetObjectData Method System.Void GetObjectData(System.Runtime.Serialization.SerializationInfo info, ...
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
MoveTo Method System.Void MoveTo(string destFileName)
Open Method System.IO.FileStream Open(System.IO.FileMode mode), System.IO.FileStream Open(S...
OpenRead Method System.IO.FileStream OpenRead()
OpenText Method System.IO.StreamReader OpenText()
OpenWrite Method System.IO.FileStream OpenWrite()
Refresh Method System.Void Refresh()
Replace Method System.IO.FileInfo Replace(string destinationFileName, string destinationBackup...
SetAccessControl Method System.Void SetAccessControl(System.Security.AccessControl.FileSecurity fileSec...
ToString Method string ToString()

调用一个对象的方法时,省略括号可以获取一个方法的详细定义信息:

PS C:Powershell> $obj.CreationTime

2011年12月19日 17:43:37

PS C:Powershell> $obj.MoveTo

MemberType          : Method
OverloadDefinitions : {System.Void MoveTo(string destFileName)}
TypeNameOfValue : System.Management.Automation.PSMethod
Value : System.Void MoveTo(string destFileName)
Name : MoveTo
IsInstance : True

调用对象的Delete方法:或者使用 Remove-Variable cmdlet。

PS C:Powershell> Test-Path $obj
True
PS C:Powershell> $obj.Delete()
PS C:Powershell> Test-Path $obj
False

不同的方法类型

类似于属性,Powershell对象也可以增加方法,方法类型包括:
CodeMethod:映射到静态的.NET方法
Method:正常的方法
ScriptMethod:一个执行Powershell脚本的方法

Powershell变量的作用域

https://www.pstips.net/powershell-scope-of-variables.html

Powershell所有的变量都有一个决定变量是否可用的作用域。Powershell支持四个作用域:全局、当前、私有和脚本。有了这些作用域就可以限制变量的可见性了,尤其是在函数和脚本中。

如果我们对变量不做特别的声明,Powershell解释器会自动处理和限制变量的作用域。将下面的内容命令保存着至test1.ps1
$windows = $env:windir
“Windows Folder: $windows”

然后在控制台给变量$windows赋值,并调用Test.ps1脚本。

PS> $windows="Hellow"
PS> .\test.ps1
Windows Folder: C:\Windows
PS> $windows
Hellow

调用脚本时,会分配一个变量$windows,在脚本调用结束后,这个变量被回收,脚本中的变量不会影响脚本外的变量,因为它们在不同的作用域中。powershell会针对每个函数和脚本给它们分配不同的作用域。

更改变量的可见性

你可以很容易的看到没有Powershell解释器自动限制可见性时会发生什么状况,同样是刚才的脚本,刚才的命令,只是在运行脚本时多加上一个点”.” 和一个空格:

PS> $windows="Hellow"
PS> . .\test.ps1
Windows Folder: C:\Windows
PS> $windows
C:Windows

在运行脚本时使用一个原点和空格,Powershell解释器就不会为脚本本身创建自己的变量作用域,它会共享当前控制台的作用域,这种不太灵活但却简单的方法,使用时一定要格外小心。

加强变量可见性限制的优点:清空初始化环境
可以假设一个场景,如果你在当前控制台不小心定义了一个只读的常量,这个常量既不能更新也不能删除,很是麻烦。但是如果你在脚本中操作这个变量就不成问题,因为脚本有自己的作用域。例如,将下面文本保存为test.ps1,并调用没有任何问题:

New-Variable a -value 1 -option Constant
"Value: $a"
PS> .\test.ps1
Value: 1
PS> .\test.ps1
Value: 1

但是如果你通过圆点禁用作用域限制,调用test.ps1,就会有异常,因为一个常量不能被创建两次。

PS> . .\test.ps1
Value: 1
PS> . .\test.ps1
New-Variable : A variable with name 'a' already exists.
Attest.ps1:1 char:13
+ New-Variable <<<< a -value 1 -option Constant
+ CategoryInfo : ResourceExists: (a:String) [New-Variable], SessionStateException
+ FullyQualifiedErrorId : VariableAlreadyExists,Microsoft.PowerShell.Commands.NewVariableCommand

所以这种变量的作用域限制可以把变量的冲突降到最小。

设置单个变量的作用域

到目前为止,看到的变量作用域的改变都是全局的,能不能针对某个具体变量的作用域做一些个性化的设置。

$global
全局变量,在所有的作用域中有效,如果你在脚本或者函数中设置了全局变量,即使脚本和函数都运行结束,这个变量也任然有效。

$script
脚本变量,只会在脚本内部有效,包括脚本中的函数,一旦脚本运行结束,这个变量就会被回收。

$private
私有变量,只会在当前作用域有效,不能贯穿到其他作用域。

$local
默认变量,可以省略修饰符,在当前作用域有效,其它作用域只对它有只读权限。

打开Powershell控制台后,Powershell会自动生成一个新的全局作用域。如果增加了函数和脚本,或者特殊的定义,才会生成其它作用域。在当前控制台,只存在一个作用域,通过修饰符访问,其实访问的是同一个变量:

PS> $logo="www.pstips.net"
PS> $logo
www.pstips.net
PS> $private:logo
www.pstips.net
PS> $script:logo
www.pstips.net
PS> $private:logo
www.pstips.net
PS> $global:logo
www.pstips.net

当调用一个已定义的函数,Powershell会生成第二个作用域,它可以对调用者的作用域中的变量执行读操作,但是不能执行写操作。

PS> function f(){ "var=$var";$var="function inner";$var }
PS> $var="I am in console."
PS> $var
I am in console.
PS> f
var=I am in console.
function inner
PS> $var
I am in console.

怎样把当前控制台中的变量保护起来,不让它在函数和脚本中被访问,Private修饰符就派上了用场。

PS>  function f(){ "var=$var";$var="function inner";$var }
PS> $private:var="i am a private variable in console,other scope can not access me."
PS> f
var=
function inner
PS> $private:var
i am a private variable in console,other scope can not access me.

对于$private限制的变量能不能在函数中通过$global修改呢?不但不能修改,还会删除当前的$private变量

PS> Function f(){ "var=$var";$global:var=" Try to change variable in function"}
PS> $private:var="I am a private variable"
PS> $private:var
I am a private variable
PS> $var
I am a private variable
PS> f
var=
PS> $private:var
PS> $var
PS>
PS> $private -eq $null
True

但是$local 修饰的变量则可以通过$global在函数内部更改。

PS> Function f(){ "var=$var";$global:var=" Try to change variable in function"}
PS> $var="I am a local variable."
PS> $var
I am a local variable.
PS> $private:var
I am a local variable.
PS> f
var=I am a local variable.
PS> $var
Try to change variable in function
PS> $local:var
Try to change variable in function

Powershell对象=属性+方法

https://www.pstips.net/powershell-object-contains-properties-and-methods.html

在现实世界中,你可能已经了解对象就是那些能够摸到的东西。Powershell中的对象和现实生活很相似。例如要在现实生活中描述一把小刀。我们可能会分两方面描述它
属性:一把小刀拥有一些特殊的属性,比如它的颜色、制造商、大小、刀片数。这个对象是红色的,重55克,有3个刀片,ABC公司生产的。因此属性描述了一个对象是什么。
方法:可以使用这个对象做什么,比如切东西、当螺丝钉用、开啤酒盖。一个对象能干什么就属于这个对象的方法。

创建对象

通过New-Object可以创建一个对象,甚至可以创建一个虚拟的小刀,但是第一步需要创建一个空对象。空对象什么都没有,如果调用它,不会返回任何东西。

PS C:Powershell> $pocketknife=New-Object object
PS C:Powershell> $pocketknife
System.Object

增加属性

接下来描述这个对象是什么

PS C:Powershell> Add-Member -InputObject $pocketknife -Name Color -Value "Red"
-MemberType NoteProperty
PS C:Powershell> $pocketknife Color
-----
Red PS C:Powershell> Add-Member -InputObject $pocketknife -Name Weight -Value "55"
-MemberType NoteProperty
PS C:Powershell> $pocketknife | Add-Member NoteProperty Blades 3
PS C:Powershell> $pocketknife | Add-Member NoteProperty Manufacturer ABC
PS C:Powershell> $pocketknife Color Weight Blades Manufacturer
----- ------ ------ ------------
Red 55 3 ABC

增加方法

给一个对象增加了属性后,这个对象就有形状了,但是它仍然不能做任何事,要想它做事,必须给它增加方法。同样使用Add-Member,不过-memberType 选项使用ScriptMethod。

1
2
3
4
5
6
7
# 增加一个新方法:
Add-Member -memberType ScriptMethod -In $pocketknife `
-name cut -Value "I'm whittling now" }
# 指定参数类型增加一个新方法:
Add-Member -in $pocketknife ScriptMethod screw { "Phew...it's in!" }
#直接通过管道增加一个新方法:
$pocketknife Add-Member ScriptMethod corkscrew { "Pop! Cheers!" }

方法添加成功后就可以调用了

PS C:Powershell> $pocketknife.cut()
I'm whittling now
PS C:Powershell> $pocketknife.screw()
Phew...it's in!
PS C:Powershell> $pocketknife.corkscrew()
Pop! Cheers!

在调用方法时如果没有使用圆括号,方法不会执行,但是可以返回方法的基本信息。

PS C:Powershell> $pocketknife.corkscrew

Script                      :  "Pop! Cheers!"
OverloadDefinitions : {System.Object corkscrew();}
MemberType : ScriptMethod
TypeNameOfValue : System.Object
Value : System.Object corkscrew();
Name : corkscrew
IsInstance : True

到目前为止一个虚拟的小刀对象就创建完成了,一个对象包含数据(属性)和动作(方法)。

Powershell变量的类型和强类型

http://www.pstips.net/powershell-variable-strongly-typing.html

变量可以自动存储任何Powershell能够识别的类型信息,可以通过$variable的GetType().Name查看和验证Powershell分配给变量的数据类型。

PS> (10).gettype().name
Int32
PS> (9999999999999999).gettype().name
Int64
PS> (3.14).gettype().name
Double
PS> (3.14d).gettype().name
Decimal
PS> ("WWW.MOSSFLY.COM").gettype().name
String
PS> (Get-Date).gettype().name
DateTime

Powershell会给数据分配一个最佳的数据类型;如果一个整数超出了32位整数的上限([int32]::MaxValue),它就会分配一个64位整数的数据类型;如果碰到小数,会分配一个Double类型;如果是文本,Powershell会分配一个String类型;如果是日期或者时间,会被存储为一个Datetime对象。
这种类型自适应也称作“弱类型”,虽然使用起来方便,但是也会有一些限制,甚至危险。如果powershell选择了一个错误的类型付给变量,可能会引发一些奇怪的现象。例如有一个变量要存储的是即将拷贝文件的个数,可是在赋值时付了一个字符串,Powershell不会去做过多的判断,它会更新这个变量的类型,并且存储新的数据。所以一般专业的程序员或者脚本开发者更喜欢使用“强类型”,哪怕在赋值时类型不兼容的报错,他们也乐意接受。
喜欢使用强类型的另一个原因是:每一个数据类型都有属于自己的函数。例如DateTime,和XML,尽管这两种类型都可以用纯文本表示,但是使用强类型[DateTime]和[XML],对于数据操作起来更方便,这两个类型的方法可是很丰富奥!

指定类型定义变量

定义变量时可以在变量前的中括号中加入数据类型。例如定义一个Byte类型的变量,因为Byte的定义域为[0,255],一旦尝试使用一个不在定义域中的值赋给该变量就会显示一条错误信息。

PS> [byte]$b=101
PS> $b
101
PS> $b=255
PS> $b
255
PS> $b.gettype() IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Byte System.ValueType PS> $b=256 Cannot convert value "256" to type "System.Byte". Error: "Value was either too large or too small for an unsigned byte.
"
At line:1 char:3
+ $b <<<< =256
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException

使用固定类型的优点

手动地定义类型的一个重要原因是每个特殊的数据类型都有自己的特殊命令和特殊方法。比如把一个日期字符串赋给一个变量,Powershell不会自动把这个字符串转换成日期对象赋给一个变量,因为Powershell毕竟是机器,没有人那么智能。当你在赋值时指定DateTime类型时,你会发现几乎所有的.Net 中DateTime类型的方法在这里都得到支持。

PS> [DateTime]$date="2012-12-20 12:45:00"
PS> $date 2012年12月20日 12:45:00 PS> $date.DayOfWeek
Thursday
PS> $date.DayOfYear
355
PS> $date.AddDays(-10) 2012年12月10日 12:45:00

Powershell处理Xml文档也很方便,
例如有如下LogoTest.xml

1
2
3
4
5
6
7
8
9
10
<logotest>
  <extensions>
    <e>.exe</e>
    <e>.dll</e>
  </extensions>
  <files>
    <f></f>
  </files>
  <dirs></dirs>
</logotest>

查询.exe 和 .dll结点

PS> [ XML ]$xml=(Get-Content .LogoTestConfig.xml)
PS> $xml.LogoTest.Extensions.E
.exe
.dll

Powershell 默认支持的.NET类型如下。
[array],[bool],[byte],[char],[datetime],[decimal],[double],[guid],[hashtable],[int16],[int32],[int],[int64],[long],[nullable],[psobject],[regex],[sbyte].[scriptblock],[single],[float],[string],[switch],[timespan],[type],[uint16],[uint32],[uint64],[ XML ]

Powershell扩展类型系统

https://www.pstips.net/powershell-extended-type-system-1.html

Powershell一个最吸引人的功能是它能够将任何对象转换成文本,我们已经使用过将对象属性以不同的版式转换成文本,并且输出。更令人惊奇的是Powershell会把最重要最能代表这个对象本质的信息输出。一个对象有很多属性,为什么它单单就输出那几个属性呢?
如果使用:

Dir | Format-Table * -wrap
PSP PSP PSC PSD PSP PSI Bas Mod Nam Par Exi Roo Ful Ext Cre Cre Las La La La At
ath are hil riv rov sCo eNa e e ent sts t lNa ens ati ati tAc st st st tr
ntP dNa e ide nta me me ion onT onT ces Ac Wr Wr ib
ath me r ine ime ime sTi ce it it ut
r Utc me ss eT eT es
Ti im im
me e eU
Ut tc
c
--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- -- -- -- --
Mic Mic ABC C Mic Tru ABC d-- ABC Pow Tru C: C: 201 201 201 20 20 20 Di
ros ros ros e -- ers e Pow 1/1 1/1 1/1 11 11 11 re
oft oft oft hel ers 2/1 2/1 2/1 /1 /1 /1 ct
.Po .Po .Po l hel 9 1 9 9 9 1 2/ 2/ 2/ or
wer wer wer lA 7:0 :05 7:0 19 19 19 y
She She She BC 5:5 :55 5:5 9 1 9
ll. ll. ll. 5 5 :0 7: :0
Cor Cor Cor 5: 05 5:
eF eF eF 55 :5 55
ile ile ile 5
Sys Sys Sys
tem tem tem
::C ::C

最新文章

  1. 如何使 WebAPI 自动生成漂亮又实用在线API文档
  2. 解析XML文档
  3. Linux服务器搬迁记(一)
  4. VS使用过程中,编写JS没有智能提示解决方法
  5. HTML知识点链接
  6. android中广告轮播图总结
  7. mac iterm2快捷键
  8. C# 操作XML 如果不存在创建 存在直接追加
  9. 【Unity3D】Unity3D之 注册表动态存取游戏存档——PlayerPrefs类
  10. com.mchange.v2.c3p0.ComboPooledDataSource
  11. asp.net后台获取前台的样式和后台给前台设置样式
  12. Struts2技术详解(转)
  13. CSS background-repeat 属性
  14. apt-get Ubuntu本地ISO镜像入源
  15. Spring Boot 发送邮件
  16. DSAPI+DS控件库 Windows7风格控件演示
  17. mysql备份与还原 数据库的常用命令。
  18. 【原创】一个线程oom,进程里其他线程还能运行吗?
  19. 关闭图形界面下普通用户关机重启命令- 7.x - CentOS
  20. 一分钟了解mongodb(转)

热门文章

  1. android 自定义滑动按钮
  2. SSM框架理解搭建(虽然是网上拼的,但是实际按照搭建是可以的)——
  3. 百度知道芝麻将,申请资格&amp;权限介绍&amp;奖惩制度(简剖)
  4. JavaSE 第二次学习随笔(二)
  5. Linux Shell 与Linux常用命令
  6. JAVA 基础编程练习题
  7. n点游戏
  8. Redis的RDB与AOF介绍(Redis DateBase与Append Only File)
  9. go学习笔记-结构体
  10. php复制目录很浪