[TOC]

0x00 PS 编程基础

描述: 当我第一次开始学习 PowerShell 时,如果无法使用 PowerShell 单行命令完成任务我会回到 GUI 找寻帮助。然后着时间的推移,我逐渐掌握了编写脚本、函数和模块的技能。


1.基础格式

  • 1.脚本注释 : 在PS中采用 #字符进行注释
  • 2.变量命名 : 全局变量采用大写变量名,而非全局变量采用首字母大写或者驼峰命名法。
  • 3.对象命名 : 使用动词-名称的格式。
  • 4.大小写: 命令执行不区分大小写。


2.调用优先级

描述: Powershell调用入口的优先级(由上到下):

  • 别名:控制台首先会寻找输入是否为一个别名,如果是执行别名所指的命令。因此我们可以通过别名覆盖任意powershell命令,因为别名的优先级最高
  • 函数:如果没有找到别名会继续寻找函数,函数类似别名,只不过它包含了更多的powershell命令。因此可以自定义函数扩充cmdlet 把常用的参数给固化进去。
  • 命令:如果没有找到函数,控制台会继续寻找命令,即cmdlet,powershell的内部命令。
  • 脚本:没有找到命令,继续寻找扩展名为“.ps1”的Powershell脚本。
  • 文件:没有找到脚本,会继续寻找文件,如果没有可用的文件,控制台会抛出异常。

总结: Alias > Function > Command > Script > File


3.PS特殊字符

  • ' : 单引号中的$符号不会识别为变量
  • "": 双引号中的$符号会识别为变量
  • ` : 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
26
27
28
29
30
31
# -1.符号使用对比
PS C:\Users\WeiyiGeek> $a=8; $b='$a is 8'; $b
$a is 8
PS C:\Users\WeiyiGeek> $a=8; $b="$a is 8"; $b
8 is 8
PS C:\Users\WeiyiGeek> $a=8; $b="`$a is 8"; $b
$a is 8
PS C:\Users\WeiyiGeek> $json = [String]@"
>> {
>> "test": 'json',
>> "name": "WeiyiGeek",
>> "age": 1024
>> }
>> "@
PS C:\Users\WeiyiGeek> $json
{
"test": 'json',
"name": "WeiyiGeek",
"age": 1024
}

# -2.转义字符进行命令执行换行使用以及字符串输出换行
PS C:\Users\WeiyiGeek> Get-WmiObject -Class win32_bios `
| select serialnumber
# serialnumber
# ------------
# 8QVY862

"This is `nnewLine"
# This is
# newLine


Tips :PowerShell的正则表达式中可能出现的字符(实际上大致与Perl差不多)

  • (1) 字符串的匹配符(占位符PlaceHolder):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    . 这是一个点儿,表示换行符之外的任意一个字符(Any character except newline (Equivalent: [^\n]))
    [^abc] 指定的字符(abc)之外的任意一个字符,可以把abc换成其它字符组。(All characters except the ones specified)
    [^a-z] 任意一个非小写字母的字符(All characters except those in the region specified)
    [abc] 指定的字符集中的任意一个,即abc中的任意一个(One of the characters)
    [a-z] 指定的字符范围中的任意一个,即任意一个小写字母。One of the characters in the region
    \a 响呤(Bell (ASCII 7))
    \c Any character allowed in XML names
    \cA-\cZ Control+A to Control+Z, ASCII 1 to ASCII 26
    \d 任意一个数字,等同于[0-9](Any number (Equivalent: [0-9]))
    \D 任意一个非数字。Any non-number
    \e ESC键(Escape (ASCII 27))
    \f Form Feed, (ASCII 12)
    \n 换行Line break
    \r 回车Carriage return
    \s 任意一个空白键(空白键如tab,换行)Any whitespace (space, tab, new line)
    \S 任意一个非空白字符(Any non-whitespace)
    \t tab键
    \w 字母,数字和下划线(Letter, number or underline)
    \W \w的补集(Non-letter, number, or underline)
  • (2) 匹配次数(量词Quantifier)

    1
    2
    3
    4
    5
    6
    7
    * 出现零次、1次、多次(Any (no occurrence, once, many times))
    ? 出现零次、1次(No occurrence or one occurrence)
    {n,} 出现至少n次(At least n occurrences)
    {n,m} 出现至少n次,最多m次(At least n occurrences, maximum m occurrences)
    {n} 出现n次(Exactly n occurrences)
    + 出现1次、多次(One or many occurrences)
    所有的匹配次数的符号,默认情况下都是贪婪的,即它将最大长度的进行匹配。如果想要得到最短的匹配,那就要在上面这组符号之后加一个问号(?)。
  • (3) 匹配边界

    1
    2
    3
    4
    5
    $ 字符串结束(End of text)
    ^ 字符串开始(Start of text)
    \b Word boundary
    \B No word boundary
    \G After last match (no overlaps)

0x01 PS 交互式

描述: 我们可以通过打开powershell.exe应用windows窗口来进行交互式命令行的输入

1.命令行计算

1
2
3
4
5
6
PS C:\Users\WeiyiGeek> (512*2)/2+512
1024
PS C:\Users\WeiyiGeek> 1gb / 1mb
1024
PS C:\Users\WeiyiGeek> 0x3389
13193


2.执行外部命令

描述: PS 能够像CMD一样很好的执行外部命令, 即在 windows Cmd 中运行的基本都可以在PS中运行。

1
2
3
4
5
6
# 通过netstat查看网络端口状态
netstat
# 通过IPConfig查看自己的网络配置
ipconfig
# 启动CMD控制台键入cmd或者cmd.exe, 而退出cmd可以通过命令exit。
cmd

Q: 为什么可以通过notpad打开记事本,不能通过wordpad打开写字板?

答: 因为notepad.exe位于C:Windows\system32 这个目录,而这个目录已经默认被包含在Powershell的环境变量$env:Path中。而wordpad.exe 所在的“%ProgramFiles%\Windows NT\Accessories\wordpad.exe“目录却没有包含;

1
2
3
4
5
C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files (x
86)\Windows Kits\8.1\Windows Performance Toolkit\;C:\Program Files\Microsoft SQL Server\110\Tools\Binn\;C:\Program File
s (x86)\Microsoft SDKs\TypeScript\1.0\;C:\Program Files\Microsoft\Web Platform Installer\

# 解决办法:可以先进入这个目录,再运行wordpad,或者将wordpad所在的目录加入到环境变量中,$env:Path=$env:Path+”%ProgramFiles%\Windows NT\Accessories”。


3.别名设置与使用

描述: 与Linux的Alias命令一样Windows PS中也支持自定义别名,其别名的两个作用是继承unix-shell和windows-cmd方便用户使用

基础实例:

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
# 1.查询别名所指的真实cmdlet命令。
Get-Alias -name ls

# 2.查看可用的别名
Get-Alias
# 查看所有别名和指向cmdlet的别名的个数
ls alias: | Group-Object definition | sort -Descending Count

# 3.创建自己的别名
PS C:\PS> Set-Alias -Name Edit -Value notepad
PS C:\PS> Edit
PS C:\PS> $alias:Edit
notepad

# 4.删除自己的别名
# 自定义的别名在powershell退出时会自动清除(前提是没有导入系统中),而内置别名需要手工进行删除别名
del alias:Edit

# 5.保存自己的别名(导出与导入)
Export-Alias alias.ps1
Import-Alias -Force alias.ps1

# 6.通过函数扩展别名(当简单的别名无法完成复制的工作时需要采用此方法),这样定义别名会变得更加灵活;
PS C:\PS> function test-conn { Test-Connection -Count 2 -ComputerName $args}
PS C:\PS> Set-Alias tc test-conn
PS C:\PS> tc localhost # 有了函数牵线别名可以完成更高级更强大的功能,其中$args为参数的占位符。
Source Destination IPV4Address IPV6Address Bytes Time(ms)
------ ----------- ----------- ----------- ----- --------
WeiyiGeek localhost 127.0.0.1 ::1 32 0


4.执行文件和脚本

描述: 我们可以直接在PS命令行中运行文件和脚本,但是必须使用绝对路径或者相对路径,或者要运行的文件必须定义在可受信任的环境变量中。

PowerShell 中可执行Bat批处理、VB脚本问号、以及PS1脚本文件

Tips: 脚本和批处理都属于伪可执行文件,它们只是包含了若干命令行解释器能够解释和执行的命令行代码。

示例1.在PS中执行ping.bat批处理

1
2
3
4
5
6
# ping.bat
@echo off
echo #batch File Test#
echo %1%
%1%
pause

演示效果:
1
2
3
4
5
6
7
8
9
10
PS C:\Users\WeiyiGeek> ./ping whoami
#batch File Test#
whoami
weiyigeek\weiyigeek
请按任意键继续. . .
PS C:\Users\WeiyiGeek> ./ping hostname
#batch File Test#
hostname
WeiyiGeek
请按任意键继续. . .

WeiyiGeek.ping

WeiyiGeek.ping

Tips : 在cmd输入ping执行的不是ping命令而是直接运行ping.bat(即.bat覆盖了cmd命令),而在PS上面运行ping批处理文件必须是以./ping的格式, 所以说命令与脚本的混淆不会发生在powershell中,因为powershell有更安全的机制。


示例2.在PS中执行VB脚本文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 执行 .\test.vbs 会遍历当前Win32进程,并把每个进程的详细信息通过窗口显示出来。
# test.vbs
Set wmi = GetObject("winmgmts:")
Set collection = wmi.ExecQuery("select * from Win32_Process")
For Each process in collection
WScript.Echo process.getObjectText_
Next

# 在powershell中执行VB脚本
PS C:\PS> cscript.exe .test.vbs
instance of Win32_Process
{
Caption = "System Idle Process";
CreationClassName = "Win32_Process";
CSCreationClassName = "Win32_ComputerSystem";
....
}

Tips : 怎样让VB脚本的通过控制台输出呢? Wscript //H:CScript
Tips : 怎样还原VB脚本通过窗口输出呢?WScript //H:WScript


示例3.在PS中执行ps1脚本文件
描述: Powershell拥有自己的脚本扩展名为”.ps1”

1
2
3
4
PS C:\PS> echo "dir;Get-PSProvider;help dir" >test.ps1
PS C:\PS> Get-Content ./test.ps1
dir;Get-PSProvider;help dir
PS C:\PS> ./test.ps1


0x02 PS 管道介绍

1.基础概念

Q:什么是管道?

答: 管道的行为就像一系列连接的管道段一样,沿着管道移动的项会通过每个管道段;

描述:在 PS 中创建管道请使用管道运算符“|”将命令连接在一起,每个命令的输出都将被用作下一命令的输入,与Linux中Shell使用类似, 但是不同的是它传递的数据不是文本而是对象;

管道的处理模式:

  • 1.顺序模式(较慢):在顺序模式中管道中同一时间只执行一条命令,只有当前一条命令的所有执行完毕,才会把所有结果交付给下一条命令。
    • 优缺点:速度慢并且耗内存,因为需要很多次分配空间存储中间结果。
  • 2.流模式(较快):流模式会立即执行所有命令,同一时间可能在执行多条命令。
    • 优缺点: 比较节省内存,可能管道的某个任务还在执行,但是已经有部分结果输出了,减少了中间结果的保存。


Tips : 管道命令也是存在的阻塞,比如在对递归的文件进行排序的时候,需要获取全部文件后才能进行排序; (Dir C: -recurse | Sort-Object)

Tips : 管道中的每个命令(称为管道元素)将其输出逐项传递到管道中的下一个命令

  • 1.传统的Cmd管道是基于文本的,但是Powershell是基于对象
  • 2.管道中传递是对象可以作为下一个cmdlet的参数
  • 3.它可以减少使用复杂命令的工作量,更轻松地查看命令的工作流程
  • 4.少了资源消耗并且能够立即开始获取输出提高执行效率


常用需要使用管道的命令:

  • Compare-Object: 比较两组对象。
  • ConvertTo-Html: 将 Microsoft .NET Framework 对象转换为可在 Web 浏览器中显示的 HTML。
  • Export-Clixml: 创建对象的基于 XML 的表示形式并将其存储在文件中。
  • Export-Csv: 将 Microsoft .NET Framework 对象转换为一系列以逗号分隔的、长度可变的 (CSV) 字符串,并将这些字符串保存到
  • 一个 CSV 文件中。
  • ForEach-Object: 针对每一组输入对象执行操作。
  • Format-List: 将输出的格式设置为属性列表,其中每个属性均各占一行显示。
  • Format-Table: 将输出的格式设置为表。
  • Format-Wide: 将对象的格式设置为只能显示每个对象的一个属性的宽表。
  • Get-Unique: 从排序列表返回唯一项目。
  • Group-Object: 指定的属性包含相同值的组对象。
  • Import-Clixml: 导入 CLIXML 文件,并在 Windows PowerShell 中创建相应的对象。
  • Measure-Object: 计算对象的数字属性以及字符串对象(如文本文件)中的字符数、单词数和行数。
  • more: 对结果分屏显示。
  • Out-File: 将输出发送到文件。
  • Out-Null: 删除输出,不将其发送到控制台。
  • Out-Printer: 将输出发送到打印机。
  • Out-String: 将对象作为一列字符串发送到主机。
  • Select-Object: 选择一个对象或一组对象的指定属性。它还可以从对象的数组中选择唯一对象,也可以从对象数组的开头或末尾选
  • 择指定个数的对象。
  • Sort-Object: 按属性值对象进行排序。
  • Tee-Object: 将命令输出保存在文件或变量中,并将其显示在控制台中。
  • Where-Object: 创建控制哪些对象沿着命令管道传递的筛选器。


2.单行命令

描述: PowerShell one 命令是一种连续管道,不一定是一条物理线路上的命令, 但又并非一个物理行上的所有命令都是单行命令。

Tips : 管道符号是 PowerShell 中允许自然换行处的某个字符,包括逗号 (,) 和方左括号 ([)、大括号 ({) 和圆括号 (()。

Tips : 其他不太常见的字符包括分号 (;)、等于号 (=) 以及左单引号和双引号(’、”)

示例1: 即使以下命令位于多个物理行上,它也是 PowerShell 单行命令,因为它是一个连续管道。

1
2
3
4
5
6
7
# 1) 系统服务获取与属性查看
Get-Service |
Where-Object CanPauseAndContinue -eq $true |
Select-Object -Property *

# 2) 输出当前目录中的文件并通过管道进行排序
ls | sort -Descending Name | Format-Table Name,Mode

示例2.将反引号 (`) 或重音符用作续行符是一个有争议的话题(建议尽量避免这样做),因为上面和下面示例中所示的命令在 PowerShell 控制台中正常工作。 但如果尝试在 PowerShell ISE 的控制台窗格中运行它们,则会出现错误。

1
2
3
4
5
6
7
8
9
10
# PS (执行OK)
Get-Service -Name w32time |
>> Select-Object -Property *

# PS ISE : PowerShell ISE 的控制台窗格不会等待命令的其余部分在下一行(如 PowerShell 控制台)中输入。
Get-Service -Name w32time |
不允许使用空管道元素。
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordEx
ception
+ FullyQualifiedErrorId : EmptyPipeElement

WeiyiGeek.PowerShell与ISE

WeiyiGeek.PowerShell与ISE

解决办法: 要避免 PowerShell ISE 的控制台窗格中出现此问题,请使用 Shift+Enter,而不是只是在继续执行另一行上的命令时按 Enter。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# PS ISE
PS C:\Users\WeiyiGeek> Get-Service -Name w32time |
# Select-Object -Property *

# Name : w32time
# RequiredServices : {}
# CanPauseAndContinue : False
# CanShutdown : True
# CanStop : True
# DisplayName : Windows Time
# DependentServices : {}
# MachineName : .
# ServiceName : w32time
# ServicesDependedOn : {}
# ServiceHandle :
# Status : Running
# ServiceType : Win32OwnProcess, Win32ShareProcess
# StartType : Manual
# Site :
# Container :


示例3.下一个示例不是 PowerShell 单行命令,因为它不是一个连续管道,它是一行上的两个单独命令,用分号(;)分隔。

1
2
3
4
$Service = 'w32time'; Get-Service -Name $Service
# Status Name DisplayName
# ------ ---- -----------
# Running w32time Windows Time


示例4.格式化管道文本输出
描述: PS 可以通过管道将对象结果转换成文本并显示在控制台上。

1
2
3
4
# 实例1.事实上Out-Default会首先调用Format-Table,将更多的属性默认隐藏,再调用Out-Host将结果输出在控制台上。
ls | Out-Default
ls | Format-Table | Out-Host
ls | Format-Table * -Wrap # 显示隐藏的对象属性


3.重定向

描述: 我们可以通过重定向符将命令输出保存到文件之中 ‘>’ 为覆盖 ’>>’ 追加;

重定向标识:

  • 1 > stdio.out
  • 2 > errorout
  • 6 > infoout


基础示例:

1
2
3
4
5
6
7
8
9
# 示例1.简单实例
PS C:\PS> "Powershell Routing" >.txt
PS C:\PS> "Powershell Routing1" >>.txt
PS C:\PS> Get-Content .\.txt
Powershell Routing
Powershell Routing1

# 示例2.错误输出重定向
Get-Command Get-Acl 1> out.txt 2> error.txt 6> info.txt


4.ETS与管道

描述: 扩展类型系统Extended Type System (ETS),ETS会对管道中对象转换成文本的机制进行宏观调控。

ETS由两部分组成:

  • 一部分控制对象的版式: 需要创建一个.ps1xml的配置文件
  • 一部分控制对象的属性: 在管道中将对象结果转换成文本后,不能再将文本转换成对象,因为ETS不能处理文本。

Tip : ETS配置中包含的类型对象会以最佳的方式转换成文本,我们可以ETS配置中包含的类型对象会以最佳的方式转换成文本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 1.首先确定命令返回结果的对象类型
PS > $object = Get-WmiObject Win32_Processor | Select-Object -first 1
PS > $object.GetType().FullName
System.Management.ManagementObject #发现目标类型为:System.Management.ManagementObject

# 2.其次创建一个配置文件:Win32_Processor.format.ps1xml
System.Management.ManagementObject
<label>Name</label>
<label>Description</label>
<label>ID</label>

PS > Update-FormatData .Win32_Processor.format.ps1xml #加载进ETS
PS > Get-WmiObject win32_processor
# Name Description ID
# ---- ----------- --
# CPU0 x64 Family 6 Model 15 Stepp... BFEBFBFF000006FD

补充: 这样的定义可能有个缺点,当我们获取其它WMI对象时,也会根据我们定义的规则显示。


基础实例

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# 0.键入以下内容看到可读形式的完整列表,通过管道符号传递给其他cmdlet并进行使用
Get-Command -Noun Variable | Format-Table -Property Name,Definition -AutoSize -Wrap
# Clear-Variable [-Name] <string[]> [-Include <string[]>] [-Exclude <string[]>] [-Force] [-PassThru] [-Scope <string>] [-WhatIf] [-Confirm] [<CommonParameters>]


# 1.例如如果使用 Out-Host 来强制逐页显示来自于另一个命令的输出(看起是传递的文本)
Get-ChildItem -Path F: | Out-Host -Paging
Get-ChildItem F: | Out-Host -Paging
<SPACE> next page; <CR> next line; Q quit
# 目录: F:\
# Mode LastWriteTime Length Name
# ---- ------------- ------ ----
# d----- 2019/7/11 12:29 BadUSB-code


# 2.如果运行 Get-Location,而当前位置是 C 驱动器的根路径
PS C:\Users\WeiyiGeek> gl
# Path #文本输出是信息摘要,而非 Get-Location 返回的对象的完整表示形式
# ----
# C:\Users\WeiyiGeek
#输出中的标题通过格式化屏幕显示数据的过程添加,可以获取有关 Get-Location 返回的对象信息。
Get-Location | Get-Member -MemberType Property
Get-Location | Get-Member -Name Path
# TypeName: System.Management.Automation.PathInfo
# Name MemberType Definition
# ---- ---------- ----------
# Equals Method bool Equals(System.Object obj)


# 3.如果要执行一些大型查询,可查询一次并将结果存储在变量中以后便使用变量的内容,而无需重复使用一些开销较高的查询。property - 英 [ˈprɒpəti]
$TimeService = Get-Service -Name W32Time
$TimeService | Select-Object -Property Name,Status,ServiceType
# Name Status ServiceType
# ---- ------ -----------
# W32Time Running Win32OwnProcess, Win32ShareProcess


# 4.通过管道停止服务和查看哪些参数接收管道符
# Stop-Service 的 InputObject 参数通过管道按值(按类型)接受 ServiceController 对象 。
Get-Service -Name w32time | Stop-Service
# 通过管道将 w32time 传递到 Get-Member,以确认它是一个字符串。
'w32time' | Get-Member
# TypeName: System.String


# 5.在 PowerShell 中,应始终使用单引号而不是双引号,除非带引号的字符串的内容包含需要扩展为其实际值的变量。通过使用单引号,PowerShell 不必分析引号中包含的内容,因此可稍微加快代码运行速度。
'w32time' | Get-Service
# Status Name DisplayName
# ------ ---- -----------
# Running w32time Windows Time
# 通过管道将 w32time 传递到 Stop-Service,以进行测试
'w32time' | Stop-Service


# 6.按 Stop-Service 的 Name 参数的属性名称创建自定义对象,以测试管道输入。
$CustomObject = [pscustomobject]@{
Name = 'w32time'
}
# CustomObject 变量的内容是 PSCustomObject 对象类型,并且它包含名为 Name 的属性 。
# 如果要在 $CustomObject 变量两边使用引号,则需要使用双引号。 否则,如果使用单引号,则会将文本字符串 $CustomObject 通过管道传递到 Get-Member,而不是传递变量包含的值。
$CustomObject | Get-Member

# 尽管将 $CustomObject 的内容通过管道传递到 Stop-Service cmdlet 会将该内容绑定到 Name 参数,但这次它会按属性名称绑定,而不是按值,因为 $CustomObject 的内容是一个具有名为 Name 的属性的对象 。
# 尝试通过管道将 $CustomObject 传递到 Stop-Service 时会产生错误,因为它不会生成 ServiceController 或 String 对象,并且没有名为 Name 的属性 。
$CustomObject | Stop-Service

# 如果一个命令的输出与另一个命令的管道输入选项不相符,则可以使用 Select-Object 重命名属性,以便正确地配置属性。
# 使用 Select-Object 将 Service 属性重命名为名为 Name 的属性 。
$CustomObject |
Select-Object -Property @{name='Name';expression={$_.Service}} |
Stop-Service

# 7.用一个命令的输出作为另一个命令的输入。
# 首先将几个 Windows 服务的显示名称保存到一个文本文件中。
'Background Intelligent Transfer Service', 'Windows Time' | Out-File -FilePath $env:TEMP\services.txt
# 可以运行命令,在括号中提供所需输出,作为需要输入的命令的参数值。
Stop-Service -DisplayName (Get-Content -Path $env:TEMP\services.txt)

# 8.使用 PowerShellGet 模块中包含的 Find-Module cmdlet,在 PowerShell 库中查找名为 MrToolkit 的模块。并进行安装
Find-Module -Name MrToolkit | Install-Module

备注:

  • 1.分页还会降低 CPU 利用率,因为准备好显示完整页面时,会转为处理 Out-Host 管道中位于前面的 cmdlet 暂停执行,直到输出的下一页可用。
  • 2.并非所有的PS主机都支持 Paging 参数 例如当你尝试在 PowerShell ISE 中使用 Paging 参数时,会看到以下错误:
  • 3.查找管道输入的简单方法安装MrToolkit 模块包含一个名为 Get-MrPipelineInput 的函数;
    1
    2
    3
    4
    5
    6
    7
    # 此 cmdlet 可用于轻松确定接受管道输入的命令参数、接受的对象类型,以及是按值还是按属性名称接受管道输入 。
    Find-Module -Name MrToolkit | Install-Module
    Get-MrPipelineInput -Name Stop-Service
    # ParameterName ParameterType ValueFromPipeline ValueFromPipelineByPropertyName
    # ------------- ------------- ----------------- ---------------
    # InputObject System.ServiceProcess.ServiceController[] True False
    # Name System.String[] True True

0x03 PS 变量

描述:变量Variable在任何一门脚本语言或者说是编程语言中都是存在的,其本质是不相上下的;

  • PS可以创建称为”变量”的命名对象,变量名称可以包含下划线字符任何字母数字字符,且变量名大小写不敏感($a和$A 是同一个变量)
  • 使用变量名称后跟的$字符调用指定变量(与世界上最好的语言相似-你懂的),或者采用${变量名}进行赋值调用,还可以将某些特殊的字符作为变量但是在实际开发中不推荐;
  • 赋值操作符不仅能给一个变量赋值,还可以同时给多个变量赋相同的值,交换变量的值PS只需要两步
  • 变量可以自动存储任何Powershell能够识别的类型信息
  • 采用`或者’’包含变量的都不能进行解析调用变量,只会原样进行输出;
  • 变量会在PS退出或关闭时自动清除

PS变量类型:

  • 自定义变量
  • 自动化变量
  • 环境变量: env:
  • 驱动器变量: varaible:


1.自定义变量

创建变量

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
# 0.创建不同类型的变量(int/String/Boolen/float)
PS > $var=1;$var;$var="String";$var;$var='TRUE';$var;$var=3.14159267;$var
# 1
# String
# TRUE
# 3.14159267

# 1.将当前位置存储在变量 $loc 中
PS > $loc = Get-Location
PS > $loc #键入 $loc 将显示当前位置:

# 2.防止变量名与其他字符串混淆使用${}
PS > $var=" variable"
PS > $var
variable
PS > ${var}
variable


# 3.某些特殊的字符在PS中有特殊的用途,一般不推荐使用这些字符作为变量名。
PS C:\> ${"I"like $}="mossfly" #请把整个变量名后缀用花括号括起来
PS C:\> ${"I"like $}
mossfly


# 4.PS给多个变量同时赋值
PS C:\> $a=$b=$c=123


# 5.交换两个变量的值
PS C:\> $value1=10
PS C:\> $value2=20
PS C:\> $value1,$value2=$value2,$value1


# 6.采用cmdlet声明变量
New-Variable number -Value 100 -Force -Option readonly #变量写保护
New-Variable NUMBER -Value 100 -Force -Option constant -Description "This is my name" #声明常量并且进行描述


# 7.变量不解析
PS C:\> Write-Host the '$HOME' is $home
PS C:\> Write-Host the `$HOME is $home
the $HOME is C:\Users\WeiyiGeek


操作变量

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
# 1.显示使用驱动器变量和环境变量:
Get-ChildItem variable: #PS将变量的相关信息的记录存放在名为variable:的驱动中
Get-ChildItem variable:value* #查找变量
Get-ChildItem env: #使用任何 Windows 进程可用的相同环境变量,其中包括 cmd.exe

# 2.用 env: 驱动器前缀访问环境变量,由于用 env: 驱动器前缀访问环境变量
#例如,cmd.exe 中的 %SystemRoot% 变量包含操作系统的根目录名称
PS > $env:SystemRoot
C:\Windows
PS > $env:JAVA_HOME
Programs\java\jdk

# 3.示例创建一个新的环境变量
$env:LIB_PATH='/usr/local/lib'
PS > $env:WEIYIGEEK=$env:PATH
PS > $env:WEIYIGEEK
# C:\Python27\;C:\Python27\Scripts;

# 4.示例或者改变更新变量PS中是 + 作为评卷符号
PS > $env:WEIYIGEEK=$env:PATH + ";c:\"
PS > $env:WEIYIGEEK
# C:\Python27\;C:\Python27\Scripts;c:\\


# 5.验证一个变量是否存在,仍然可以象验证文件系统那样
PS C:\> -Path variable:value1
True
PS C:\> -Path variable:valueUnkonw
False

# 6.删除变量
PS C:\> -Path variable:value1
True
PS C:\> Remove-Item variable:value1 -Force # 强制删除 del -> Remove-Item
PS C:\> -Path variable:value1
False

WeiyiGeek.环境变量获取显示

WeiyiGeek.环境变量获取显示


2.自动化变量

描述:一旦打开Powershell就会自动加载的变量,并且某些自动化变量只读不能写,一般存放的内容包括:

  • 用户信息:例如用户的根目录$home
  • 配置信息:例如powershell控制台的大小,颜色,背景等。
  • 运行时信息:例如一个函数由谁调用,一个脚本运行的目录等。
1
2
3
4
5
6
7
8
9
10
11
12
13
PS> $HOME
C:\Users\

PS> $currentProcessID=$pid;$currentProcessID
5356

PS> Get-Process -Id $pid
# Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
# ------- ------ ----- ----- ----- ------ -- -----------
# 390 10 30604 33100 172 1.11 5356 powershell

PS> $PROFILE
C:\Users\\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

详细说明-自动变量的列表:

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
$$ : 包含会话所收到的最后一行中的最后一个令牌。

$? : 包含最后一个操作的执行状态。如果最后一个操作成功,则包含 TRUE,失败则包含 FALSE。

$^ : 包含会话所收到的最后一行中的第一个令牌。

$_ : 包含管道对象中的当前对象。在对管道中的每个对象或所选对象执行操作的命令中,可以使用此变量。

$Args : 包含由未声明参数和/或传递给函数、脚本或脚本块的参数值组成的数组。
在创建函数时可以声明参数,方法是使用 param 关键字或在函数名称后添加以圆括号括起、逗号
分隔的参数列表。

$ConsoleFileName : 包含在会话中最近使用的控制台文件 (.psc1) 的路径。在通过 PSConsoleFile 参数启动
Windows PowerShell 或使用 Export-Console cmdlet 将管理单元名称导出到控制台文件
时,将填充此变量。
在使用不带参数的 Export-Console cmdlet 时,它自动更新在会话中最近使用的控制台文件。
可以使用此自动变量确定要更新的文件。

$Error : 包含错误对象的数组,这些对象表示最近的一些错误。最近的错误是该数组中的第一个错误对象
($Error[0])。

$Event :包含一个 PSEventArgs 对象,该对象表示一个正在被处理的事件。
此变量只在事件注册命令(例如 Register-ObjectEvent)的 Action 块内填充。
此变量的值是 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
$host.ui.rawui.setbackgroundcolor(“Red”)。

$Input : 一个枚举数,它包含传递给函数的输入。$Input 变量区分大小写,只能用于函数和脚本块。(脚本块本质上是未命名的函数。)在函数的 Process 块中,$Input 变量包含当前位于管道中的对象。在 Process 块完成后,$Input 的值为 NULL。如果函数没有 Process 块,则 $Input的值可用于 End 块,它包含函数的所有输入。

$LastExitCode : 包含运行的最后一个基于 Windows 的程序的退出代码。

$Matches : $Matches 变量与 -match 和 -not match 运算符一起使用。
将标量输入提交给 -match 或 -notmatch 运算符时,如果检测到匹配,则会返回一个布尔值,并使用由所有匹配字符串值组成的哈希表填充 $Matches 自动变量。

$MyInvocation : 包含一个对象,该对象具有有关当前命令(如脚本、函数或脚本块)的信息。可以使用该对象中的信息(如脚本的路径和文件名 ($myinvocation.mycommand.path) 或函数的名称
($myinvocation.mycommand.name))来标识当前命令。对于查找正在运行的脚本的名称,这非常有用。

$NestedPromptLevel : 包含当前提示级别。值 0 指示原始提示级别。该值在进入嵌套级别时递增,在退出嵌套级别时递减。
例如,在使用 $Host.EnterNestedPrompt 方法时,Windows PowerShell 会出现嵌套命令提示符。在 Windows PowerShell 调试程序中到达断点时,Windows PowerShell 也会出现嵌套命令提示符。在进入嵌套提示时,Windows PowerShell 暂停当前命令,保存执行上下文,并递增
$NestedPromptLevel 变量的值。要创建更多嵌套命令提示符(最多 128 级)或返回到原始命令提示符,请完成命令,或键入”exit”。
$NestedPromptLevel 变量有助于跟踪提示级别。可以创建包含此值的备用 WindowsPowerShell 命令提示符,以使此值始终可见。

$NULL: 包含 NULL 或空值。可以在命令和脚本中使用此变量表示 NULL,而不是使用字符串”NULL”。
如果该字符串转换为非空字符串或非零整数,则可将该字符串解释为 TRUE。

$PID : 包含承载当前 Windows PowerShell 会话的进程的进程标识符 (PID)。

$Profile : 包含当前用户和当前主机应用程序的 Windows PowerShell 配置文件的完整路径。可以在命令
中使用此变量表示配置文件。例如,可以在命令中使用此变量确定是否已创建某个配置文件:
也可以在命令中使用此变量创建配置文件: new-item -type file -path $pshome -force 此外,还可以在命令中使用此变量在记事本中打开配置文件:
notepad $profile

$PSBoundParameters
包含活动参数及其当前值的字典。只有在声明参数的作用域(如脚本或函数)中,
此变量才有值。可以使用此变量显示或更改参数的当前值,也可以将参数值传递给
其他脚本或函数。

基础示例:
function {
param($a, $b)

# Display the parameters in dictionary format.
$psboundparameters

# Call the 1 function with $a and $b.
1 @psboundparameters
}

$PsCmdlet : 包含一个对象,该对象表示正在运行的 cmdlet 或高级函数。
可以在 cmdlet 或函数代码中使用该对象的属性和方法来响应使用的条件。例如,ParameterSetName 属性包含正在使用的参数集的名称,而 ShouldProcess 方法将 WhatIf和 Confirm 参数动态添加到 cmdlet。
有关 $PSCmdlet 自动变量的详细信息,请参阅 about_Functions_Advanced。

$PsCulture : 包含操作系统中当前所用的区域性的名称。区域性确定数字、货币和日期等项的显示格式。这是系统的System.Globalization.CultureInfo.CurrentCulture.Name 属性的值。要获取系统的 System.Globalization.CultureInfo 对象,请使用 Get-Culture cmdlet。

$PSDebugContext : 在调试期间,此变量包含有关调试环境的信息
在其他时间,此变量包含 NULL 值。因此,可以使用此变量指示调试程序是否拥有控制权。填充之后,此变量包含一个具有 Breakpoints 和InvocationInfo 属性的 PsDebugContext 对象。InvocationInfo 属性有多个十分有用的属性,包括 Location 属性。Location 属性指示正在调试的脚本的路径。

$PsHome
包含 Windows PowerShell 的安装目录的完整路径(通常为%windir%System32WindowsPowerShellv1.0)。可以在 Windows PowerShell 文件的路径中使用此变量。例如,下面的命令在概念性帮助主题中搜索”variable”一词:
select-string -pattern variable -path $pshome*.txt

$PSScriptRoot :包含要从中执行脚本模块的目录。通过此变量,脚本可以使用模块路径来访问其他资源。

$PsUICulture
包含操作系统中当前所用的用户界面 (UI) 区域性的名称。UI 区域性确定哪些文本字符串用于用户
界面元素(如菜单和消息)。这是系统的
System.Globalization.CultureInfo.CurrentUICulture.Name 属性的值。要获取系统
的 System.Globalization.CultureInfo 对象,请使用 Get-UICulture cmdlet。

$PsVersionTable
包含一个只读哈希表,该哈希表显示有关在当前会话中运行的 Windows PowerShell 版本的详
细信息。
该表包括下列项:
* CLRVersion: 公共语言运行时 (CLR) 的版本
* BuildVersion: 当前版本的内部版本号
* PSVersion: Windows PowerShell 版本号
* WSManStackVersion: WS-Management 堆栈的版本号
* PSCompatibleVersions: 与当前版本兼容的 Windows PowerShell 版本
* SerializationVersion :序列化方法的版本
* PSRemotingProtocolVersion:Windows PowerShell 远程管理协议的版本

$Pwd : 包含一个路径对象,该对象表示当前目录的完整路径。

$Sender : 包含生成此事件的对象。此变量只在事件注册命令的 Action 块内填充。
此变量的值也可在 Get-Event 返回的 PSEventArgs
(System.Management.Automation.PSEventArgs) 对象的 Sender 属性中找到。

$ShellID : 包含当前 shell 的标识符。

$SourceArgs : 包含表示正在被处理的事件的事件参数的对象。此变量只在事件注册命令的 Action
块内填充。此变量的值也可在 Get-Event 返回的 PSEventArgs
(System.Management.Automation.PSEventArgs) 对象的 SourceArgs 属性中找到。

$SourceEventArgs : 包含一个对象,该对象表示从正在被处理的事件的 EventArgs 中派生出的
第一个事件参数。此变量只在事件注册命令的 Action 块内填充。
此变量的值也可在 Get-Event 返回的 PSEventArgs
(System.Management.Automation.PSEventArgs) 对象的 SourceArgs 属性中找到。

$This : 在定义脚本属性或脚本方法的脚本块中,$This 变量引用要扩展的对象。
$True : 包含 TRUE。可以在命令和脚本中使用此变量表示 TRUE。


3.内置变量

描述: 内置变量包括了PS中的默认的环境变量、以及命令行控制显示变量、以及函数参数的变量。

  • 1) 环境变量: 存在于操作系统之中但是如果环境变量被更新了其它程序也可以更新调用它。

内置变量一览表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1.环境变量
$env

# 2.消息控制变量
$DebugPreference #显示Debug输出: 可选值 [Continue | SilentlyContinue]
$ErrorActionPreference #显示Error输出: 可选值 [Continue | SilentlyContinue]

# 3.函数及参数变量
$global
$local
$function
$input # 管道数据中转变量
$arg # 万能参数变量


# 4.其它变量
$Host # 例如$host.UI.Rawui


基础实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#1.读取特殊的环境变量
PS> ls $env:
PS> $env:windir
C:\Windows
PS> $env:ProgramFiles
C:\Program Files


#2.为了和其它变量保持一致,你可以把它插入到文本中。
PS> "My computer name $env:COMPUTERNAME"
My computer name MYHome--01


#3.创建新的环境变量
PS> $env:Var1="This is my environment variable"
PS> $env:Var2="Hollow, environment variable"
PS> $env:Path+=";C:\\python\\"


#4.环境变量更新生效
# .NET方法[environment]::SetEnvironmentvariable操作可以立刻生效。
PS> [environment]::SetEnvironmentvariable("Path", ";c:\WeiyiGeek", "User")
PS> [environment]::GetEnvironmentvariable("Path", "User")
;c:\WeiyiGeek

备注:

  • 尽管没有要求,但环境变量名称通常使用全部大写字母。


4.驱动器变量

描述:PS中所有不是我们自己的定义的变量都属于驱动器变量(比如环境变量),它的前缀只是提供给我们一个可以访问信息的虚拟驱动器.。

基础实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#0.查看你PS支持的驱动器
PS > Get-PSDrive
# Name Used (GB) Free (GB) Provider Root CurrentLocation
# ---- --------- --------- -------- ---- ---------------
# C 58.24 91.76 FileSystem C:\ Users\WeiyiGeek
# Cert Certificate \
# D 11.76 249.24 FileSystem D:\
# E 19.07 240.93 FileSystem E:\
# Env Environment
# F 88.83 171.46 FileSystem F:\
# Function Function
# G FileSystem G:\
# HKCU Registry HKEY_CURRENT_USER
# HKLM Registry HKEY_LOCAL_MACHINE
# I FileSystem I:\
# Variable Variable
# WSMan WSMan


#1.$后花括号中的路径必须是具体的路径,而不能带返回值。
PS> Invoke-Expression "`${$env:HOMEDRIVE/Powershell/ping.bat}" #反引号"\`"放在$前,会把$解析成普通字符,解释器会继续去解析第二个$
#参数=${C:/Powershell/ping.bat}


5.变量作用域

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

设置单个变量的作用域:

  • $global 全局变量: 在所有的作用域中有效,如果你在脚本或者函数中设置了全局变量,即使脚本和函数都运行结束这个变量也任然有效。
  • $script 脚本变量: 只会在脚本内部有效,包括脚本中的函数,一旦脚本运行结束变量就会被回收。
  • $private 私有变量: 只会在当前作用域有效,不能贯穿到其他作用域。
  • $local 默认变量: 可以省略修饰符,在当前作用域有效,其它作用域只对它有只读权限。


Tips : 利用"."来更改变量的可见性,加强变量可见性限制的优点清空初始化环境,但如果定义的是一个自读的常量的时候这个是不能操作和删除的;

Tips : 本地变量会从全局变量继承值,但是本地变量的更改不会影响全局变量,除非显示制定global;


基础示例:

  • 1) 变量在交换影响

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 1.在脚本里面的变量不影响交互式环境中的变量
    PS E:\WeiyiGeek> $DemoVar="This is a Demo"
    PS E:\WeiyiGeek> .\Demo1.ps1
    # D:\Programs\java\jdk
    PS E:\WeiyiGeek> $DemoVar
    # This is a Demo

    # 2.点"."来运行脚本该符号域Linux中的source命令有异曲同工之妙;
    PS E:\WeiyiGeek> . .\Demo1.ps1
    # D:\Programs\java\jdk
    PS E:\WeiyiGeek> $DemoVar # 脚本中的变量覆盖了$DemoVar变量(关键点)
    # D:\Programs\java\jdk
  • 2) 单个变量作用域实例

    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    # 1.在当前控制台只存在一个作用域,通过修饰符访问,其实访问的是同一个变量:
    PS C:\Users\WeiyiGeek> $var="WeiyiGeek"
    PS C:\Users\WeiyiGeek> $private:var
    # WeiyiGeek
    PS C:\Users\WeiyiGeek> $script:var
    # WeiyiGeek
    PS C:\Users\WeiyiGeek> $global:var
    # WeiyiGeek
    PS C:\Users\WeiyiGeek> $local:var="WeiyiGeek"
    # WeiyiGeek


    # 2.普通变量与Global修饰符之间的区别(在函数中利用Global修饰符来更改普通变量之中)
    $var = "WeiyiGeek"
    function demo1() { echo "Function => $($Var)";$Var = "Function Change";echo "-----$($Var)-----"}
    $var; demo1; $var
    # Function => WeiyiGeek
    # WeiyiGeek
    # -----Function Change-----
    # WeiyiGeek
    function demo2() { $Global:Var = "Function Change $var 变量";$var}
    $var; demo2; $var
    # WeiyiGeek
    # Function Change WeiyiGeek 变量
    # Function Change WeiyiGeek 变量


    # 3.Private修饰符在控制台中的变量保护起来,不让它在函数和脚本中被访问,但他可以被Global修饰符修改;
    function fun() {
    echo "DemoVar=$($DemoVar)";
    $global:DemoVar="This is Function Inner";
    $DemoVar;
    }
    $Private:DemoVar="This is private variable"
    fun;
    $DemoVar
    # 执行结果 (此处是关键点私有变量在函数中不能获取)
    # DemoVar=
    # This is Function Inner
    # This is Function Inner
    $Global:DemoVar="This is global variable"
    fun;
    $DemoVar
    $Private:DemoVar
    # 执行结果 (全局变量可被内部全局变量更改)
    # DemoVar=This is global variable
    # This is Function Inner
    # This is Function Inner
    # This is Function Inner


    # 4.Global修饰符中验证对private修饰符的影响
    function fun() {"DemoVar=$DemoVar";$Global:DemoVar="This is Global";$DemoVar;}
    $Private:DemoVar="this is private"
    $DemoVar
    fun #对后续变量存在影响
    $DemoVar
    # 执行结果
    # this is private
    # DemoVar=this is private
    # This is Global
    # This is Global


    # 5.Local修饰符可以通过$global修饰符修饰的变量
    function fun() {"DemoVar=$DemoVar";$Global:DemoVar="This is Global";$DemoVar;}
    $Local:DemoVar="this is Local"
    $DemoVar
    fun
    $Local:DemoVar
    # 执行结果
    # this is Local
    # DemoVar=this is Local
    # This is Global
    # This is Global


6.变量类型转换

描述: Powershell 默认支持的.NET类型如下:

  • [Byte] [sbyte]
  • [Char]
  • [Bool]
  • [Int] [Int16] [Int32] [Int64]
  • [uint16] [uint32] [uint64]
  • [float]
  • [double]
  • [array]
  • [string]
  • [long]
  • [Decimal]
  • [timespan]
  • [DateTime]
  • [type]
  • [switch]
  • [guid]
  • [nullable]
  • [hashtable]
  • [psobject]
  • [regex]
  • [scriptblock]
  • [single]
  • [Xml]


PS弱类型和强类型
描述: PS给数据分配一个最佳的数据类型也称作“弱类型”,如果一个整数超出了32位整数的上限([int32]::MaxValue),它就会分配一个64位整数的数据类型;同样如果是小数,字符串,日期时间也会分配成为该对应的数据类型,使用时候非常的方便;

  • 1.弱类型的缺点:
  • 有一个变量要存储的是即将拷贝文件的个数,可是在赋值时付了一个字符串,Powershell不会去做过多的判断,它会更新这个变量的类型,并且存储新的数据。
  • 2.强类型的优点:
  • 严谨防止程序异常,不会根据数据进行转换数据类型,
  • 手动地定义类型的一个重要原因是每个特殊的数据类型都有自己的特殊命令和特殊方法,
  • PS中使用它的另一个原因是每一个数据类型都有属于自己的函数;


变量类型查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
PS C:\Users\WeiyiGeek> $var=1024; $var -is [int]
True
PS C:\Users\WeiyiGeek> $var=1024; $var -is [int32]
True
PS C:\Users\WeiyiGeek> $string="weiyigeek"; $string -is [string]
True

# (1) 类型获取
$string.gettype()
# IsPublic IsSerial Name BaseType
# -------- -------- ---- --------
# True True String System.Object

# (2) 对象类型全称
$string.gettype().fullname
# System.String


通过$variableGetType().Name查看和验证PS分配给变量的数据类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
PS C:\Users\WeiyiGeek> $var=1024;$var is Int
Int32
PS C:\Users\WeiyiGeek> $var=1024;$var.GetType().name
Int32
PS C:\Users\WeiyiGeek> (999999999999999).GetType().name
Int64
PS C:\Users\WeiyiGeek> (99999999999999999999).GetType().name
Decimal
PS C:\Users\WeiyiGeek> (3.14).GetType().name
Double
PS C:\Users\WeiyiGeek> (3.14d).GetType().name
Decimal
PS C:\Users\WeiyiGeek> ("String").GetType().name
String
PS C:\Users\WeiyiGeek> (date).GetType().name
DateTime
PS C:\Users\WeiyiGeek> (get-date).GetType().name
DateTime


指定类型定义变量:

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
#1.例如定义一个Byte类型的变量,因为Byte的定义域为[0,255],一旦尝试使用一个不在定义域中的值赋给该变量就会显示一条错误信息。
PS C:\Users\WeiyiGeek> [byte]$b=254
PS C:\Users\WeiyiGeek> $b.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Byte System.ValueType


#2.DateTime类型对象的属性的使用
PS C:\Users\WeiyiGeek> [DateTime]$date="2019-11-27 09:19:20"
PS C:\Users\WeiyiGeek> $date
2019年11月27日 9:19:20
PS C:\Users\WeiyiGeek> $date.DayOfWeek
Wednesday
PS C:\Users\WeiyiGeek> $date.DayOfyear
331
PS C:\Users\WeiyiGeek> $date.AddDays(-10)
2019年11月17日 9:19:20


#3.XML类型对象的使用查询.exe 和 .dll结点
PS > [XML]$xml=(Get-Content .\Demo2.xml)
PS > $xml
# logo
# --------
# logo
PS > $xml.FirstChild
# extensions unextensions
# ---------- ------------
# extensions unextensions
PS > $xml.logo.extensions.e
# .exe
# .dll


变量强弱类型转换
描述:每个变量的都有自己的类型,这个具体的类型存放在PsVariable对象的Attributes[System.Management.Automation.PSVariableAttributeCollection]属性,如果这个Attributes为空,可以给这个变量存放任何类型的数据,PS会自己选择合适的类型。

注意事项: 一旦Attribute属性确定下来就不能随意存储其他类型的数据;

  • 例如给$var存放一个整数,属于弱类型,所以Attributes属性为空,这时还可以给它赋值一个字符串。但是如果给$var增加强类型,存放一个整数,再给它赋值一个其它类型,解释器会自动尝试转换,如果不能转换就会抛出异常。

解决办法:使用 (Get-Variable var).Attributes.Clear() 清空 Attributes此时强类型又转变成为弱类型了;

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
#1.默认申明的变量是弱类型
PS C:\Users\WeiyiGeek> $var=1024
PS C:\Users\WeiyiGeek> (Get-variable var).Attributes
PS C:\Users\WeiyiGeek> $var.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType

PS C:\Users\WeiyiGeek> $var=3.14
PS C:\Users\WeiyiGeek> $var.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Double System.ValueType


#2.强类型转弱类型
PS C:\Users\WeiyiGeek> [Int]$var=1024

PS C:\Users\WeiyiGeek> (Get-variable var).Attributes
TransformNullOptionalParameters TypeId
------------------------------- ------
True System.Management.Automation.ArgumentTypeConverterAttribute

PS C:\Users\WeiyiGeek> $var=3.14;$var
3

PS C:\Users\WeiyiGeek> $var="2019 IS END"
#无法将值“2019 IS END”转换为类型“System.Int32”。错误:“输入字符串的格式不正确。”

PS C:\Users\WeiyiGeek> (Get-variable var).Attributes.clear() # 关键点-强类型清除
PS C:\Users\WeiyiGeek> $var="2019 IS END";$var
2019 IS END


7.变量验证检查

描述:变量PSVariable对象Attributes属性能够存储一些附件条件, 常用的变量内容验证分别为:

  • ValidateLengthAttribute:限制变量的长度
  • ValidateNotNullAttribute:限制变量不能为空
  • ValidateNotNullOrEmptyAttribute:限制变量不等为空,不能为空字符串,不能为空集合
  • ValidatePatternAttribute:限制变量要满足制定的正则表达式
  • ValidateRangeAttribute:限制变量的取值范围
  • ValidateSetAttribute:限制变量的取值集合

基础实例:

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
#1.ValidateLengthAttribute 限制一个字符串变量的长度为位于2-5之间
PS> $var="限制变量"
PS> $condition = New-Object System.Management.Automation.ValidateLengthAttribute -ArgumentList 2,5 #关键点
PS> (Get-Variable var).Attributes.Add($condition)
PS> $var="射雕英雄传" #变量长度位于2-5之间


#2.ValidateNotNullAttribute 例子
PS> $a=123
PS> $con=New-Object System.Management.Automation.ValidateNotNullAttribute
PS> (Get-Variable a).Attributes.Add($con)
PS> $a=$null #无法验证此变量,因为值不是变量 a 的有效值。


#3.ValidateNotNullOrEmptyAttribute 例子 注意@()为一个空数组。
PS> $con=New-Object System.Management.Automation.ValidateNotNullOrEmptyAttribute
PS> (Get-Variable a).Attributes.clear()
PS> (Get-Variable a).Attributes.add($con)
PS> $a=$null


#4.ValidatePatternAttribute 例子利用正则表达式验证Email格式
PS> $email="@mossfly.com"
PS> $con=New-Object System.Management.Automation.ValidatePatternAttribute "[A-Z0-9._%+-][email protected][A-Z0-9.-]+.[A-Z]{2,4}"
PS> (Get-Variable email).Attributes.Add($con)
PS> $email="[email protected]"


#5.ValidateRangeAttribute 例子验证月份1-12
PS> $month=1
PS> (Get-Variable month).Attributes.Add($(New-Object System.Management.Automation.ValidateRangeAttribute -ArgumentList 1,12))
PS> $month=10


0x04 PS 运算操作符

描述: 我们可以把 PS 看作是一个非常强大的计算器,除了支持数学表达式运算符还支持计算机容量单位和HEX进制转换;

计算机容量常用单位: Bit - B - KB - MB - GB - TB - PB

参考地址: https://docs.microsoft.com/zh-cn/powershell/module/microsoft.powershell.core/about/about_arithmetic_operators?view=powershell-7.1


0.运算符及其优先级一览

  • 1) 基础运算符: PowerShell 包含了我们常规使用的基础运算符,用于算数运算等
    1
    2
    3
    4
    5
    6
    - ()
    - +
    - -
    - *
    - /
    - %


  • 2) 比较运算符: PowerShell 包含许多比较运算符,用于比较值或查找与特定模式匹配的值。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 值 & 字符串
    -eq 等于
    -ne 不等于
    -gt 大于
    -ge 大于或等于
    -lt 小于
    -le 小于或等于
    -Like 使用 * 通配符进行匹配
    -NotLike 不使用 * 通配符进行匹配
    -Match 匹配指定的正则表达式
    -NotMatch 不匹配指定的正则表达式
    -Contains 确定集合中是否包含指定的值
    -NotContains 确定集合是否不包含特定值
    -In 确定指定的值是否在集合中
    -NotIn 确定指定的值是否不在集合中
    -Replace 替换指定的值

Tips: 上述列出的所有运算符都不区分大小写,将 c 放置在上次表中列出的运算符之前使其区分大小写。
Tips: -Like 和 -Match 运算符也可能会造成混淆, 其两者的区别是前者与通配符 * 和 ? 结合使用后者与正则表达式结合使用
Tips: PowerShell 版本 3.0 首次引入了“in”比较运算符。换言 -in 执行与 contains 比较运算符相同的测试,不过方向相反。
Tips: 还有一些可用于替换内容的方法如 Replace(),其工作原理类似于替换运算符。但是默认情况下,-Replace 运算符不区分大小写,而 Replace() 方法区分大小写。
Tips: 字符串比较时是模仿忽略大小写并且大小写敏感比较时小写字母小于大写字母。如果需要大小写敏感比较可以使用操作符-ceq, -clt, -cle, -cge,如果要明确的大小写不敏感比较操作符是在默认操作符前加前缀i,即-ieq,-ilt,-ile,-igt,-ige


  • 3) 逻辑运算符: 顾名思义进行逻辑判断(位运算符仅适用于整数类型)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    -and     :和
    -or :或
    -xor :异或
    -not | ! :逆
    -band 位与 5 -band 3 # 1
    -bnot 按位“非” -bnot 5 # -6
    -bor 按位“或” 5 -bor 0x03 # 7
    -bxor 按位“异或” 5 -bxor 3 # 6
    -shl 将位向左移动 3 -shl 2 # 12
    -shr 将位向右移动 16 -shr 2 # 4


  • 4) 布尔转换: 包括位操作符在内的多个操作符返回数字类型的值,PowerShell可以自动将其转换为布尔类型的值,转换规则如下:

    1
    2
    3
    4
    1) 任何非零值将会被转换为$true
    2) 非零长度的字符串将会被转换为$true
    3) 至少有一项的集合会返回$true
    4) 其他对象将会被转换成$true,除非它们为$null
  • 5) 运算符优先级

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    - PowerShell 按以下顺序处理算术运算符:
    # 优先级 运算符 说明
    # 1 () 括号
    # 2 - 对于负数或一元运算符
    # 3 *, /, % 用于乘法和除法
    # 4 +, - 加法和减法
    # 5 -band, -bnot 对于位运算
    # 5 -bor, -bxor 对于位运算
    # 5 -shr, -shl 对于位运算

    - PowerShell 根据优先规则从左到右处理表达式。
    # 表达式 结果
    # 3+6/3*4 11
    # 3+6/(3*4) 3.5
    # (3+6)/3*4 12

    - PowerShell 计算表达式的顺序可能不同于你使用的其他编程和脚本语言
    在此示例中,对表达式 $a++ 进行计算 $b[$a] 。在 $a++ $a 语句中使用之后,计算更改的值, $c[$a++] 但在中使用它之前 $b[$a] 。 中的 $a 变量 $b[$a] 等于 1 ,而不是 0 ; 因此,语句将值赋给 $b[1] ,而不是 $b[0] 。
    $a = 0
    $b = @(1,2)
    $c = @(-1,-2)

    $b[$a] = $c[$a++] # $b[1] = $c[0] ==> -1


1.基础运算符实例

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
# 1.四则运算(交换式)
PS > 3.14*10*10
314
PS > 1+3-(2.4-5)*(7.899-4.444)
12.983
#由 $+圆括号+表达式 构成的变量属于子表达式变量,这样的变量会先计算表达式,然后把表达式的值返回。
PS C:\Users\WeiyiGeek> $((3+9)/3)
4

#2.十六进制转换
PS > 0xA
10
PS > 0xB
11
PS > 0xff
255


#3.自动识别计算机容量单位
PS > 1kb
1024
PS > 1GB
1073741824
PS > 1gb
1073741824
PS > 1gb/1kb
1048576
PS > 1gb/20mb*10kb
524288
PS C:\ps> 80kb*800*30/1gb # 假如一个网站每个页面大小为80kb,统计显示每天的PV操作为800,1个月下来占用的带宽
1.8310546875


2.比较运算符实例

基础示例:

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
50
51
52
53
54
55
56
57
58
59
60
# 1.首字母大写的“PowerShell”等效于使用等于比较运算符的小写的“powershell”。
'PowerShell' -eq 'powershell' # True
'PowerShell' -ceq 'powershell' # False 区别大小写

# 2.不等于比较运算符反转条件。
'PowerShell' -ne 'powershell'

# 3.大于、大于或等于、小于和小于或等于均可用于字符串或数值。
5 -gt 5 # False
5 -ge 5 # True
# 针对于计算机容量进行比较
PS > 1gb -lt 1gb+1
True
PS > 1gb -lt 1gb-1
False

# 4.执行"like"匹配 -Like 与通配符 * 和 ? 结合使用
'PowerShell' -like '*shell' # True
'PowerShell' -notLike 'weiyigeek' # True


# 5.使用正则表达式执行匹配 -Match
'PowerShell' -match '^*.shell$'
'[email protected]' -match '@' # 貌似只要有一个字符串匹配即返回True
# True
'[email protected]' -match 'ji'
# False
'[email protected]' -notMatch 'weiye'
# True

# 6.列表包含或者不包含指定`$Numbers`变量,-NotContains 反转逻辑以查看 $Numbers 变量是否不包含值。
(3,4,5) -contains 2
$Numbers = 1..10 # 使用范围运算符将数字 1 到 10 存储在变量中
$Numbers -contains 15 # False
$Numbers -notcontains 15 # True


# 7.它用于确定某个值是否“位于”数组中。
# $Numbers 变量是数组,因为它包含多个值。
# 与 -contains 运算符一样,not 反转 -in 运算符的逻辑。
15 -in $Numbers # False
10 -in $Numbers # True
10 -notin $Numbers # False


# 8.-replace 运算符 它用于替换内容
# 如果指定一个值,则会将该值替换为空值。
'PowerShell' -replace 'Shell' # Power
# 如果要将值替换为其他值,请在要替换的模式之后指定新值。
'my website address is hTTp://wwww.weiyigeek.top' -replace 'http','https'
my website address is https://wwww.weiyigeek.top
# 如果要区分大小写进行替换请采用 Replace() 方法。
'my website address is hTTp://wwww.weiyigeek.top'.Replace('http','https')
my website address is hTTp://wwww.weiyigeek.top


# 9.比较数组和集合
PS WeiyiGeek> 1,2,3,4,3,2,1 -eq 3
3
3


3.逻辑运算符实例

基础示例:

1
2
3
4
5
6
7
8
9
10
11
12
# 1.求反运算符为-not 但是像高级语言一样”! “ 也支持求反
PS > $a= 2 -eq 3
PS > $a
False
PS > -not $a
True
PS > !($a)
True
PS > $true -xor $false
True
PS > $true -xor $true
False