PowerShell 入门指南

news/2025/2/12 19:59:43/

https://learn.microsoft.com/zh-cn/powershell/scripting/lang-spec/chapter-01?view=powershell-7.3

From:https://zhuanlan.zhihu.com/p/76708298

如何使用 PowerShell 文档:https://learn.microsoft.com/zh-cn/powershell/scripting/how-to-use-docs?view=powershell-7.3
关于主题 (涵盖有关 PowerShell 的一系列概念):https://learn.microsoft.com/zh-cn/powershell/module/microsoft.powershell.core/about/about?view=powershell-7.3

Windows PowerShell 语言规范:https://learn.microsoft.com/zh-cn/powershell/scripting/lang-spec/chapter-01?view=powershell-7.3

1、powershell 概述

特点

  • 破天荒的方便
    诸如存储计算中 GB, MB, KB 单位等;数组声明中的 1..n 和下标为 -1 的处理;还有所见即所得,通俗易懂的 动词+名词 结构的 Cmdlet ( PowerShell命令的称呼 )。 还有自带的文档支持也很是丰富,只要熟练掌握 Get-Help 命令,其他命令的用法均可通过 Get-Help 查到
  • 面向对象
    良心啊,这个语言竟然是面向对象的 与面向过程相比,面向对象更方便更容易描述现实世界,也算赶上了时髦。
  • 依托 .NET
    正所谓大树下面好乘凉,PowerShell 绑上 .NET 这个大款了,借助 .NET 平台强大的类库,几乎让一切都成为可能。
  • 强大的兼容性
    完全兼容 Windows 平台上其它调用,如可执行文件(exe),批处理 bat / cmd 和 VBscript 等, 在 Linux 和 macOS 上也能很好地工作。
  • 基于平台的可扩展性
    微软有个优点,与应用相比,它更喜欢做平台。PowerShell 早已变成一个平台,在 PowerShell 刚发布的第二年,微软的 System Center Operations Manager 和 SharePoint 就提供了针对该平台的组件,后来的活动目录,Hyper-V,Windows Azure,Office 365就更不用说了。除了微软,亚马逊的云平台管理,Dell的out-of-hand 管理,也都提供了基于 PowerShell 的管理组件。PowerShell 俨然变成了一个标准,变成了一个规范。

PowerShell 是一种脚本语言。"PowerShell变量、cmdlet、模块、提供者(.NET 程序集)" 构成了强大的PowerShell工具,帮助完成工作。

  • 变量:表示 特定值,便于参考和重复使用。
  • cmdlet:是一个内置的 PowerShell 命令( Get 命令 cmdlet 是最常见的一个,有多种用途,如检索现有设置或通过 get-help cmdlet 寻求帮助)。【Windows PowerShell 和 Linux 中的 BASH shell 之间的主要区别之一是 Microsoft 为 PowerShell 开发了 cmdlet(command-let)。它们 cmdlet 本质上是完成有时更复杂任务的单个命令,类似于函数。这些 cmdlet 采用动词名词的形式,例如 get-help 】
  • 模块:包含多个对象的包,如 cmdlet、变量等。
  • 提供者(.NET 程序集):是一个 .NET程序,它提供对信息的访问,如注册表、别名、函数、变量、文件系统和整个操作系统环境。

PowerShell 是一种跨平台的任务自动化解决方案,由命令行 shell、脚本语言和配置管理框架组成。 PowerShell 在 Windows、Linux 和 macOS 上运行。

PowerShell 是新式命令 shell,其中包括其他常用 shell 的最佳功能。 与大多数仅接受并返回文本的 shell 不同,PowerShell 接受并返回 .NET 对象。 shell 包括以下功能:

  • 可靠的命令行历史记录
  • Tab 自动补全和命令预测(请参阅 about_PSReadLine)
  • 支持命令和参数别名
  • 用于链接命令的管道
  • 控制台内帮助系统,类似于 Unix man 页面

作为一种脚本语言,PowerShell 通常用于自动执行系统管理。 它还用于经常在 CI/CD 环境中生成、测试和部署解决方案。 PowerShell 是在 .NET 公共语言运行时 (CLR) 上构建的。 所有输入和输出都是 .NET 对象。 无需分析文本输出即可从输出中提取信息。 PowerShell 脚本语言包含以下功能:

  • 可通过函数、类、脚本和模块进行扩展
  • 便于输出的可扩展格式系统
  • 用于创建动态类型的可扩展类型系统
  • 对常用数据格式(例如 CSV、JSON 和 XML)的内置支持

入门

不熟悉 PowerShell 且不知道从何处开始? 了解以下资源。

  • 安装 PowerShell
  • PowerShell 点滴教程
  • PowerShell 101
  • Microsoft Virtual Academy 视频
  • PowerShell 学习模块

了解如何在不同的方案和不同的平台上使用 PowerShell。

  • 通过 SSH 进行 PowerShell 远程处理
  • Azure PowerShell 入门
  • 使用 DSC 生成 CI/CD 管道
  • 管理 Microsoft Exchange

建议的内容

  • 简介 - PowerShell

    本文是对 Mike F Robbins 所著的“PowerShell 101”一书的简介。

  • 探索 PowerShell - PowerShell

    了解 PowerShell 是什么,并了解一些可用于进一步探索 PowerShell 的基本命令。

  • 开始使用 PowerShell - PowerShell

    在哪里可以找到 PowerShell 以及如何为新用户启动它。

  • PowerShell 命令是什么? - PowerShell

    PowerShell 命令称为 cmdlet(读作 command-let)

  • 帮助系统 - PowerShell

    掌握帮助系统是成功使用 PowerShell 的关键。

  • 优化 shell 体验 - PowerShell

    本文概述了可帮助用户改进其用户体验的 shell 功能。

  • 如何使用 PowerShell 文档 - PowerShell

    本文介绍如何使用此站点的功能,包括搜索筛选和版本选择。

  • 自定义 shell 环境 - PowerShell

    本文介绍如何使用配置文件保存首选 PowerShell 设置并优化 shell 体验。

命令行使用 powershell

启动 powershell

1、cmd 中执行 powershell,切换为 powershell
2、开始菜单中输入 powershell 启动 powershell
3、开始菜单 ---- 附件--- -powershell 启动

get-help

启动成功后,不知道干啥,可以直接输入 help 查看帮助。

输入 get-help 查看帮助。Microsoft 为 get-help 这个 cmdlet 设置了别名 help,以便和 Linux 命令 man 完成相同的操作

Get-Command 查看 powershell 支持的命令

CommandType列,表示命令类型,Alias是别名、Cmdlet是powershell格式的命令、Function是函数、Name列,就是命令
Definition列,命令功能的简单描述

支持通配符

Get-Command *process*

Get-Help Get-Process -full    //得到 Get-Process 的详细用法以及使用范例

也可以通过 poweshell ise 右面 "命令 侧边框" 查看所有命令, 并且还可以筛选你想要的命令!

process 进程

执行:get-command *process

get-process 查找进程
stop-process 杀除进程

示例命令:get-process -name *notepad*
示例命令:stop-process -id pid

安装 appx

1、Add-AppxPackage

用途:安装一个appx程序包。
语法:Add-AppxPackage [–DependencyPath <依赖的包路径>]
举例:Add-AppxPackage D:\AppxSource\MyAppx.appx

2、Add-AppxProvisionedPackage

用途:设置应用程序到计算机。
举例:Add-AppxProvisionedPackage -Online -FolderPath D:\Appx
说明:将应用程序设置到计算机,所有的用户都将默认安装此APPX包。

3、Get-AppxPackage

用途:获取应用程序清单
举例:
Get-AppxPackage -AllUsers #获取所有用户安装的APPX包
Get-AppxPackage -Name Package1 -User domain\username #获取指定域下面的指定用户的指定包

4、Get-AppxPackageManifest

用途:获取应用程序包的详细信息
举例:
Get-AppxPackageManifest -Package Package1

5、Remove-AppxPackage

用途:卸载一个appx程序包。
语法:Remove-AppxPackage <包名>
举例:Remove-AppxPackage MyAppx

6、Remove-AppxProvisionedPackage

用途:移除计算机对包的设置
举例:Remove-AppxProvisionedPackage -Online -PackageName MyAppxPkg
说明:移除之后,新建用户不再安装此包,但已经安装此包的用户,不会被删除。

如何熟悉 powershell 命令

看一下 powershell 的命名规则,可以看出来命令都包含一个动词和一个名词,由连字符分隔。比如关机命令Stop-Computer 在ise中还可看相应的参数!

PowerShell 别名(Alias)

使用别名:https://learn.microsoft.com/zh-cn/powershell/scripting/learn/shell/using-aliases?view=powershell-7.2

查看所有别名:Get-Alias

查看 某个命令的 别名:Get-Alias -Definition Get-ChildItem

若要获取单个别名的定义,请使用 Name 参数:Get-Alias -Name gci

PowerShell 具有多个别名,使 UNIX 和 cmd.exe 用户可以在 Windows 中使用熟悉的命令。 下表显示了常用命令、相关的 PowerShell cmdlet 和 PowerShell 别名:

cmd.exe命令UNIX 命令PowerShell CmdletPowerShell 别名
cdchdircdSet-Locationslcdchdir
clsclearClear-Hostcls clear
copycpCopy-Itemcpicpcopy
deleraserdrmdirrmRemove-Itemrideleraserdrmrmdir
dirlsGet-ChildItemgcidirls
echoechoWrite-Outputwrite echo
mdmkdirNew-Itemni
movemvMove-Itemmimovemi
popdpopdPop-Locationpopd
pwdGet-Locationglpwd
pushdpushdPush-Locationpushd
renmvRename-Itemrniren
typecatGet-Contentgccattype

一些 总结

1、$PSVersionTable :查看PowerShell的版本信息。

2、PowerShell 界面:

  • 开始界面搜索 “PowerShell” ,点击 “PowerShell.exe” 或者 “PowerShell ISE”。
  • cmd 命令界面输入 “PowerShell”。

3、PowerShell 快捷键

  • Alt + F7 :清除命令等历史记录,相当于 cls 命令。
  • Ctrl + PgUp :上翻页。
  • Ctrl + PgDn :下翻页。
  • 上下箭头键 :切换命令行等历史记录。
  • 左/右箭头键 :左右移动光标。
  • Ctrl + Home :
  • Ctrl + End :
  • ESC:清空当前命令行。
  • Tab :自动补齐并选择补齐命令或文件名。
  • Enter :执行当前的命令。
  • Ctrl + C :取消正在执行等命令。
  • Backspace :从右删除命令行字符。
  • F2 :自动补充历史命令到指定字符。
  • F4 :删除命令行至光标右边指定等字符处。
  • F7 :对话框显示命令行历史记录。
  • F8 :检索包含指定字符的命令行历史记录。
  • F9 :根据命令行等历史记录编号选择命令,历史记录编号可以通过 F7 查看。

4、PowerShell 的管道

  • PowerShell 的管道是基于对象的,和Linux Shell 基于文本不同。
  • 管道:前一个命令的输出作为下一个命令的输入。
  • 重定向:
    • “>” 表示输出到某文件,覆盖文件原有的内容,如果文件不存在则自动创建。
    • “>>” 表示添加到某文件内容的结尾。

5、PowerShell 的运算符

  • 支持四则运算
  • 支持数值的进制转换
  • 支持逻辑运算

6、PowerShell 使用外部命令

  • PowerShell 是 cmd 的扩展,cmd 的命令在 PowerShell 中基本都可以使用执行。

  • netstat -ano :查看端口信息,同 cmd 命令。

  • ipconfig :查看网络配置信息,同 cmd 命令。

  • route print :打印路由信息,同 cmd 命令。

  • start :打开应用程序。

  • notepad :打开文本编辑器,同 cmd 命令。

  • calc :打开计算器,同 cmd 命令。

  • &"command" :打开PowerShell 外部命令,PowerShell 专用。

  • $env:path :输出 path 环境变量的内容。

  • $env:path = $env:path + "dir_path" :临时添加 path 环境变量。

7、PowerShell 的命令集

  • Get-Command :获取 PowerShell 所有的命令。
  • PowerShell 的命令类型有 Alias 、Function 、Cmdlet 三种。
  • Alias :别名。
  • Function :函数。
  • Cmdlet :PowerShell 内部命令,以动-名词的格式命名。
  • Get-Help :获取命令的帮助信息。
  • Get-process :获取系统的进程信息。
  • Get-Alias :获取别名对应的命令信息。
  • Get-History :获取命令行使用命令的历史信息。
  • Get-Date:获取当前的日期时间信息。

8、PowerShell 的别名

  • Get-Help :获取命令的帮助信息,包含命令的别名信息。
  • Get-Alias :获取别名对应的命令信息。
  • Get-Alias -name "ls" :获取别名是“ls”的PowerShell命令。
  • Get-Alias | where {$_.definition.startswith("Remove")} :获取以“Remove”开头命令的别名信息。
  • Get-Alias | Group-Object definition | sort -descending Count :根据命令别名的个数倒序显示命令及其别名。

9、自定义别名

  • Set-Alias :定义命令的别名。
    • Set-Alias -name txt -value notepad
    • -name :指定命令的别名。
    • -value :指定需要定义别名的命令。
  • del alias:txt :删除别名“txt”。
  • Export-Alias :导出别名,Export-Alias demo.ps1
  • Import-Alias :导入别名,Import-Alias demo.ps1,不成功可以使用“-force”参数进行强制导入。

10、PowerShell 变量

  • PowerShell 使用 $ 符号来定义变量,不需要指定变量类型。
  • $var_name
  • $var_name = value
  • PowerShell 对大小写不敏感。
  • 定义变量使用特别的变量名需要使用花括号将变量名括起来。
  • 变量的赋值可以是别名、命令、表达式等。
  • 多个变量可以同时赋值。

11、变量操作

  • 两个变量的值互换:
            $tempt = $var1
            $var_1 = $var_2
            $var_2 = $tempt
            或者
            $var_1,$var_2 = $var_2,$var_1

  • ls variable:: 查看当前使用的变量。

  • ls variable:var_name: 查看变量 $var_name 的信息,支持正则表达式。

  • Test-Path variable:var_name:查看变量 $var_name 是否存在,返回布尔值。

  • del variable:var_name:删除指定的变量。

  • Clear-Variable :清除指定的变量。

  • Remove-Variable:删除指定的变量。

12、PowerShell 自动化变量

  • 自动化变量是由 PowerShell 自己创建和维护的,一些变量是只读而不能写入的。
  • $home :用户根目录路径。
  • $pid :当前界面进程的ID。
  • $$ :上一个运行的命令。
  • $? :上一个命令运行的状态,返回布尔值。
  • $_ :当前变量。
  • $null :空值,空变量。

13、PowerShell 环境变量

  • ls env: :查看环境变量信息。
  • env:var_name :显示指定的环境变量信息,支持正则表达式。
  • env:varname=value :创建添加一个环境变量。
  • del env:var_name :删除指定的环境变量,支持正则表达式。
  • [environment]::setenvironmentvariable("PATH","D:\","User"):设置用户的 $PATH 变量,永久生效。
  • [environment]::getenvironmentvariable("PATH","User"):获取环境变量 $PATH 。

14、PowerShell 脚本执行策略

  • PowerShell 脚本以 .ps1 后缀。
  • Get-Executionpolicy :查看命令行的脚本执行权限,返回 Restricted 表示禁止。
  • Set-Executionpolicy RemoteSigned :允许命令行运行 PowerShell 脚本。

15、PowerShell 脚本调用

  • 切换到桌面:cd desktop
  • & “PowerShell_script_path” :执行脚本。
  • .bat 脚本文件调用PowerShell 脚本:powershell "& 'PowerShell_script_path'"

总结 2

1. 进入Powershell环境
        开始--运行--powershell
        开始--运行--cmd--powershell
        不同系统内置的powershell系统版本是不一样的
        查看版本:$psversiontable

2. powershell功能特别强大,使用方便
        命令命名方式简单:动词+名词
        >get-service 获取系统服务
        >get-help get-service 查看命令的帮助信息
        
        面向对象
        绑定了.net开发平台
        强大的兼容性,与cmd、vbs可直接调用
        扩展性:可管理AD域、虚拟化等产品

3. 自定义powershell控制台
        右击标题栏--属性
        编辑模式--快捷/普通

4. powershell快捷键
        ALT+F7         清除命令的历史记录
        Pgup Pgdown    翻页
        Enter          执行当前命令
        End            光标移至末尾
        Del            删除光标后的命令字符
        ESC            清空当前命令行
        F2             自动补充历史命令至指定位置
        F4             删除命令行至光标右边指定的字符处
        F7             对话框显示命令行历史记录
        F8             检索包含指定字符的命令行历史记录
        F9             根据编号选择历史命令
        上/下          翻看历史命令
        左/右          左右移动光标
        Home           移至命令行最左端
        Backspace      从右侧删除命令行字符
        CTRL+C         取消命令执行
        Tab            自动补齐命令或文件名

5. 管道和重定向
        >ls | Format-Table mode,name
        >ls | Format-Table mode,name > 1.txt
        >ls | Format-Table mode,name >> 1.txt
        >type 1.txt

6. Powershell数学运算符:+ - * / %

7. 执行外部命令
        命令程序必须在system 32目录中
        如果命令程序不在目录中,需要将文件复制到目录中或修改环境变量
        ipconfig
        netstat -na
        notepad        

8. Powershell命令集
        查看命令集:get-command
        命令类型:Alias 别名
        Function 函数
        Cmdlet 内部命令
        powershell命令是cmd命令的扩展,一般情况下,cmd命令在powershell中是可以使用
        查看命令的帮助信息:get-help get-command
        查看系统进程:get-process
        查看当前会话的别名:get-alias
        查看历史命令:get-history
        查看日期:get-date

9. Powershell别名使用
        get-help get-command
        get-childitem命令的别名 dir ls 显示文件
        get-alias -name ls 查看是谁的别名
        查询以remove开头的别名
        Get-Alias | where {$_.definition.startswith("Remove")}
        对分组显示的所有别名按个数以降序进行排列
        Get-Alias | Group-Object Definition |sort -Descending Count

10. 自定义别名
        自定义别名:set-alias -name pad -value .\notepad
        删除别名:del alias:pad
        导出别名:export-alias demo.ps1
        强制导入别名:import-alias -force demo.ps1

11. 变量
        定义变量:$name="xiaoming"
        $age=25
        输出变量:$name
        变量对大定是不区分的:$a和$A是同一个变量
        定义特殊名称的变量:${i am a”()}=100
        定义变量时可以跟表达式:$n=(7*6+8)/2
        也可以跟命令:$n=ls
        同时给多个变量赋值:$sum1=$sum2=200

12. 变量的操作
        改变变量的值:$sum1=10
        $sum2=20
        $temp=$sum1
        $sum1=$sum2
        $sum2=$temp
        $sum1,$sum2
        查看当前使用的变量有哪些:ls variable:
        查看指定的变量:ls variable:su*
        查看变量是否存在:test-path variable:sum1
        删除变量:del variable:sum1
        Remove-Variable sum2

13. 自动变量(启动时会自加载,只能读不能改)
        $home 当前用户根目录
        $pid 当前进程号
        $$ 上一个命令
        $? 上一个命令是否执行成功
        $null 空变量

14. 环境变量
        查看环境变量:ls env:
        查看环境变量的值:ls env:os
        查看系统变量的值:$env:Path
        添加环境变量:$env:apollo_test="TEST_VALUE" 影响空间范围: 仅在此窗口。适合场景: 临时修改环境变量
        图形化设置环境变量 ----永久生效
        del env:name 删除环境变量
        [environment]::setenvironment variable("PATH";"d:\";"user") 修改
        [environment]::getenvironment variable("PATH";"d:\";) 显示

15. 脚本执行策略的设置

(1)写一个.bat的脚本程序
        echo hello world!!

(2)写一个.ps1的脚本程序
$sum=46
Switch($sum)
{
    {$_ -lt 50 -and $_ -gt 40} {"40 < sum < 50"}
    {$_ -eq 50} {"sum 等于 50"}
    {$_ -gt 50} {"sum 大于 50"}
}

16. 与其他脚本的相互调用
        (1)在cmd中运行powershell脚本:C:\>powershell .\demo.ps1
        (2)如何Powershell中运行.bat脚本
                查看策略:Get-ExecutionPolicy
                Restricted 禁止
                Get-help set-ExecutionPolicy
                Set-ExecutionPolicy RemoteSigned 允许策略
                C:\Users\ASUS-PC\Desktop>.\demo.bat
        (3)如何在powershell中运行vbs脚本。将vbs脚本拖拽到powershell环境中

17. 条件操作符
        算术运算符:-eq -nq -gt -lt -contains -notcontains
        89 -eq 99
        1gb -gt 1mb
        (1,2,3) -contains 1
        (1,2,3) -notcontains 1
        逻辑运算符:-and -or -not
        1,5,9,0 -ne 0 不显示等于0的数字
        1,5,9,0 -eq 0 显示等于0的数字
        1,5,9,0 -contains 0 判断是否包含0

18. 条件判断:if语句
        $num=200
        if ($num -gt 90) {"num 大于 90"}
        if ($num -lt 90) {"num 小于 90"}
        if ($num -eq 100) {"num 等于 90"}
        修改为:
        $num=80
        if ($num -gt 90) {"1"} elseif ($num -lt 90) {"0"} else {90}

19. 条件判断:swith语句
        举例1:
        $sum=56
        {$_ -lt 50} {"此数小于50"}
        {$_ -eq 50} {"此数等于50"} 或 50 {"此数等于50"}
        {$_ -gt 50} {"此数大于50"}
        举例2:
        {$_ -lt 50 -and $_ -gt 40} {"此数小于50大于40"}
        {$_ -eq 50} {"此数等于50"}

20. 循环语句:foreach语句
        $arr=1..10
        foreach ($n in $arr)
        {
            $n*$n/2
        }

21. 循环语句:while语句
        $num=15
        while ($num -gt 10)
        {
            $num
            $num=$num-1
        }
        
        echo "*********************"
        
        do 
        {
            $num
        }
        while($num -gt 10)

22. Break(跳出整个循环,不再执行)和continue(只跳出满足条件的循环)关键字使用

23. 循环语句:for语句
$num=10
for ($i=1;$i -le 100;$i++){$num=$num+$i}
$num

24. 循环语句:switch语句
        $num=1..100
        Switch ($num)
        {
            {($_%2) -eq 0} {"($_) 是偶数"}
            {($_%2) -eq 1} {"($_) 是奇数"}
        }

25. 数组的创建
        $arr=1..10
        $arr.GetType()
        $arr

26. 访问数组
        $arr+="AA" 增加元素到数组
        $arr[] 通过索引读取元素
        $arr.Count 统计元素个数
        $arr 显示数据中的元素

27. 自定义函数及调用
(1)不指定参数
        function myping
        {
            ping www.baidu.com   
        }
        myping

(2)传递参数
        function myping($site){ ping $site }
        myping www.baidu.com
        function myping($name,$age)
        { 
            $content="I am $name,and I am $age years old!"
            write-host $content 
        }
        myping "xiaoming" 25

28. powershell函数返回值
        function add_1($num1,$num2)
        {
            $sum=$num1+$num2
            return $sum
        }
        add_1 3 4
        
        # 查看返回值类型
        $sum.GetType().fullname
        add_1 3.1 4
        
        # 返回多个参数的返回值类型
        function add_2($num1,$num2,$sum3)
        {
            $value=$num1,$num2,$sum3
            $value.GetType().fullname
            $value[2]
        }
        add_2 3 4 9

29. powershell定义文本
        打印一句话: 'hello world'
        打印一句话带变量: "hello world! $(Get-Date)"
        支持表达式:"hello world! $(5*9)"
        单引号: '“hello world!” $(5*9)'
        转义字符:"hello world!`"$(5*9)`" "
        `n 换行符
        `r 回车符
        `t 制表符
        `b 退格符

30. powershell实现用户交互
        $input=read-host "请输入你的姓名:"
        "你好,你输入的姓名是:$input"

31. powershell格式化字符串
        $name="xiaoming"
        $body="strong"
        "my name is $name,i am $age years old,and my body is $body"
        name="xiaoming"
        "my name is {0},i am {1} years old,and my body is {2}" -f $name,$age,$body
        "my name is {0},i am {1} years old,and my body is {2},{3}" -f $name,$age,$body,(3*6)

32. String对象方法
        分隔字符串
        $str="c:\windows\system32\demo.txt"
        $str.Split("\") 分隔字符
        $str.Split("\").GetType() 查看类型
        $str[0,1] 数组索引
        $str.EndsWith("txt") 是否以txt结尾
        $str.cont("txt") 是否包含txt字符串
        $str.CompareTo("xxy") 字符串是否相等
        $str.indexof("w") 字符w的位置
        $str.Insert(3,"xxxx") 插入字符
        $str.Replace("c","88888") 替换

分割操作符 -split 可以通过指定分隔符,分割指定的字符串。
$temp = "This分隔符is分隔符a分隔符test" -split "分隔符"
$temp
$temp[0]

join 操作符可以将多个文本块合并成一个
 "Scott","Matteson" -join " "

总结图

2、GUI 编辑工具 

Windows PowerShell ISE

Windows PowerShell 集成脚本环境 (ISE) 是 Windows PowerShell 的主机应用程序。 在 ISE 中可以图形用户界面来 运行命令并编写、测试和调试PowerShell 脚本。 ISE 提供多行编辑、Tab 自动补全、语法颜色设置、选择性执行、上下文相关帮助以及对从右到左语言的支持。在 ISE 中调试脚本时,可以右键单击编辑窗格中的代码行来设置断点。同时还有一个方便的工具栏功能区和右边列出的命令参考,你可以点击它来插入PowerShell命令以及了解它们的更多信息。

启动 Windows PowerShell ISE

单击“开始” ,选择“Windows PowerShell” ,然后单击“Windows PowerShell ISE” 。 或者,可以在任何命令 shell 或“运行”框中键入 powershell_ise.exe

默认的可执行文件是64位的,但是为了向后兼容的目的,可以在这个文件夹中找到每个人的32位PowerShell版本。

Windows PowerShell ISE:https://learn.microsoft.com/zh-cn/powershell/scripting/windows-powershell/ise/introducing-the-windows-powershell-ise?view=powershell-7.3

在 Windows PowerShell ISE 中编写和运行脚本

:https://learn.microsoft.com/zh-cn/powershell/scripting/windows-powershell/ise/how-to-write-and-run-scripts-in-the-windows-powershell-ise?view=powershell-7.3

使用示例:

Get-Date

断点

运行一个新创建的PowerShell脚本,如果该脚本包含bug,可能会产生意想不到的后果。一种保护自己的方法是在脚本的战略位置插入断点。这样一来,你就可以在处理整个脚本之前,确保该脚本是按预期工作的。

插入断点的最简单方法是按行号插入。例如,要在脚本的第10行插入一个断点,你可以使用这样的命令。

Set-PSBreakpoint -Script C:\Scripts\Script.ps1 -Line 10

你也可以将断点绑定到一个变量上。因此,如果你想让你的脚本在a$的内容发生变化时中断,你可以使用类似这样的命令。

Set-PSBreakpoint -Script C:\scripts\Script.ps1 -variables a

可以在 PSBreakpoint 中使用一些动词,包括Get, Enable, Disable和Remove。

在调试一个脚本时,有时可能需要逐行运行该脚本。为此,你可以使用PowerShell ISE中的Stepping过程,使脚本在每一行之后都暂停,而不管是否存在断点。利用下表中列出的功能。

示例

visual studio code

推荐使用 Visual Studio Code(以下简称 VSC),VSC提供了 PS1 的自动补全(安装插件)、语法高亮、自动缩进、格式化代码、断点调试等功能。

ISE 可以通过 侧边框 搜索、查看 cmdlet 的说明。

可以 vsc 编写代码, ISE 搜索、查看使用帮助

PowerShell Studio

官网地址

  • https://www.sapien.com/   现在好像是拒绝访问!
  • 文档地址:https://info.sapien.com/manuals/powershell_studio/index.html 可以访问

PowerShell Studio 是专业的开发环境,官网在这里,简单看看他的一张截图:

可以看到软件是非常专业的,非常的方便编写与管理你的代码。

软件功能

  • 直观地创建 PowerShell GUI 工具
  • 将脚本转换为可执行 (.exe) 文件
  • 创建 MSI 安装程序
  • 从现有函数或帮助文件创建模块
  • 使用函数生成器创建高级函数
  • 使用 PowerShell 创建 Windows 服务
  • 监视脚本性能和内存使用情况
  • 使用远程计算机中的 cmdlet 编写脚本
  • 具有 Git 集成的通用版本控制
  • 集成PowerShell控制台(32位和64位)
  • 全面的脚本调试器
  • 远程调试
  • 多文件和模块调试
  • 32 位和 64 位 PowerShell 集成
  • 内置的PowerShell帮助
  • 支持 Windows PowerShell 和 PowerShell 7
  • 代码格式
  • 使用文件恢复功能防止工作丢失。

安装激活教程。下载地址:https://www.huajclub.com/17566.html

链接: https://pan.baidu.com/s/1TF8rhbX1M1fL6CkcE5fwzA 提取码: xrg9

1.安装应用程序
2.使用keyfilemaker生成许可证文件
3.使用防火墙阻止程序或将以下内容添加到HOSTS文件中:
127.0.0.1 www.sapien.com
4.在应用程序中使用文件激活方法,并为其提供生成的许可证文件。

visual studio

Visual Studio 同样也能达到这样的效果,那么大家可以自行选择。

安装插件:https://marketplace.visualstudio.com/items?itemName=AdamRDriscoll.PowerShellToolsforVisualStudio2015

https://marketplace.visualstudio.com/items?itemName=AdamRDriscoll.PowerShellToolsforVisualStudio2015

3、编写 powershell 脚本

powershell 的脚本文件扩展名是 ps1。PowerShell脚本语言的操作方式是执行一系列的PowerShell命令(或单个命令),每个命令出现在单独的一行。为了使文本文件被当作PowerShell脚本,其文件名需要以.PS1结尾,以暗示PowerShell扩展名。

PowerShell 是一个强类型 ( 变量一旦定义,其本身类型不可改变就是强类型,反之就是弱类型) 的动态脚本语言,支持面向对象,支持调用系统API和 .NET 库。 受到了 Python, Ksh, Perl, C#, CL, DCL, SQL, Tcl, Tk, Chef, Puppet 等语言的影响,结合了以上语言的部分特性。PowerShell 代码的外观和操作方式与C#的相似程度最高,不过也有它自己的特色。

powershell 基础

关于空白字符

与 Python 等语言不同,PowerShell 的解释器不会考虑代码中的空格或制表符(这些字符统称空白字符)。这样一来,格式化代码就有很大的自由度,但是遵循某些规则将有助于提高代码的可读性。

代码块、代码 基本结构

PowerShell 代码由一系列语句构成,每条语句可以使用一个分号结束,当然也可以不写。按照习惯是不写分号的,因此要用换行来区分不同的语句,如果必须写到一行中,那就在每一句后加个分号

和C语系的大多数语言类似,PowerShell 是一种块结构的语言,这些块用 { 和 } 来界定,代码块可以包含任意多条语句,或者不包含任何语句,下面的示例还使用了缩进格式,这样能大大提高可读性,实际上编译器会自动缩进代码。一般情况下,每个代码块都有自己的缩进级别,代码块之间还能嵌套。当然 PowerShell 的缩进不是强制的。

{
    <#代码行1#>
    <#代码行2#>
    {
        <#代码行3#>
        <#代码行4#>
    }
    <#代码行5#>;<#代码行6#>;
}

注释

  • 行注释: #
  • 块注释: <# 和 #>

PowerShell 代码是不区分大小写的,因此只要拼写正确的命令(或变量),而无需关心大小写即可执行,不过最好还是有一定规范。

PowerShell 脚本的基本结构

PowerShell 像 Python 一样,允许使用控制台直接输入命令进行交互,也可以事先把代码写入一个文件再作为脚本运行。 一个 PowerShell 脚本仅仅是一个包含 PowerShell 代码的文本文件。如果这个文本文件执行, PowerShell 解释器会逐行解释并执行它的的语句。PowerShell 脚本有点像以前 CMD 控制台上的批处理文件。可以通过非常简单的文本编辑工具创建 PowerShell 脚本。

PowerShell脚本文件的扩展名是 .ps1

执行策略限制

PowerShell 一般初始化情况下都会禁止脚本执行。脚本能否执行取决于PowerShell的执行策略。

PS E:> ./MyScript.ps1

无法加载文件 E:MyScript.ps1,因为在此系统中禁止执行脚本。有关详细信息,请参阅 "get-help about_signing"。
所在位置 行:1 字符: 15
+ .MyScript.ps1 < <<<
    + CategoryInfo          : NotSpecified: (:) [], PSSecurityException
    + FullyQualifiedErrorId : RuntimeException

只有管理员才有权限更改这个策略。非管理员会报错。

查看脚本执行策略,可以通过在 PowerShell 控制台直接输入: Get-ExecutionPolicy 更改脚本执行策略,可以管理员启动PowerShell,在控制台输入: Set-ExecutionPolicy <策略>

名称说明
Restricted受限制的,可以执行单个的命令,但是不能执行脚本Windows 8, Windows Server 2012, and Windows 8.1中默认就是这种策略,所以是不能执行脚本的,执行就会报错,那么如何才能执行呢?Set-ExecutionPolicy -ExecutionPolicy Bypass就是设置策略为Bypass这样就可以执行脚本了。
AllSignedAllSigned 执行策略允许执行所有具有数字签名的脚本
RemoteSigned当执行从网络上下载的脚本时,需要脚本具有数字签名,否则不会运行这个脚本。如果是在本地创建的脚本则可以直接执行,不要求脚本具有数字签名。
Unrestricted这是一种比较宽容的策略,允许运行未签名的脚本。对于从网络上下载的脚本,在运行前会进行安全性提示。需要你确认是否执行脚本
BypassBypass 执行策略对脚本的执行不设任何的限制,任何脚本都可以执行,并且不会有安全性提示。
UndefinedUndefined 表示没有设置脚本策略。当然此时会发生继承或应用默认的脚本策略。

如果要使用脚本功能又要兼顾安全性,我们就选择RemoteSigned 即在以管理员身份允许的 PowerShell 输入 Set-ExecutionPolicy RemoteSigned

执行策略可以防止您执行不信任的脚本。更改执行策略可能会使您面临 about_Execution_Policies帮助主题中所述的安全风险。是否要更改执行策略?
[Y] 是(Y)  [N] 否(N)  [S] 挂起(S)  [?] 帮助 (默认值为“Y”): y

设置执行权限  官网文档:https://learn.microsoft.com/zh-cn/powershell/module/microsoft.powershell.security/set-executionpolicy?view=powershell-7.2

为了防止恶意脚本的执行,PowerShell 执行了一个执行策略。默认情况下,执行策略被设置为受限,这意味着 PowerShell 脚本将不会运行。你可以通过使用以下 cmdlet 来确定当前的执行策略, 命令:Get-ExecutionPolicy

你可以使用的执行策略有。

  • Restricted - 脚本不会运行。
  • RemoteSigned - 本地创建的脚本会运行,但从互联网下载的脚本不会运行(除非它们是由受信任的发布者数字签名)。
  • 所有签名的脚本 只有在经过受信任的发布者签名后才会运行。
  • 不受限制的脚本 会运行,不管它们来自哪里,也不管它们是否被签名。

通过 cmdlet 来设置 PowerShell 的执行策略。命令:Set-ExecutionPolicy <policy name>

注意:在PowerShell命令提示符下输入命令时,你可以输入部分命令,然后点击Tab来自动填充其余部分(或者显示与你输入的内容相匹配的多个选择)。例如,输入Set-Ex并按Tab键将自动填入整个Set-ExecutionPolicy命令,为你节省一些时间。

运行 PowerShell 脚本

当您的脚本编写成功后您可能第一次会像下面的方式运行它,也就是只输入脚本的文件名,会报错。PS E:> ./MyScript.ps1

通过重定向创建脚本

如果想要执行的脚本不是很长,我们甚至可以直接在控制台中要执行的语句重定向给一个脚本文件。

PS E:> '"Hello,World!"' > MyScript.ps1
PS E:> ./MyScript.ps1
Hello,World!

这样有个缺点,就是您的代码必须放在闭合的引号中。这样的书写方式一旦在脚本内部也有引号时,是一件很痛苦的事。甚至您还可能希望在脚本中换行。下面的Here-strings例子不错,也就是将脚本文件通过@' '@闭合起来。

PS E:> @'
>> Get-Date
>> $Env:CommonProgramFiles
>> #Script End
>> "files count"
>> (ls).Count
>> #Script Really End
>>
>> '@ > myscript.ps1
>>
PS E:> .MyScript.ps1

2019年3月27日 18:15:10
C:\Program Files\Common Files
files count
20

Here-String以 @'开头,以'@结束.任何文本都可以存放在里面,哪怕是一些特殊字符,空白字符。但是如果您不小心将单引号写成了双引号,PowerShell 将会把里面的变量进行解析。

变量

变量可以临时保存数据,因此可以把数据保存在变量中,以便进一步操作。PowerShell 的变量定义非常方便。 我们可以用 $变量名=初值 的方法定义变量,解释器会根据所赋的初值判断变量类型,类似于C#的 var 关键字或 C++11 中的 auto 关键字。PowerShell 不需要显式地去声明,可以自动创建变量,只须记住变量的前缀为$(这一点又像bash了)。创建好了变量后,可以通过变量名输出变量,也可以把变量名加入双引号字符串中从而把变量值加到字符串内(所谓的模板字符串),但是有个例外: 单引号中的字符串不会识别和处理变量名。

$a = Get-Process
$a
$a = (Get-Process | Sort-Object ID)
echo $a

上面定义了变量 a,变量的定义是 "$变量名",

在 PowerShell 中变量名均是以美元符 $ 开始,剩余字符可以是数字、字母、下划线的任意字符,并且PowerShell变量名也对大小写不敏感($a 和 $A 是同一个变量)。 某些特殊的字符(比如$等)在 PowerShell 中有特殊的用途,一般不推荐使用这些字符作为变量名。当然你非要使用,请把整个变量名后缀用花括号括起来。

PS C:/> ${"I"like $}=5.1
PS C:/> ${"I"like $}
5.1

不能定义与保留变量名称相同的变量

使用ls variable: 列出当前使用的所有变量,刚启动的 PowerShell 执行此命令能看到 PowerShell 的所有自动化变量(一旦打开 Powershell 就会自动加载的变量)

查看变量类型

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

PS C:/> $num=10
PS C:/> $num.gettype() #方法不区分大小写

删除变量

如果不想继续使用自定义的变量,可以使用 del variable:变量名  删除变量,注意此处无$符号

$a=0
$a -eq $null
False
del variable:a
$a -eq $null 
True

PowerShell支持的变量类型和C#大体相同(没有了short、uint、ulong等),大多都继承自System.ValueType类( .NET类),其基本数据类型包括

整型

其实 int 、long 、以及下面的 float 都是 .NET的语法糖,真正的原生类型名是Int32、int64single 之类的类名

浮点型

浮点数标准形式(floatdouble)

±m×2e 其中m为尾数,e为阶码,尾数是一个非负数,阶码是一个整数

PowerShell(. NET库)还支持一个特别的浮点数类型 decimal,其形式为:±m×10e

其他类型

除了数值类型以外,还有4种基本类型和一些特殊的类型(引用类型)

注意

  • C/C++的 char 只有一个字节,因此只能表示ASCII的字符,
  • PowerShell 和 C# 的 char 是两个字节,支持Unicode的
  • PowerShell和C#的string类型是直接继承自 System.Object 类,因此说string 类型并非是简单类型(值类型),而是一种引用类型(如果有过C#的开发经验应该知道继承自ValueType类的类型运行时在栈里创建对象,而直接继承自Object的是在堆中创建对象)。
  • PowerShell的转义字符是 ` 而不是 \,这也是和C#的一个区别

#使用char
PS D:/>[char]$c="A"
$c
A
#使用bool
PS D:/>$boolean=$true
$boolean
True

#使用enum
enum fruit
{
    apple
    banana
    cherry
    durian
}
[fruit]$en=[fruit]::apple
$en
apple
$item="cherry"
[fruit]$enu=[fruit]::($item)
$enu
cherry

#这种使用方法是错误的
PS D:/> [fruit]$enum=banana

banana : 无法将“banana”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
所在位置 行:1 字符: 12
+ [fruit]$en=banana
+            ~~~~~~
    + CategoryInfo          : ObjectNotFound: (banana:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

#当尝试使用非枚举值进行赋值时
PS D:/> [fruit]$en=[fruit]::peach

由于枚举值无效,无法将 Null 转换为类型“fruit”。请指定以下枚举值之一,然后重试。可能的枚举值为“apple,banana,cherry,durian”。
所在位置 行:1 字符: 1
+ [fruit]$en=[fruit]::peach
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

PS D:/> "\n 123 `n 123"
<#输出
\n 123
 123
#>

PS D:/>$date=get-date
$date
$date.gettype()
<#输出
2019年3月28日 19:32:30

IsPublic IsSerial Name                            BaseType
-------- -------- ----                            --------
True     True     DateTime                        System.ValueType
#>

赋值和返回值

赋值操作符为 =,几乎可以把任何数据赋值给一个变量,甚至一条cmdlet命令 ,因为 PowerShell 支持面向对象,对象可以包罗万象。

PS D:\powershell\test> $item=ls
PS D:\powershell\test> $item
    目录: D:\powershell\test
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2017/11/24     12:52            136 4-3.cpp
-a----        2019/3/27     15:13             65 anapple.txt

PS D:\powershell\test> $item.gettype()
IsPublic IsSerial Name                              BaseType
-------- -------- ----                              --------
True     True     Object[]                          System.Array

$item为一个对象数组

动态和静态类型

一般对 PowerShell 变量重新赋值时,变量类型会自动改变,这体现了动态语言的特点; 而同样使用.NET 的C#却是静态强类型的语言,既然很像C#因此PowerShell 也可以使用静态类型,静态类型带来的严谨性能避免不必要的错误。

可以在变量前添加类型限定符使该变量变为静态类型,可以确保变量的类型不会随着赋值而改变

[int]$num=123 #正确
[int]$num=ls <#错误
无法将“System.Object[]”类型的“System.Object[]”值转换为“System.Int32”类型。
所在位置 行:1 字符: 1
+ [int]$num=ls
+ ~~~~~~~~~~~~
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException
#>

类型转换

PowerShell 能够非常方便地将字符串等类型转换成期望的类型。之所以神奇,是因为 PowerShell 本身做了很多辛苦的工作,按照优先级:

  1. 直接赋值:输入类型和期望类型一致,可以直接交付。
  2. 基于语言的类型转换:当目标类型为void,Boolean,String , Array , Hashtable , PSReference (i.e.: [ref]), XmlDocument , Delegate 和 Enum 时,基于语言的类型转换(.NET提供的)开始工作。
  3. Parse 转换:如果目标类型包含了 Parse() 方法,则采用它。
  4. Static Create 转换:如果目标类型包含静态的Create方法,则采用它。
  5. 构造函数转换:如果目标类型定义了构造函数,采用它。
  6. Cast 转换:如果目标类型定义了从源类型的显式或者隐式的操作符,则采用它。
  7. IConvertible 接口转换:如果目标类型实现了支持源类型IConvertible 接口,则采用它。
  8. IDictionary 转换:如果源类型是词典或者哈希表,会尝试创建一个实例,然后来填充name和value属性。
  9. PSObject 属性转换:如果源类型是PSObject,通过目标类型的默认的构造函数创建一个实例,然后使用PSObject中的属性名称和值来填充实例的属性。
  10. TypeConverter 转换:如果存在注册的 TypeConverter 或 PSTypeConverter 来处理转换,则使用它。

注意对浮点数向整数进行类型转换时,会自动四舍五入!! 如果要C++/C#那种向下取整的方法请使用 [math]::Floor() 函数 看几个转换的例子

PS D:/test> $s=12.56
PS D:/test> [int]$s
13
PS D:/test> [convert]::ToInt32($s)
13

[convert]::ToInt32() 是 .NET System.Convert 类提供的转换函数 convert 类中的转换函数格式为:TO+原生类型名(),这里的原生类型名指的是各个类型实际类名 常用: [convert]::ToInt32() [convert]::ToSingle() [convert]::ToDouble() [convert]::ToBoolean() * [convert]::ToString()

convert 类提供了一系列静态方法来完成不同变量之间的转换,获得函数列表及使用方法请参考微软的 .NET文档Convert类 方法列表

当然每个类型本身也提供了一些静态方法以供安全转换,比如int32类型提供了Parse和TryParse两个静态方法尝试将其他类型转换成int32类型

运算符

注意逻辑运算符和比较运算符的写法,不支持 C# 的&& ||  == != < > >= <=这些运算符,而是使用下列运算符(终究还是个shell啊,因此不论是变量名还是运算符都有shell的感觉)

#加 减 乘 除 取余
+ - * / %
#自增、自减运算符,和C#或C++完全一致
++$i
$i++
$i--
--$i
#且
-and
#并
-or
#非
-not
!
#样例
$true -and $false -or -not 0
!$true
#输出
True
False
#等于 (equal to)
-eq
#不等于 (not equal to)
-ne
#大于 (greater than)
-gt
#大于等于 (greater than or equal to)
-ge
#小于 (less than)
-lt
#小于等于 (less than or equal to)
-le

#对于字符串类型,可以在比较运算符前加i或c表示是否区分大小写,
#i表示对大小写不敏感,c表示敏感,不写默认不敏感
"a" -eq "A"
"a" -ceq "A"
#输出
True
False

#判断变量是否为兼容类型(同一类型或其父类型),类型格式为 [类型名]
-is
#示例
$a=0
$a -is [int]
$b=1,2,3
$b -is [array]
$a -is [ValueType]
#输出
True
True
True # System.Int32类继承自System.ValueType类,因此int是其父类型ValueType的子类型

条件分支 --- if else

if 和 else 用法和C#完全一样,除了大括号不允许省略,多分支时还多了个elseif 可用(与 Python 的 elif 作用相同)

if($true -and $true) {
    $a=0
}
elseif($a -eq $b) {
    $a=1
}
else {
    $a=2
}

条件分支 --- switch

PowerShell的switch非常灵活,使用起来较为方便 相对C#或C++,PowerShell的 switch 不需要写 case ,但是必须写大括号

$a="Beijing"
switch($a) 
{
    "Beijing" {$res="北京"}
    "Shanghai" {$res="上海"}
}

默认比较运算符为-eq,你也可以使用下面的例子自定义比较条件,必须保证表达式返回 bool 类型($true和$false)

$v=18
switch($v)
{
    {$_ -lt 10} {"小于10"} # $_ 表示当前的传入的变量 直接写的字符串会被输出
    10 {"等于10"}
    {$_ -gt 10} {"大于10"}
}
<#输出
大于10
#>

for 循环

PowerShell 的 for 循环类似于C#,看一个样例:

for($i=0;$i -lt 10;$i++)
{
    Write-Output "Hello"
}

do-while 循环

Do 和 While 可能产生死循环,为了防止死循环的发生,因此我们必须确切的指定循环终止的条件。指定了循环终止的条件后,一旦条件不满足就会退出循环。 do-while() 会先执行再去判断,能保证循环至少执行一次。

do 

    $n=Read-Host "请输入数字"

while($n -ne 0)
<#输出
请输入数字: 1
请输入数字: 2
请输入数字: s
请输入数字: 0
#>

只使用 while

$n=5
while($n -gt 0)
{
    $n
    $n=$n-1
}
#输出
5
4
3
2
1

跳出循环

使用 continue 关键字,可以终止当前循环,跳过 continue 后其它语句,重新下一次循环。 跳出循环语句使用 break 关键字

$n=1
while($n -lt 6)
{
    if($n -eq 4)
    {
        $n=$n+1
        continue

    }
    else
    {
        $n
    }
    $n=$n+1
}
1
2
3
5
$n=1
while($n -lt 6)
{
    if($n -eq 4)
    {
        break
    }
    $n
    $n++
}

还有一种循环 foreach ,等到数组再说

比较运算符
-eq :等于
-ne :不等于
-gt :大于
-ge :大于等于
-lt :小于
-le :小于等于
-contains :包含
$array -contains something

-notcontains :不包含
!($a): 求反
-and :和
-or :或
-xor :异或
-not :逆
if-else
if-else:

if($value -eq 1){
    code1
}else{
    code2
}
循环语句
while
while($n -gt 0){
    code
}
for
$sum=0
for($i=1;$i -le 100;$i++)
{
    $sum+=$i
}
$sum
foreach
# 打印出windows目录下大于1mb的文件名
foreach($file in dir c:windows)
{
    if($file.Length -gt 1mb)
    {
        $File.Name
    }
}

数组

定义数组。在 PowerShell 中创建数组可以使用逗号

PS C:/Powershell> $nums=2,0,1,2
PS C:/Powershell> $nums

对于连续的数字数组可以使用一个更快捷的方法:

PS C:/Powershell> $nums=1..5
PS C:/Powershell> $nums

对象数组的多态

像变量一样,如果数组中元素的类型为弱类型,默认可以存储不同类型的值。

PS C:/Powershell> $array=1,"2019",([Guid]::NewGuid()),(get-date)
PS C:/Powershell> $array

PS C:/Powershell> $array|foreach{$_.gettype()}

空数组和单元素数组

对数组元素可以查看它的公有属性,比如长度 只需要输入$数组名.Count即可显示数组长度

空数组

PS C:/Powershell> $a=@()
PS C:/Powershell> $a -is [array]
True
PS C:/Powershell> $a.Count
0

单元素数组

PS C:Powershell> $a=,"moss"
PS C:Powershell> $a -is [array]
True
PS C:Powershell> $a.Count
1

遍历 数组

将数组作为单独一行将会自动遍历这个数组的所有元素

PS C:/> $a=1..10
PS C:/> $a

for 循环遍历

PS C:/> $a=1..5
PS C:/> for($i=0;$i -lt 5;$i++) {
>> $a[$i] }

foreach 遍历法

还有一种遍历的方法,用到了之前提到的 foreach 语句 意思是使用变量 $n 对 $a 元素进行迭代,这实际上是一种对可迭代对象的访问算法。 在 C# 也有这种语法,严格来说foreach是一种对实现了IEnumerable接口容器对象的一种遍历操作

$a="A","B","C","D","E"
foreach($n in $a)
{
    $n+" "+$n
}

foreach 还有一种遍历的写法

这里我们需要先了解一下管道 管道的符号 | 管道允许将它左侧命令的输出结果发送到右侧做命令的参数。示例命令:Get-Process | Sort-Object ID

管道并不是什么新事物,以前的各种shell也有重定向的命令,例如cmd里面都有Dir | More可以将结果分屏显示。

不过传统的管道是基于文本的,但是 PowerShell 是基于对象的

列出当前目录下的目录和文件,然后根据文件名降序排列,再投影(数据库术语,实际就是挑出的意思...)文件名,文件大小,文件的修改时间:

PS D:/test> ls | Sort-Object -Descending Name | Select-Object Name,Length,LastWriteTime

可迭代对象(比如数组)可以由管道送到一些命令上进一步处理 foreach就可以接受管道送来的可迭代对象,并进行遍历,使用$_ 表示遍历到的元素

$array="A","B","C","D","E"
$array|foreach
{
    $_+"s"
}

数组 逆序 输出

PS C:/Powershell> $books="A1","B2","C3"
PS C:/Powershell> $books[($books.Count)..0]

访问 数组 元素

与C#相同,数组的元素可以使用索引寻址,第一个元素的索引为0,第i个元素的索引为i-1,最后一个元素的索引为Count-1,但是 PowerShell 为了使用方便,直接可以将 -1 作为最后的一个元素的索引(参考了 Python 的语法)

PS C:/Powershell> $books="1A","2B","3C"
PS C:/Powershell> $books[0]
1A
PS C:/Powershell> $books[1]
2B
PS C:/Powershell> $books[($book.Count-1)]
3C
PS C:/Powershell> $books[-1]
3C

从数组中选择多个元素

PS C:/Powershell> $result=ls
PS C:/Powershell> $result[0,3,5,12]

给数组添加元素

因为PowerShell数组在内存中是顺序存储的,所以数组的大小必须是确定的,这样才方便分配存储空间,所以给数组增加元素其实相当于创建一个新的数组,只不过之后会把原来的副本删除。在当前数组追加元素可以使用 += 操作符。

PS C:/Powershell> $books="A1","B2","C3"
PS C:/Powershell> $books+="D4"
PS C:/Powershell> $books

删除指定位置元素

采用截断重连法删除指定元素

PS C:/Powershell> $num=1..4
PS C:/Powershell> $num
1
2
3
4
PS C:/Powershell> $num=$num[0..1]+$num[3] #相当于删掉了第三项
PS C:/Powershell> $num
1
2
4

复制数组

数组属于引用类型,使用默认的的赋值运算符在两个变量之间赋值只是复制了一个引用,两个变量共享同一份数据。这样的模式有一个弊病:如果其中一个改变也会株连到另外一个。所以复制数组最好使用 Clone() 方法( System.Array 类的成员函数,继承自Object类),除非有特殊需求。

PS C:/Powershell> $chs=@("A","B","C")
PS C:/Powershell> $chsBak=$chs
PS C:/Powershell> $chsBak[1]="H"
PS C:/Powershell> $chs
A
H
C
PS C:/Powershell> $chs.Equals($chsBak)
True
PS C:/Powershell> $chsNew=$chs.Clone()
PS C:/Powershell> $chsNew[1]="Good"
PS C:/Powershell> $chs.Equals($chsNew)
False
PS C:/Powershell> $chs
A
H
C

强类型数组

PowerShell 数组一般具有多态性,如果你不指定元素的具体类型,解释器会自动选择合适的类型存储每个元素。如果要统一限制所有元素的类型,可是使用类型名和一对方括号作为数组变量的类型。这样每当赋值时,会自动类型检查。如果目标数据类型不能转换成功,就会抛出一个异常,这样的数组被称为强类型数组 定义方法[类型[]]$数组名=初值

PS C:/Powershell> [int[]] $nums=@()
PS C:/Powershell> $nums+=2012
PS C:/Powershell> $nums+=12.3
PS C:/Powershell> $nums+="999"
PS C:/Powershell> $nums+="can not convert"
Cannot convert value "can not convert" to type "System.Int32". Error: "Input string was not in a correct format."
At line:1 char:6
+ $nums <<<< +="can not convert"
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

命令返回数组

当我们把一个非Cmdlet命令的执行结果保存到一个变量中,可能会认为变量存放的是纯文本。
但是,事实上 PowerShell 会把文本按每一行作为元素存为数组。如果一个命令的返回值不止一个结果时, PowerShell 也会自动把结果存储为数组

PS C:/Powershell> $IPcfg=ipconfig
PS C:/Powershell> $IPcfg
PS C:/Powershell> $IPcfg.Count

使用数组存储结果

判断一个变量是否为数组

PS C:/Powershell> $ip=ipconfig
PS C:/Powershell> $ip -is [array]
True
PS C:/Powershell> "abac" -is [array]
False
PS C:/Powershell> $str="字符串"
PS C:/Powershell> $str.ToCharArray() -is [array] #转换为字符数组
True

使用真实的对象操作

为什么不愿把 IPconfig 返回的结果称为对象,因为它不是真正Cmdlet命令(事实上ipconfig是一个单独的程序),真正的 PowerShell 命令返回的数组元素可不止一个字符串,它是一个内容丰富的对象。

PS D:/test> $list=ls
PS D:/test> $list

PS D:/test> $list.gettype()

PS D:/test> foreach($i in $list){$i.name}

PS D:/test> $list[0].gettype()

上面的例子中数组的每一个元素存放的是一个 System.IO.DirectoryInfo 对象。 当我们输出这些对象时,PowerShell 会自动帮我们把它转换成友好的文本格式。 对于任何一个对象都可以使用 Format-List * 来查看它所有的属性和方法。

PS D:/test> $list[0]|fl * 
# "|"符号是管道符,将左边返回结果做参数发送到右侧,fl是Format-List的简称

哈希表 (key ---> value)

通过使用 @符号 创建 hash 表

哈希表的创建:$stu=@{ Name = "test";Age="12";sex="man" }

哈希表里存数组:$stu=@{ Name = "hei";Age="12";sex="man";Books="kali","sqlmap","powershell" }

哈希表的插入与删除:
$Student=@{}
$Student.Name="hahaha"
$stu.Remove("Name")

例如,下面这行代码,它创建了一个名为 $Procs 的键值对的 hash表

$procs = @{name="explorer","svchost"}
$procs
echo "***************************************"
$procs['name'][0]
$procs['name'][1]

也可以在使用该变量时使用@符号,以确保它被当作一个数组而不是一个单一的值。例如,下面这行代码将针对我刚才定义的变量运行Get-Process cmdlet。这样做,Windows将显示Windows Explorer和Svchost使用的所有进程。请注意变量名称前面使用的是@符号,而不是我们通常看到的美元符号。

$procs = @{name="explorer","svchost"}
Get-Process @procs

函数

函数是自定义的 Powershell 代码,有三个原则:
简短:函数名简短,并且显而易见。
聚合:函数可以完成多个操作。
封装和扩展:将一批 Powershell 语句进行封装,实现全新的功能需求。 函数的结构由三部分组成:函数名,参数,函数体

function Invoke-PortScan {
    <#
    .SYNOPSIS 
    简介​    
    .DESCRIPTION
    描述        
    .PARAMETER StartAddress
    参数​    
    .PARAMETER EndAddress
    参数​    
    .EXAMPLE
    PS > Invoke-PortScan -StartAddress 192.168.0.1 -EndAddress 192.168.0.254
    用例
    #>
    code
}

异常处理

Try{
    $connection.open()
    $success = $true
}Catch{
    $success = $false
}

定义函数。脚本中函数的定义方法

函数可以在文本编辑器上编写,写完以后复制进 PowerShell 控制台即可。如果控制台设置为快速编辑模式,从记事本复制后,直接在控制台鼠标右键即可完成粘贴(Windows 10默认开启了快速编辑模式)

function FuncName(args[]) #括号可省略
{
    <#代码段#>
}

控制台上多行输入定义函数

PS C:/PowerShell> function MyPing
>> {
>> PING.EXE  -n 1 $args
>> }
PS C:/PowerShell>

把函数精简成一行

我们可以将一个函数定义在一行上,但是这样阅读和理解起来就不方便,所以要在每条命令后加分号进行分割(最后一句可以不写;)

PS C:/PowerShell> function cd...{ cd.. ; cd.. }
PS C:/PowerShell> cd...

使用函数作为别名

假如 PowerShell 不支持 Get-SystemVersion 命令,你可以通过定义函数实现这个功能:

function get-systemversion
{
    $psversiontable.BuildVersion
}

Get-SystemVersion

更新函数。如果要更新已经定义好的函数,简单的方法是重新定义,这样新的定义会覆盖旧的定义。但是如果函数代码没有保存副本,可以先将函数定义导出到ps1文件,然后就可以编辑了。

PS C:/PowerShell> function MyPing
>> {
>> PING.EXE  -n 1 $args
>> }

PS C:/PowerShell> $function:MyPing | Out-File myPing.ps1
PS C:/PowerShell> $function:MyPing

PING.EXE  -n 1 $args

PS C:/PowerShell> $function:MyPing | Out-File myPing.ps1
PS C:/PowerShell> .myPing.ps1
必须指定 IP 地址。
PS C:/PowerShell> notepad.exe $$

删除函数

控制台定义的函数只会在当前会话生效,一旦控制台退出,会自动消失。在不关闭控制台的条件下删除一个已经定义好的函数,可是使用虚拟驱动器的方法:

function cc{"hello"}
PS C:/> cc
hello
PS C:/> del function:cc
PS C:/> cc
cc : 无法将“cc”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。
所在位置 行:1 字符: 1
+ cc
+ ~~
    + CategoryInfo          : ObjectNotFound: (cc:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

控制台 输入、输出

PowerShell提供了 Read-Host 命令,可以接收返回用户在控制台输入的字符

$name=read-host "请输入你的名字" 
#会把提示信息打印到PS控制台,也可以不写提示信息
<#执行+输入 结果:
请输入你的名字: Nougat 
#>
$name
Nougat

注意到 1. 提示信息(如果有)后面自动加了个冒号; 2. 用户键入任何信息都被作为该命令的返回结果; 3. 可以把键入的信息传递给一个变量;

有两种输出命令 Write-HostWrite-Output 若输出字符串不包含空白字符可以不加引号

Write-Host

当需要展示一个特定信息,比如使用其他颜色来吸引人们的注意力的时候,可使用 Write-Host 命令

Write-Host 和其他Cmdlets一样使用管道,但是它不放置任何数据道管道中。反而会直接写到宿主应用程序的界面。正如此,可以使用-ForegroundColor 和 -BackgroundColor 参数将前景和背景设置为其他颜色:

write-host "啊哈" -ForegroundColor White -BackgroundColor Red
啊哈

注:不是每个使用PowerShell的应用程序都支持其他颜色,也并不是每个应用程序都支持所有颜色。 该输出方法不适用于常规的输出结果,因为 Write-Host 命令输出到屏幕的任何东西都无法被捕捉。若执行远程命令或无人值守命令(纯自动化), Write-Host 可能不会按照你的预期工作。因此,此命令仅仅用于与人进行直接交互。

Write-Output

Write-Output命令会将对象发送给管道。由于它不会直接发送到显示界面,所以不允许你指定其他任何的颜色。

它是PowerShell默认使用的一个Cmdlets,默认输出方式即使用该命令,即使你没有指定,PowerShell会在底层将信息传递给Write-Output命令(就是一行直接写一个变量就能直接输出的情况),另外这个命令还有两个别名 write 和 echo

write-host ACB #无空白字符可以不写引号 
ACB
write "ABC"
ABC
echo "ABD"
ABD

Write-Output输出基本过程为:

  1. Write-Output命令将string类型的对象Hello World!放入管道中;
  2. 管道中只有这个string对象,其会直接到达管道的末端,也就是Out-Default命令;
  3. Out-Default命令将对象传递给Out-Host命令;
  4. Out-Host命令要求PowerShell的格式化系统格式化该对象。
  5. Out-Host将格式化的结果集放在显示界面上

还有一点,在输出多个对象时,Write-Host会以空格隔开各对象 Write-Output会以换行隔开各对象

write-host "ABC" "23232"
ABC 23232

write-output "ABC" "23232"
ABC 
23232

其他的输出方式:Write-Warning / Verbose / Debug / Error

具体参考:https://learn.microsoft.com/zh-cn/powershell/module/microsoft.powershell.utility/write-debug?view=powershell-7.3&viewFallbackFrom=powershell-3.0

处理函数参数

PowerShell 函数可以接受参数,并对参数进行处理。函数的参数有3个特性:

  1. 任意参数:内部变量$args 接受函数调用时接受的参数,$args是一个数组类型;
  2. 命名参数:函数的每一个参数可以分配一个名称,在调用时通过名称指定对应的参数;
  3. 预定义参数:函数在定义参数时可以指定默认值,如果调用时没有专门指定参数的值,就会保持默认值;

$args 万能参数

给一个函数定义参数最简单的是使用$args这个内置的参数。它可以识别任意个参数。尤其适用那些参数可有可无的函数。

function sayHello
{
    if($args.Count -eq 0)
    {
        "No argument!"
    }
    else
    {
        $args | foreach {"Hello,$($_)"}
    }
}
#无参调用
sayhello
#输出
No argument!

#一参调用
sayhello "World!" #也可以写成sayhello("World!")
#输出
Hello,World!


#多参数调用
$str="it's me."
sayhello 123 "aha" $str #如果字符串不包含空白字符(比如空格),引号可以不写
<#输出
Hello,123
Hello,aha
Hello,it's me.
#>

因为 $arg 是一个数组,可以用它很方便的写出求和函数

function Add
{
    $sum=0
    $args | foreach {$sum=$sum+$_}
    $sum
}
Add 10 7 3 100
#120

使用固定参数

function StringContact($str1,$str2)
{
    return $str1+$str2
}

StringContact LN P
#StringContact -str1 word -str2 
StringContact("word","press")
输出
LNP
wordpress

给参数定义默认值

function stringContact($str1="LN",$str2="P")
{
    return $str1+$str2
}

stringContact
LNP

使用强类型参数

通过之前的例子发现将用户的参数传递给函数显得比较混乱。罪魁祸首就是PowerShell的参数解释器,它可以自动处理和分配参数给函数。
函数的参数解释器比较傲慢,它对你提供的参数的信息完全不关心。它只会粗略地将参数进行分割,并且最大限度的进行自动类型转换。事实上,这种类型转换很多时候并不完美。所以最好提前能够对参数进行强类型限制

限制数字类型

下面的函数执行后,会抛出异常

因为 subtract 定义了强类型参数,调用时参数类型不匹配就会触发异常。

function subtract([int]$value1,[int]$value2)
{
    return $value1-$value2
}
subtract LN P
#执行结果报错
subtract : 无法处理对参数“value1”的参数转换。无法将值“LN”转换为类型“System.Int32”。错误:“输入字符串的格式不正确。”
所在位置 行:1 字符: 10
+ subtract LN P
+          ~~
    + CategoryInfo          : InvalidData: (:) [subtract],ParameterBindingArgumentTransformationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,subtract

subtract 8.1 7.9
0
<#结果为0,这是因为PowerShell对结果整型化时进行了四舍五入
但是如果将上面的函数的参数定义为Double型#>
function subtract([double]$value1,[double]$value2)
{
    return $value1-$value2
}
subtract 8.1  7.9
0.199999999999999
<#输出 0.199999999999999的原因就是 .NET使用IEEE754标准存储浮点数,
由于这些小数转化二进制会无限循环,会根据一定精度截取尾数,
这个问题引发了这种奇怪的结果,
其实著名的0.1+0.2!=0.3也是这个原因导致的#>

限制日期类型

函数的参数解释器会自动尝试将字符串转换成日期类型,如果转换失败就是抛出异常 看下面的例子

function DayOfWeek([datetime]$date)
{
    return  $date.DayOfWeek
}

DayofWeek '1927-8-1'
Monday

DayofWeek 2008-8-1
Friday

DayofWeek 'abc'
DayOfWeek : 无法处理对参数“date”的参数转换。无法将值“abc”转换为类型“System.DateTime”。错误:“该字符串未被识别为有效的 DateTime。有一个未知单词(从索引 0 处开始)。”
所在位置 行:1 字符: 12
+  DayofWeek 'abc'
+            ~~~~~
    + CategoryInfo          : InvalidData: (:) [DayOfWeek],ParameterBindingArgumentTransformationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,DayOfWeek

Switch 参数

Powershell 函数最简单的参数类型为布尔类型,除了使用 Bool 类型,也可以使用 Switch 关键字。
下面的函数逆转字符串,但是可以通过 $try 参数进行控制,如果没有指定 $try 的值,默认值为 $false

function  tryReverse( [switch]$try , [string]$source ) 
#此处switch完全可以换成bool
{
    [string]$target=""
    if($try)
    {
        for( [int]$i = $source.length -1; $i -ge 0 ;$i--)
        {
            $target += $source[$i]
        }
        return $target
    }
    return $source
}
tryReverse -source www.google.com
tryReverse -try $true -source www.google.com
#输出
www.google.com
moc.eloog.www

指定函数的返回值

一个或多个返回值

PowerShell 不像其它的编程语言,它的函数可以有多个返回值。如果你直接调用函数,返回值会在控制台输出。当然你也可以将结果存储在一个变量中进一步处理
下面的例子演示返回一个值:

function Square([double]$num)
{
    return $num*$num
}
#在控制台输出结果
Square 9.87
97.4169

#将结果赋值给变量
$value=Square 9.87
$value
97.4169

#返回值为Double类型
$value.GetType().FullName
System.Double

下面的例子演示返回多个值

function gbMeasure($amount)
{
    "$amount GB=$($amount) GB"
    "$amount GB=$($amount*1gb/1mb) MB"
    "$amount GB=$($amount*1gb/1kb) KB"
    "$amount GB=$($amount*1gb) B"
}

#函数返回4个值
gbMeasure 1
1 GB=1 GB
1 GB=1024 MB
1 GB=1048576 KB
1 GB=1073741824 B

#将所有的返回值存储在一个变量中
$result=gbMeasure 1
$result

1 GB=1 GB
1 GB=1024 MB
1 GB=1048576 KB
1 GB=1073741824 B

#所有的返回值会自动存储在一个数组中
$result=gbMeasure 1
$result.GetType().Name
Object[]

#通过索引访问每个返回值
$result=gbMeasure 1
$result[3]
1 GB=1073741824 B

总结一下,如果一个函数返回一个值,像其它编程语言一样,这个值包括它的类型信息会直接返回。但是如果遇到多个返回值,PowerShell会将所有的返回值自动构造成一个对象数组。 可以通过索引访问数组

Return语句

Powershell 会将函数中所有的输出作为返回值,但是也可以通过return语句指定具体的返回值。
Return 语句会将指定的值返回,同时也会中断函数的执行,return后面的语句会被忽略

看一个例子

function test($num)
{
    1
    9
    return 10
    4
    6
}

test
1
9
10
<# 1 和 9 作为输出会返回
return语句中的10 也会返回
return 语句后的4和6会被忽略#>

访问返回值

一个函数返回了一个值还是多个值,是可以验证的。下面的例子会产生随机数,如果没有指定个数,默认会返回一个随机数,否则会返回指定个数的随机数

function lottery([int]$number=1)
{
    $rand = New-Object system.random
    for ($i=1; $i -le $number; $i++) 
    {
        $rand.next(1,50)
    }
}

# 参数为空时,返回值不是数组:
$result = lottery
$result -is [array]
False

# 如果指定多个随机数时,返回值是数组类型:
$result = lottery 10
$result -is [array]
True
$result.count
10

从函数的返回值中消除输出

函数默认会将函数中的所有输出作为函数的返回值返回,这样很方便。但有时可能会将不必要的输出误以为返回值。写脚本程序时,可能需要自定义一些函数,这个函数可能只需要一个返回值,但是为了提高函数的可读性,可能会在函数增加一些注释输出行,或者使用write-host

function Test()
{
    "Try to calculate."
    "3.1415926"
    "Done."
}

#保存在变量中输出,
$value=Test
$value
#输出
Try to calculate.
3.1415926
Done.

#如果要过滤注释,只输出,不作为返回值,
#可以使用Write-Host命令
function Test()
{
    Write-Host "Try to calculate."
    "3.1415926"
    Write-Host "Done."
}
# 在变量值中保存返回值,在控制台输出注释行
$value=Test
#控制台输出
Try to calculate.
Done.

# 测试返回值
$value
3.1415926

恭喜你!到此 PowerShell 基础入门算是完成了! 之后将介绍 PowerShell 的进阶使用

对象

在 powershell 中一切都可以视为对象,使用 New-Object 可以创建任何对象,使用 Add-Member 可以添加属性和方法

新建对象:New-Object

实例:
创建一个空对象(Object):$empty = New-Object Object
新建List类型的对象:$list = New-Object System.Collections.Generic.List[String]

新建TcpClient
$tcpClient = New-Object System.Net.Sockets.TcpClient
$tcpClient.Connect("127.0.0.1", 135)
$tcpClient.Close()

新建文件并将设置文件对象的创建时间
$File = New-Item NewFile.txt -Force
$File.CreationTime = Get-Date -Day 1 -Month 2 -Year 1692

添加成员:Add-Member
作用:将新成员添加到对象中

实例:
新建对象,并添加成员(键值对属性)
$empty = New-Object Object
$empty | Add-Member -Name New -Value 'Hello world' -MemberType NoteProperty

新建对象,并添加成员(键值对属性)
$panda = New-Object Object
$panda | Add-Member -Name 'PandaProperty' -Value "Panda666.com" -MemberType NoteProperty

新建对象,并添加成员(代码属性)
$dog = New-Object Object;
#添加普通键值对属性
$dog | Add-Member -Name "p1" -Value "Panda666" -MemberType NoteProperty;
#添加代码属性
$dog | Add-Member -Name "p2" -Value { $this.p1.Length } -MemberType ScriptProperty; 

获得对象的成员

PSMemberTypes Enum:https://learn.microsoft.com/zh-cn/dotnet/api/system.management.automation.psmembertypes?view=powershellsdk-7.2.0

实例:获得指定对象的成员
Get-Process -Id 3880 | Get-Member

指定成员类型
Get-Process -Id $PID | Get-Member -MemberType Property

获得对象成员
(Get-Process -Id $PID).StartTime

获得对象成员的成员
(Get-Process -Id $PID).StartTime.DayOfWeek

如果对象成员有空格,可以使用单引号、双引号、括号进行包裹
$object = [PSCustomObject]@{ 'Some Name' = 'Value' }
$object."Some Name"
$object.'Some Name'
$object.{Some Name}

还可以使用变量作为成员名称
$object = [PSCustomObject]@{ 'Some Name' = 'Value' }
$propertyName = 'Some Name'
$object.$propertyName
注意:不要修改对象的只读属性,否则会报错

使用对象的方法(Using methods)
调用无参数的方法:<Object>.Method()
调用有参数的方法:<Object>.Method(Argument1, Argument2)
通过调用对象的属性修改对象状态:(Get-Date).Date.AddDays(-1).ToString('u')

遍历对象:ForEach-Object
提示:除了可以引用单个元素对象,还可以获得元素的单个属性或执行方法

实例:
给数组的元素自增1
$pandaArr = 1,2,3,4,5;
$pandaArr | ForEach-Object { $_ + 1; }; 

获得进程的名称
Get-Process | ForEach-Object {
 Write-Host $_.Name -ForegroundColor Green
}

直接调用元素的 方法、属性

$pandaArr = "Panda","Dog","Cat";
$pandaArr | ForEach-Object ToUpper`
等价于:
$pandaArr = "Panda","Dog","Cat";
$pandaArr | ForEach-Object {
    $_.ToUpper();
}

直接调用元素的方法2
(Get-Date '2020年9月22日' ), (Get-Date '01/01/2020') | ForEach-Object ToString('yyyyMMdd') 
等价于:
(Get-Date '2020年9月22日'), (Get-Date '01/01/2020') | ForEach-Object {
    $_.ToString('yyyyMMdd');
}

直接调用元素的属性
$pandaArr = "Panda","Dog","Cat";
$pandaArr | ForEach-Object Length
等价于:
$pandaArr = "Panda","Dog","Cat";
$pandaArr | ForEach-Object {
    $_.Length
}

筛选对象

Where-Object [-Property] <String> [[-Value] <Object>] -GT ...
提示:?(问号)是Where-Object Cmdlet的别名

实例:筛选出启动时间在5点后的进程
Get-Process | Where-Object StartTime -gt (Get-Date 17:00:00)
也可以使用代码块结构
$pandaArr = 1,2,3,4,5
$pandaArr | Where-Object { $_ -gt 3 }

带有多个筛选条件
Get-Service | Where-Object { $_.StartType -eq 'Manual' -and $_.Status -eq 'Running' }

选择对象的数据子集:Select-Object
实例:选择指定名称的成员
Get-Process | Select-Object -Property Name,Id,CPU

排除指定的字段
Get-Process | Select-Object -Property * -Exclude *Memory* 

获得前10条数据
Get-Process | Select-Object -First 10

获得后10条数据
Get-Process | Select-Object -Last 10

跳过2条数据
Get-ChildItem C:\ | Select-Object -Skip 4 -First 1
不重复
1, 1, 1, 3, 5, 2, 2, 4 | Select-Object -Unique

对象排序:Sort-Object

实例:
指定排序的key 使用对象的属性
Get-Process | Sort-Object -property VM
Get-Process | Sort-Object -Property Id

降序排序
Get-Process | Sort-Object -property Comments -Descending
排除重复然后排序
1, 1, 1, 3, 5, 2, 2, 4 | Select-Object -Unique | Sort-Object 

多字段排序
Get-ChildItem C:\Windows | Sort-Object LastWriteTime, Name
还可以使用代码块结构进行复杂的排序
$examResults = @(
    [PSCustomObject]@{ Exam = 'Music'; Result = 'N/A'; Mark = 0 }
    [PSCustomObject]@{ Exam = 'History'; Result = 'Fail'; Mark = 23 }
    [PSCustomObject]@{ Exam = 'Biology'; Result = 'Pass'; Mark = 78 }
    [PSCustomObject]@{ Exam = 'Physics'; Result = 'Pass'; Mark = 86 }
    [PSCustomObject]@{ Exam = 'Maths'; Result = 'Pass'; Mark = 92 }
)
$examResults | Sort - Object {
    switch ($_.Result) {
    'Pass' { 1 }
    'Fail' { 2 }
    'N/A' { 3 }
    }
}

对象分组:Group-Object

实例:数组分组
6, 7, 7, 8, 8, 8 | Group-Object
不需要元素
6, 7, 7, 8, 8, 8 | Group-Object -NoElement
也可以使用代码块的方式使用
'one@one.example', 'two@one.example', 'three@two.example'  | Group-Object { ($_ -split '@')[1] }

统计测量对象操作:Measure-Object

常用于统计对象的内容
注意:When used without any parameters, Measure-Object will
return a value for Count

实例:默认返回Count
1, 5, 9, 79 | Measure-Object
获得项数
3358,6681,9947,1156 | Measure-Object -Count
获得合计值
3358,6681,9947,1156 | Measure-Object -Sum
获得最大值
3358,6681,9947,1156 | Measure-Object -Max
获得最小值
3358,6681,9947,1156 | Measure-Object -Min
获得平均数
3358,6681,9947,1156 | Measure-Object -Average
指定多项目
1, 5, 9, 79 | Measure-Object -Average -Maximum -Minimum -Sum
获得单词数目
Get-Content -Path "D:/test.txt" | Measure-Object -Word
获得字符数量
Get-Content -Path "D:/test.txt" | Measure-Object -Character 
获得行数(不包括空行)
Get-Content -Path "D:/test.txt" | Measure-Object -Line

对象对比:Compare-Object

实例:对比文本
Compare-Object "D:/test.csv" "D:/test2.csv"
对比文件内容
Compare-Object (Get-Content "D:\test.csv") (Get-Content "D:\test2.csv")
显式带参数方式
Compare-Object -ReferenceObject 1, 2 -DifferenceObject 1, 2
显示相同点和不同点(默认只显示不同点)
Compare-Object -ReferenceObject 1, 2, 3, 4 -DifferenceObject 1, 2 -IncludeEqual

命名空间

:https://learn.microsoft.com/zh-cn/powershell/module/microsoft.powershell.core/about/about_using?view=powershell-7.3

使用 using 语句可以指定会话中使用的命名空间。 添加命名空间可简化 .NET 类和成员的使用,并允许从脚本模块和程序集导入类。

  • 语句 using 必须位于脚本或模块中的任何其他语句之前。 任何未注释的语句都不能位于它前面,包括参数。
  • 语句 using 不得包含任何变量。
  • 不应将 using 语句与变量的范围 using: 修饰符混淆。 有关详细信息,请参阅 about_Remote_Variables。

使用.NET 命名空间:using namespace <.NET-namespace>

using namespace System.Text
using namespace System.IO

[string]$string = "Hello World"
## Valid values are "SHA1", "SHA256", "SHA384", "SHA512", "MD5"
[string]$algorithm = "SHA256"

[byte[]]$stringbytes = [UnicodeEncoding]::Unicode.GetBytes($string)

[Stream]$memorystream = [MemoryStream]::new($stringbytes)
$hashfromstream = Get-FileHash -InputStream $memorystream `
  -Algorithm $algorithm
$hashfromstream.Hash.ToString()

从 PowerShell 模块加载类:using module <module-name>

using module CardGames

[Deck]$deck = [Deck]::new()
$deck.Shuffle()
[Card[]]$hand1 = $deck.Deal(5)
[Card[]]$hand2 = $deck.Deal(5)
[Card[]]$hand3 = $deck.Deal(5)

从 .NET 程序集预加载类型:using assembly <.NET-assembly-path>

using assembly './YamlDotNet.dll'
using namespace YamlDotNet

$yamlSerializer = [Serialization.Serializer]::new()

$info = [ordered]@{
  Inventory = @(
    @{ Name = 'Apples' ; Count = 1234 }
    @{ Name = 'Bagels' ; Count = 5678 }
  )
    CheckedAt = [datetime]'2023-01-01T01:01:01'
}

$yamlSerializer.Serialize($info)

PowerShell 中执行 .net 类库。Powershell脚本一个比较强大的功能是可以直接调用.net类库(ps core能调用.net core类库),除了调用系统类库外,也可以调用自己编写的类库,从而扩充我们脚本的功能。本文这里简单的介绍下如何调用.net类库的方法:

namespace ClassLibrary1
{
    public class Class1
    {
        public static void SayHello()
        {
            Console.WriteLine($"hello {DateTime.Now}");
        }
    }
}

首先我们编写一个简单的函数

将其编译为dll,然后在 PowerShell中 就可以使用它了。

Add-Type -Path "ClassLibrary1.dll"
[ClassLibrary1.Class1]::SayHello()

powershell 中的写法还比较灵活,下面的这个方式也是可以的。

using assembly "ClassLibrary1.dll"
using namespace ClassLibrary1
[Class1]::SayHello()

如果不创建新的 PowerShell 类,请 Add-Type 改用 cmdlet。 有关详细信息,请参阅 Add-Type。

Get-TypeData:获取当前会话中的扩展类型数据。( 获取已经加载的命名空间 )

示例 1:获取所有扩展类型数据
此示例获取当前会话中的所有扩展类型数据:Get-TypeData


示例 2:按名称获取类型数据
此示例获取当前会话中名称使用“System.IO”限定的所有类型数据。
Get-TypeData -TypeName System.IO.*


示例 3:获取创建属性值的脚本块
此示例获取创建 EventLogEntry 对象的 EventID 属性值的脚本块。
(Get-TypeData *EventLogEntry*).Members.EventID


示例 4:获取为指定对象定义属性的脚本块
此示例获取在 PowerShell 中定义 System.DateTime 对象的 DateTime 属性的脚本块。


(Get-TypeData -TypeName System.DateTime).Members["DateTime"].GetScriptBlock
if ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq  "Date") {
    "{0}" -f $this.ToLongDateString()
}
elseif ((& { Set-StrictMode -Version 1; $this.DisplayHint }) -ieq "Time") {
    "{0}" -f  $this.ToLongTimeString()
}
else {
    "{0} {1}" -f $this.ToLongDateString(), $this.ToLongTimeString()
}

命令使用 Get-TypeData cmdlet 获取 System.DataTime 类型的扩展类型数据。 该命令将获取 TypeData 对象的 Members 属性。

Members 属性包含由扩展类型数据定义的属性和方法的哈希表。 Members 哈希表中的每个键均为某个属性或方法名称,每个值均为该属性或方法值的定义。

命令获取 Members 中的 DateTime 键及其 GetScriptBlock 属性值。

输出显示创建 PowerShell 中每个 System.DateTime 对象的 DateTime 属性值的脚本块。

使用 .NET 的类型名称很麻烦,因为这些名字很长。以下是一个例子:
Add-Type -AssemblyName System.Speech
$speak = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer
$speak.Speak('Hello I am PowerShell!')

在 PowerShell 中使用 .NET 命名空间时, using namespace 语句必须放在脚本的开头。
此时代码的可读性变得更好,并且 using 语句明确了该脚本使用了哪些 .NET 命名空间:
using namespace System.Speech.Synthesis
Add-Type -AssemblyName System.Speech
$speak = New-Object -TypeName SpeechSynthesizer
$speak.Speak('Hello I am PowerShell!')

命名空间 System.IO.Path .NET 包含一系列有用的路径工具方法。
一些例子:
[System.IO.Path]::ChangeExtension('test.txt', 'bat')
[System.IO.Path]::GetExtension('test.txt')

现在可以不必重复地使用 [System.IO.Path] 来访问这些方法。
添加一句 using namespace System.IO 语句之后就可以直接访问 [Path] 类型:
using namespace System.IO
[Path]::ChangeExtension('test.txt', 'bat')
[Path]::GetExtension('test.txt')

PowerShell 在线教程

认识Powershell

  • 介绍和安装
  • 自定义控制台
  • 快速编辑模式和标准模式
  • 快捷键
  • 管道和重定向

Powershell交互式

  • 数学运算
  • 执行外部命令
  • 命令集
  • 别名
  • 通过函数扩展别名
  • 执行文件和脚本

Powershell变量

  • 定义变量
  • 自动化变量
  • 环境变量
  • 驱动器变量
  • 变量的作用域
  • 变量的类型和强类型
  • 变量的幕后管理

Powershell数组和哈希表

  • 命令返回数组
  • 创建数组
  • 访问数组
  • 复制数组
  • 强类型数组
  • 使用哈希表

Powershell管道

  • 使用管道
  • 对象转换成文本
  • 排序和分组
  • 过滤管道结果
  • 分析和比较管道结果
  • 导出管道结果
  • 扩展类型系统

Powershell使用对象

  • 对象=属性+方法
  • 属性(对象是什么)
  • 方法(对象能做什么)
  • 使用真实的对象工作
  • 调用静态方法
  • 创建对象

Powershell条件判断

  • 条件表达式
  • Where-Object
  • IF-ElseIf-Else
  • Switch

Powershell循环

  • ForEach-Object
  • Foreach
  • Do While
  • For
  • Switch

Powershell函数

  • 定义新函数
  • 处理函数的参数
  • 指定函数的返回值
  • 查看支持的函数
  • 函数 过滤器 管道

Powershell脚本

  • 编写和运行脚本
  • 给脚本传递参数
  • 增强脚本的可读性
  • 创建管道脚本
  • 自动执行脚本之profile
  • 脚本的数字签名

Powershell错误处理

  • what-if
  • 定义容错度
  • 识别和处理异常
  • 错误记录:详细错误
  • 理解异常
  • 在函数和脚本中捕获异常
  • 断点执行

Powershell命令发现和脚本块

  • 发现命令
  • 调用操作符
  • 使用语句块
  • 执行上下文

Powershell文本和正则表达式

  • 定义文本
  • 使用特殊文本命令

    • 字符串操作符
      • 格式化字符串
      • 设置数字格式
      • 固定宽度的制表输出
    • String 对象方法
    • String 类方方法
  • 简单模式匹配
  • 正则表达式

    • 定义模式
    • 同时搜索不同的词语
    • 大小写敏感
    • 在文本中搜索信息
    • 搜索不同的关键字
    • 深入使用子表达式
    • 贪婪与非贪婪匹配
    • 搜索字符串片段
    • 替换字符串
    • 使用反向引用
    • 在文本行的开始插入文本
    • 删除多余的空格
    • 搜索和移除重复的单词
    • 非捕获组
  • 文本处理实例

    • 文本处理实例(一)
    • 文本处理实例(二)
    • 文本处理实例(三)
    • 文本处理实例(四)

PowerShell处理XML

  • XML 结构
  • 加载和处理XML文件
  • 浏览扩展类型系统

PowerShell文件系统

  • 前言
  • 访问文件和目录
  • 导航文件系统
  • 使用目录和文件工作
  • 管理访问权限

PowerShell注册表

  • 操作注册表的几条重要命令
  • “提供程序”文件系统以外的位置
  • 搜索注册表
  • 创建和删除键值
  • 注册表权限

PowerShell教程 - 编程结构(Program Struct)

PowerShell教程 - 汇总:https://www.cnblogs.com/cqpanda/category/2145620.html

第一部分(变量、作用域、数组、hash表(键值对))

:https://www.cnblogs.com/cqpanda/p/16589951.html

第二部分(字符串、math、列表、字典、队列、栈、日期、创建对象)

:https://www.cnblogs.com/cqpanda/p/16589954.html

第三部分(预定义变量、环境变量、输入、输出、各种运算、正则)

:https://www.cnblogs.com/cqpanda/p/16589955.html

第四部分(分支语句、循环语句、函数)

:https://www.cnblogs.com/cqpanda/p/16589959.html

第五部分(创建类[封装、继承、多态]、正则、事件、管道、程序集)

:https://www.cnblogs.com/cqpanda/p/16589957.html

利用 powershell 做渗透

Powershell 攻击指南 ---- 黑客后渗透之道

黑客如何玩powershell脚本

:https://github.com/rootclay/Powershell-Attack-Guide

:https://www.wenjiangs.com/doc/heg6wwey

  1. powershell 基础语法
  2. powershell 脚本编写与调用执行
  3. powershell 的Socket编程
  4. powershell 端口扫描与服务爆破
  5. powershell 多线程
  6. powershell 操作wmi与.net
  7. powershell 操作win32API
  8. powershell 操作Dll注入&shellcode注入&exe注入
  9. powershell 混淆
  10. powershell 事件日志
  11. powershell 实例使用场景
  12. Powershell 渗透工具集

Powershell攻击指南黑客后渗透之道系列:https://www.anquanke.com/subject.html?id=90541

  • ​Powershell攻击指南黑客后渗透之道系列 --- 基础篇:https://www.anquanke.com/post/id/87976
  • Powershell攻击指南黑客后渗透之道系列 --- 进阶利用:https://www.anquanke.com/post/id/88851
  • Powershell攻击指南黑客后渗透之道系列 --- 实战篇:https://zhuanlan.zhihu.com/p/31793425


http://www.ppmy.cn/news/438831.html

相关文章

03-SNAP处理Sentinel-2 L2A级数据(一)

转载自&#xff1a;https://blog.csdn.net/lidahuilidahui/article/details/102765420 03-SNAP处理Sentinel-2 L2A级数据&#xff08;一&#xff09; 前言云检测 云检测方法去云方法 掩膜法 再谈Sen2Cor插件叠加掩膜图层合成法 Sen2Three插件重采样操作 法一&#xff1a;使用…

unity绘制管道_【译文】unity可编程渲染管道#1——自定义管道

前言 Scriptable Render Pipeline定制流水线控制渲染创建管道资产和实例。剔除&#xff0c;过滤&#xff0c;排序&#xff0c;渲染。保持记忆清洁。提供良好的编辑体验。这是涵盖Unity可编写脚本的渲染系列教程的第一部分管道。本教程假设您首先完成了基础知识系列&#xff0c;…

AI视觉在教育场景中的创新应用

正文字数&#xff1a;4312 阅读时长&#xff1a;7 分钟 本次LiveVideoStackCon 2020线下北京峰会我们邀请到了360AI影像事业部总经理张焰老师来做分享&#xff0c;他会为我们带来目前AI视觉在教育中的创新应用&#xff0c;包括课堂专注度、课堂接受度、疲劳提醒、姿态纠正等在…

【ChatGPT+XMind超级详细的保姆级思维导图教程】

&#x1f680; AI &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;CSDN…

离散数学题目收集整理练习(期末过关进度80%~100%)完结撒花

✨博主&#xff1a;命运之光 &#x1f984;专栏&#xff1a;离散数学考前复习&#xff08;知识点题&#xff09; &#x1f353;专栏&#xff1a;概率论期末速成&#xff08;一套卷&#xff09; &#x1f433;专栏&#xff1a;数字电路考前复习 &#x1f31f;博主的其他文章&…

走在时代前沿:宝洁的柔性供应链战略及其对全球快消品市场的影响

01 先进的供应链计划不断推动宝洁引领全球快速消费品市场 宝洁公司&#xff08;Procter & Gamble&#xff09;成立于1837年&#xff0c;是全球知名的消费品公司&#xff0c;公司拥有多个知名品牌&#xff0c;如宝洁、海飞丝、汰渍、奥妙、潘婷、威露士等&#xff0c;这些产…

一台服务器最大能支持多少条 TCP 连接

一、一台服务器最大能打开的文件数 1、限制参数 我们知道在Linux中一切皆文件&#xff0c;那么一台服务器最大能打开多少个文件呢&#xff1f;Linux上能打开的最大文件数量受三个参数影响&#xff0c;分别是&#xff1a; fs.file-max &#xff08;系统级别参数&#xff09;&a…

【gitflow】 概念基本介绍

gitflow 简介 什么是gitflow&#xff1f; 我们大家都很会用git&#xff0c;但是我们很少去关心我们要怎么用branch和版本控制。 只知道master是第一个主分支&#xff0c;其他分支都是次要分支&#xff0c; 那你知道如下的问题如何回答吗&#xff1f; 如何保证主分支的稳定…