PowerShell 技能连载 - 查找 PowerShell 缺省变量(第一部分)
有些时候识别出 PowerShell 管理的缺省变量十分有用,这样能帮您区分内置的变量和自定义的变量。Get-Variable
总是输出所有的变量。
以下是一个简单的技巧,使用一个独立、全新的 PowerShell 运行空间来确定内置的 PowerShell 变量:
1 | # create a new PowerShell |
当您运行这段代码时,该代码输出找到的变量数量,以及这些变量。
有些时候识别出 PowerShell 管理的缺省变量十分有用,这样能帮您区分内置的变量和自定义的变量。Get-Variable
总是输出所有的变量。
以下是一个简单的技巧,使用一个独立、全新的 PowerShell 运行空间来确定内置的 PowerShell 变量:
1 | # create a new PowerShell |
当您运行这段代码时,该代码输出找到的变量数量,以及这些变量。
从 PowerShell 5 开始,您可以定义 PowerShell 类。它们是动态定义的,并且存在于内存中。那么要如何知道这些类的名字?
我们首先定义一个简单的,没有任何内容的类:
1 | class TestClass |
如何确认内存中确实存在一个名为 “TestClass” 的类?以下是一个名为 Get-PSClass
的工具函数:
1 | function Get-PSClass($Name = '*') |
执行这个函数后,它会返回当前内存中所有定义的 PowerShell 类(在我们的 PowerShell 例子中,在前几个技能实验中有好几个 PowerShell 类):
1 | PS> Get-PSClass |
您也可以显示地测试一个类名:
1 | PS> Get-PSClass -Name TestClass |
您也可以使用通配符。一下代码将返回所有以 “A” 至 “H” 字母开头的类:
1 | PS> Get-PSClass -Name '[A-H]*' |
从 PowerShell 5 开始,您可以定义 PowerShell 类。您可以使用类来创建新对象,并通过创建一个或多个构造函数,您可以方便地初始化新创建的对象。
让我们看看效果:
1 | class Employee |
这段代码运行后,将创建一个包含三个构造函数的 “Employee” 新类。以下是如何使用新类的方法:
1 | PS> [Employee]::new() |
每次调用都使用一个新的构造函数,并且该类根据需要创建相应的对象。
从 PowerShell 5 开始,您可以定义类。它们有许多应用场景。一个是为有用的工具函数创建一个库来更好地整理它们。要实现这个功能,这个类要定义一些 “static” 方法。以下是一个简单的例子:
1 | class HelperStuff |
“HelperStuff” 类定义了 “GetFirstCharacter
“ 和 “GetFileExtension
“ 两个静态方法。现在查找和使用这些工具函数非常方便:
1 | PS> [HelperStuff]::GetFirstCharacter('Tobias') |
在前一个技能中我们演示了 Get-ItemProperty
无法读取数据错误的注册表键值:
1 | PS> $key = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\History\{35378EAC-683F-11D2-A89A-00C04FBBCFA2}\0" |
有一个变通办法,您可以使用 Get-Item
代替,来存取注册表键,这将使用它的 .NET 成员来读取所有值:
1 | $key = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\History\{35378EAC-683F-11D2-A89A-00C04FBBCFA2}\0" |
结果看起来如下:
1 | Name Value |
有些时候,读取注册表键值可能会失败,提示奇怪的错误信息:
1 | PS> $key = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\History\{35378EAC-683F-11D2-A89A-00C04FBBCFA2}\0" |
当发生这种情况时,用 regedit.exe 检查注册表发现一个或多个键值已破坏。在我们的例子中,”lParam” 的值似乎在所有的 Windows 机器中都是错误的。Regedit.exe 报告“(invalid … value)”。
在这个例子中,Get-ItemProperty
指令并不会读出任何值。您无法也排除该值:
1 | PS> Get-ItemProperty -Path $key -Include * -Exclude lParam |
可以采取的措施是只读取合法的键值:
1 | PS> Get-ItemProperty -Path $key -Name DSPath |
在前一个技能中我们解释了如何在 PowerShell 配置文件中增加个人问候。这个问候信息也可以朗读出来,假设音量打开的情况下。这对所有的 PowerShell 宿主都有效,包括 VSCode。
这将把代码增加到您的配置文件脚本中:
1 | # create profile if it does not yet exist |
要编辑用户配置文件,请运行这段代码:
1 | PS> notepad $profile.CurrentUserAllHosts |
以下是一个在 PowerShell 中接受一个字符串数组并返回一个随机的字符串,可以用作自定义问候语的简单方法:
1 | $greetings = |
您所需要做的只是将这段代码加到您的 profile 脚本,例如这样:
1 | # create profile if it does not yet exist |
完成以后,PowerShell 将会使用自定义信息向您问候。
不久前有一些关于 LINQ,一个 .NET 查询语言,在 PowerShell 中用来提升代码速度的报告。
直到 PowerShell 真正支持 Linq 之前,使用 Linq 是非常冗长的,并且需要使用强类型和没有文档的方法。另外,同样的事可以使用纯 PowerShell 方法来做,速度的提升很少——至少对 IPPro 相关的任务不明显。
以下是一个使用很简单的 Linq 语句对数字求和的测试用例。它接受 Windows 文件夹下的所有文件,然后对所有文件的长度求和:
1 | $numbers = Get-ChildItem -Path $env:windir -File | Select-Object -ExpandProperty Length |
当您运行它多次的时候,您会观察到执行时间的输出。Linq 的方法可以使用,但是对数据类型十分敏感。例如,您需要将数字数组转换为 integer 数组,否则 Linq 的 Sum()
方法将不起作用。
可以提炼出两条法则:
这时不值得使用 Linq,因为它尚未集成到 PowerShell 中,并且会产生难读的代码。它几乎相当于在 PowerShell 使用 C# 源代码。
如果您想提升速度,请在所有可能的地方避免使用管道。foreach 循环的执行速度比用管道将许多对象通过管道传到 ForEach-Object
快许多。
If Linq was better integrated into PowerShell in the future, it would indeed be highly interesting.
When you open a native PowerShell console in Windows 10, you can hold down CTRL+SHIFT, then move your mouse wheel, to adjust console background color transparency, and let other windows shine through. The same works for cmd.exe as well, of course.
当您在 Windows 10 中打开一个原生的 PowerShell 控制台,按下 CTRL
+ SHIFT
键,然后滚动鼠标滚轮,就可以调节控制台背景色的透明度,并且让其它窗口的内容透射出来。当然这对 cmd.exe 也是有效的。