PowerShell 技能连载 - 创建快速的 Ping(第一部分)
Ping 是一个常见的任务。类似 Test-Connection
等 PowerShell cmdlet 可以进行 Ping 操作,但没有超时限制,所以当您尝试 ping 一台离线的主机时,可能要比较长时间才能得到结果。
WMI 支持带超时的 ping 操作。以下是使用方法:
1 | $ComputerName = 'microsoft.com' |
状态码 0 代表成功,其它代码代表失败。
Ping 是一个常见的任务。类似 Test-Connection
等 PowerShell cmdlet 可以进行 Ping 操作,但没有超时限制,所以当您尝试 ping 一台离线的主机时,可能要比较长时间才能得到结果。
WMI 支持带超时的 ping 操作。以下是使用方法:
1 | $ComputerName = 'microsoft.com' |
状态码 0 代表成功,其它代码代表失败。
假设您下载了 PowerShell 的帮助文件,有一个获取各类 PowerShell 主题的快捷方法:
首先,确保您下载了帮助文件:以管理员权限启动 PowerShell,并且运行以下代码:
1 | Update-Help -UICulture en-us -Force |
下一步,检查 “about” 主题:
1 | Get-Help about_* |
在 PowerShell ISE 中,您所需要做的是点击 cmdlet 列出的主题,然后按 F1
键。这将产生一个类似这样的命令:
1 | PS> Get-Help -Name 'about_If' -ShowWindow |
在其它编辑器里,例如 VSCode 的 PowerShell 控制台,您需要自己键入命令。它将在 PowerShell 帮助查看器中打开帮助主题。
您也可以搜索指定的帮助主题,例如:
1 | PS> help operator |
在 PowerShell ISE 中,仍然可以点击某个列出的 about 主题,并按 F1 查看它的内容。
技术上,所有 about 主题都是文本文件,它们的位置在这里:
1 | PS> explorer $pshome\en-us |
Select-Object
是一个基础的 cmdlet,多数 PowerShell 用户都经常使用它。然而,它有一些限制,不太为大家所知。
Select-Object
最常见的形式是选择可见的属性。如果不使用 Select-Object
,那么 PowerShell 将自行决定该显示哪些属性,以及它们的格式:
1 | Get-ChildItem -Path c:\windows\system32 -Filter *.dll |
如果加上了 Select-Object
,您可以自行决定哪些属性可见。例如:
1 | Get-ChildItem -Path c:\windows\system32 -Filter *.dll | |
Select-Object
还可以将属性的内容向上提升一层。在前一个例子中,VersionInfo
包含另一个对象。通过使用 -ExpandProperty
属性,您可以将它的属性向上提升一层:
1 | Get-ChildItem -Path c:\windows\system32 -Filter *.dll | |
要查看合并属性的实际结果,请将结果再次发送给 Select-Object
,因为 PowerShell 默认情况下只显示其中的一部分结果:
1 | Get-ChildItem -Path c:\windows\system32 -Filter *.dll | |
除了 “*” 之外,您还可以用逗号分隔的列表来决定要查看的属性:
1 | Get-ChildItem -Path c:\windows\system32 -Filter *.dll | |
Windows 注册表中的 RunOnce
键存储了所有的自启动。它可能是空的。要检查自启动的应用程序请试试这段代码:
1 | $path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce' |
再次申明,这个键可能没有内容。如果它有内容,那么每个自启动程序都有它自己的值和名字。如果只要读取自启动程序的路径,请用 GetValueNames()
读取这个注册表键。它能够读取注册表值的名称。然后通过 GetValue()
读取实际的值:
1 | $path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce' |
以下是另一小段用于生成由指定数量的大小写字母、数字,和特殊字符组成的随机密码:
1 | $length = 10 |
以下是一个有趣的 PowerShell 脚本,名为 Convert-PowerShellToBatch
。将 PowerShell 脚本的路径作为参数传给它,或者将 Get-ChildItem
的执行结果用管道传给它,来批量执行多个脚本。
该函数为每个脚本创建一个批处理文件。当您双击批处理文件时,将执行 PowerShell 代码。
1 | function Convert-PowerShellToBatch |
当您查看某个生成的脚本文件时,您会发现 PowerShell 代码被转换为 BASE64 编码的字符串。所以这种转换适用于许多真实世界的需求:
申明:BASE64 并不是加密。将 BASE64 编码的文本转换为可读的明文是很简单的事。所以这里用的技术不适合用来隐藏秘密,例如密码。
假设您想创建一个函数,接受一个文件路径参数。文件可以进行许多操作。您可能希望拷贝文件,压缩文件,将它们设置为隐藏文件,或其它各种操作。我们在这里并不关注具体需要做什么操作。我们希望关注 PowerShell 函数如何接受文件参数。
您应该遇到过这样的函数:
1 | function Process-File |
结果看起来类似这样:
1 | PS> Process-File -Path C:\windows\explorer.exe |
这个函数每次只处理一个路径。如果希望传入多个路径,您需要这样做:
1 | function Process-File |
现在,您的函数可以接受任意多个逗号分隔的路径。如果您希望也能从管道输入路径呢?需要增加这些代码:
1 | function Process-File |
基本上,您现在有两个嵌套的循环:process {}
是管道对象使用的循环,而其中的 foreach
循环处理用户传入的的字符串数组。
如果您希望 Get-ChildItem
提供路径给函数呢?它并不是返回字符串。它返回的是文件系统对象,而且在对象之内,有一个名为 “FullName” 的属性,存储对象的路径。以下是您要做的:
1 | function Process-File |
现在,这个函数不止能接受管道传来的字符串 (ValueFromPipeline),而且还能接受有某个属性名或别名与参数 (Path) 相似的对象 (ValueFromPipelineByPropertyName)。任务完成了。您的函数现在能够为用户提供最大的灵活性,这基本上也是 cmdlet 所做的事。
WMI 是一个丰富的信息库——如果您知道 WMI 的类名:
1 | Get-CimInstance -ClassName Win32_BIOS |
如果您想探索 WMI 的内容,那么以下代码会十分便利。Find-WmiClass
接受一个简单的关键字,例如 “video”、”network”、”ipaddress”。接下来它可以获取所有类名、某个属性名或方法名包含该关键字的 WMI 类。
1 | function Find-WmiClass |
接下来用户可以选择某个找到的类,该代码将显示这个类的实际实例。
声明:有部分类有几千个实例,例如 CIM_File。当选择了一个有这么多实例的 WMI 类时,该脚本将执行很长时间才能完成。
以下代码查找某个 Active Directory 用户属于哪些组(包括嵌套的组成员)。该代码需要 ActiveDirectory 模块。
1 | #requires -Module ActiveDirectory |
要查找组成员,只需要执行 Get-NestedGroupMember
,跟上用户名即可。该函数和 Get-ADUser
接受同样的身份信息,所以您可以传入 SamAccountName、SID、GUID,或 distinguishedName。
如果您的机器通过不同网络连接,连到了 internet(或 VPN),以下两个函数可能对您有用。
Get-ActiveConnection
列出当前所有获取到 IP 地址的网络连接。Test-ActiveConnection
接受一个关键字并检查是否有一个名字中包含该关键字的活动连接。
1 | function Get-ActiveConnection |
以下是一个快速的演示输出:
1 | PS> Get-ActiveConnection |