PowerShell 技能连载 - 查找一个脚本中的所有变量
在前一个技能中我们掩饰了如何分析一段脚本块的内容并且搜索变量或命令。这种技术也适用于基于文本的脚本。以下脚本将会检查自己并且提取出变量和命令:
1 | $filepath = $PSCommandPath |
请确保将脚本保存到硬盘,或为 $filepath
指定一个不同的实际存在的脚本路径。
在前一个技能中我们掩饰了如何分析一段脚本块的内容并且搜索变量或命令。这种技术也适用于基于文本的脚本。以下脚本将会检查自己并且提取出变量和命令:
1 | $filepath = $PSCommandPath |
请确保将脚本保存到硬盘,或为 $filepath
指定一个不同的实际存在的脚本路径。
要分析一个脚本快中的内容,您可以简单地检查 AST,并且,例如创建一个包含代码中所有变量的清单:
1 | $code = { |
如果您想查看所有的命令,请试试以下代码:
1 | $code = { |
这在根据脚本块自动生成文档的时候非常有用。
如果您需要以固定的频率运行一段 PowerShell 脚本,何不以计划任务的方式运行它呢?以下是一段帮您新建一个每天上午 6 点执行一个 PowerShell 脚本的计划任务的代码:
1 | #requires -Modules ScheduledTasks |
以下是一种快速查看 PowerShell 函数源码的方法:
1 | ${function:Clear-Host} | clip |
这将会把 Clear-Host
的源代码复制到剪贴板中,并且当您粘贴它时,您可以看到 Clear-Host
是如何工作的:
1 | $RawUI = $Host.UI.RawUI |
通常可以从这里学到很多东西。如果您想用非空格的字符填充 PowerShell 控制台,例如绿底白字的 ‘X’,请试试这段代码:
1 | $host.UI.RawUI.SetBufferContents( |
请注意这只能在真正的 PowerShell 控制台宿主中起作用。
在 PowerShell 控制台中,您仍然可以用 more 管道,就像在 cmd.exe 中一样一页一页查看结果。然而,more 不支持实时管道,所以所有数据需要首先收集好。这将占用很长时间和内存:
1 | dir c:\windows -Recurse -ea 0 | more |
一个更好的方法是使用 PowerShell 自带的分页功能:
1 | dir c:\windows -Recurse -ea 0 | Out-Host -Paging |
请注意这些都需要一个真正的控制台窗口,而在图形界面的宿主中不能工作。
以下几行代码能在远程服务器上创建一个 SMB 共享:
1 | #requires -Version 3.0 -Modules CimCmdlets, SmbShare -RunAsAdministrator |
您可以在客户端将该共享映射为一个网络驱动器。请注意这个网络共享是单用户的,所以如果您使用 Administrator 账户做了映射,那么无法在 Windows Explorer 中存取。
1 | $computername = 'Server12' |
以下是一个重要的 PowerShell 变量的列表:$pshome
表示 PowerShell 所在的位置。$home
是个人用户配置文件夹的路径。$PSVersionTable
返回 PowerShell 的版本和重要的子组件的版本:
1 | PS> $pshome |
$profile
是您个人的自启动脚本所在的位置。每当您当前的 PowerShell 宿主启动时,自启动脚本就会自动加载(假设文件存在)。$profile.CurrentUserAllHosts
是任何宿主都会加载的配置文件脚本。并且 $env:PSModulePath
列出 PowerShell 可以自动发现的存放 PowerShell module 的文件夹:
1 | PS> $profile |
使用 Read-Host 向用户提示输入信息可能会造成问题,因为它影响了脚本的自动化运行。一个更好的方法是将 Read-Host
包装在 param()
代码块中。通过这种方式,该信息可以通过无人值守操作的参数传入,也可以通过交互式提示传入:
1 | param |
当您运行以上脚本时,它像 Read-Host
一模一样地显示提示信息。您也可以通过参数执行该脚本:
1 | PS> C:\myscript.ps1 –Name test –Id 12 |
If you do not need custom prompting, you can go even simpler, and declare parameters as mandatory by adding [Parameter(Mandatory)] above each parameter variable.
如果您不需要自定义提示信息,您还可以更加简单,只需要在每个参数变量上加上 [Parameter(Mandatory)]
使它们变为必需参数。
如果您的客户端没有和您的域控制器正常地同步时间,请使用以下代码。这段代码需要管理员特权:
1 | w32tm.exe /resync /force |
PowerShell 提供很多种方式来连接到 SMB 文件共享。以下是三种不同的方法:
1 | # adjust path to point to your file share |
Net.exe 是最多功能的方法,在 PowerShell 的所有版本中都有效。通过传入一个 “*”,它自动选择下一个有效的驱动器盘符。
New-PSDrive
从 PowerShell 3 起支持 SMB 共享。New-SmbMapping
需要 SmbShare 模块并且现在看来有点古怪:重启后才能在 Windows Explorer 中显示该驱动器。