PowerShell 技能连载 - 从注册表中读取文件扩展名关联(第二部分)

适用于 PowerShell 所有版本

在前一个技能里您已学到了如何用单行代码读取多个注册表键。在第二部分中,请试试这段单行代码:

$lookup = Get-ItemProperty Registry::HKCR\.[a-f]?? |
  Select-Object -Property PSChildName, '(default)', ContentType, PerceivedType |
  Group-Object -Property PSChildName -AsHashTable -AsString

这段代码读取注册表 HKCR 中所有以点开头,接下来是三个字母,并且第一个字母必须是 a-f 的键——它的作用是读取所有以 a-f 开头,并且必须是 3 个字符的文件扩展名。

另外,结果通过管道输出到 Group-Object,并且“PSChildName”属性被用作哈希表的键名。

PSChildName 总是返回注册表的键名,在这个例子中代表的是文件的扩展名。

当您运行这行代码时,您可以查询任何已注册的文件扩展名:

PS> $lookup.'.avi'

PSChildName         (default)           ContentType         PerceivedType
-----------         ---------           -----------         -------------
.avi                WMP11.AssocFile.AVI                     video



PS> $lookup.'.fon'

PSChildName         (default)           ContentType         PerceivedType
-----------         ---------           -----------         -------------
.fon                fonfile

请注意这行代码限制了只包括 a-f 开头、三个字母的扩展名。要获取所有的文件扩展名,请使用这个路径:

Registry::HKCR\.*

PowerShell 技能连载 - 从注册表中读取文件扩展名关联(第一部分)

适用于 PowerShell 所有版本

PowerShell 代码可以写得十分紧凑。以下是一个从 Windows 注册表中读取所有文件扩展名关联的单行代码:

Get-ItemProperty Registry::HKCR\.* |
  Select-Object -Property PSChildName, '(default)', ContentType, PerceivedType

请注意这些技巧:Get-ItemProperty 使用了名为“Registry::”的 provider,而不是 PowerShell 提供的注册表驱动器。通过这种方式,您可以使用默认的注册表路径,并且可以存取类似 HKEY_CLASSES_ROOT 这样没有驱动器的 hive。

请注意 Select-Object 如何选择获取注册表值。这里有两个特殊的名字:“(default)”总是代表缺省的注册表值,并且“PSChildName”总是代表当前读取的注册表键名。

由于路径名中的“*”符,该命令将自动读取 HKCR 路径中以点开头的所有键。

PowerShell 技能连载 - 根据类型对数据排序

适用于 PowerShell 所有版本

Sort-Object 是一站式的排序解决方案。如果要对简单数据类型排序,只需要将它通过管道传递给 Sort-Object。如果要对复杂数据类型排序,则需要指定排序所使用的属性:

# sorting primitive data
1,5,2,1,6,3,12,6 | Sort-Object -Unique

# sorting object data
Get-ChildItem -Path c:\windows | Sort-Object –Property name

由于对象的天生原因,PowerShell 自动选择排序的算法。但如果您需要更多的控制呢?

只需要传入一个代码块。在代码块中,$_ 代表需要排序的对象。您可以将它转型为任何期望的类型:

# sorting string as numbers
'1','5','3a','12','6' | Sort-Object -Property { $_ -as [int]  }

# sorting IPv4 addresses as versions
'1.2.3.4', '10.1.2.3', '100.4.2.1', '2.3.4.5', '9.10.11.12' |
  Sort-Object -Property { [version] $_ }

PowerShell 技能连载 - 用 PowerShell 打开网页

适用于 PowerShell 所有版本

假设您希望每天开始时,就用浏览器打开您最喜欢的网站。PowerShell 可以简单地实现这个需求。不过,这要看您是否喜欢自动打开网页。

使用 Start-Process 的时候,您可以通过参数指定选用哪个浏览器,以及提交的 URL 地址:

# starts with a specific browser
Start-Process -FilePath iexplore -ArgumentList www.powershellmagazine.com

这将在 Internet Explorer 中打开网站,而不是选用缺省的浏览器设置。

不过,它总是打开一个新的浏览器实例。请看另一种实现方式:

# starts with default browser and adds to open browser
Start-Process -FilePath www.tagesschau.de

这段代码中,我们将一个 URL 当做一个“可执行程序”,Windows 就会使用缺省的浏览器。如果缺省浏览器已经打开了,将在其中打开一个新的标签页,而不是打开一个新的浏览器窗口。

要让 PowerShell 在启动时自动打开网页,请确保 $profile 指向的文件路径存在。下一步,打开该脚本,并添加启动命令。

PowerShell 技能连载 - 检查网站的响应(和执行时间)

适用于 PowerShell 3.0 及以上版本

有些时候了解一个命令的执行时间是十分重要的。例如,要监控网站的响应时间,您可以使用 Invoke-WebRequest。用 Measure-Command 来测量执行的耗时。

$url = 'http://www.powershell.com'


# track execution time:
$timeTaken = Measure-Command -Expression {
  $site = Invoke-WebRequest -Uri $url
}

$milliseconds = $timeTaken.TotalMilliseconds

$milliseconds = [Math]::Round($milliseconds, 1)

"This took $milliseconds ms to execute"

它返回一个 TimeSapn 对象,该对象包含了一个 “TotalMilliseconds“ 属性。使用 “Math“ 类提供的 Round() 方法将结果四舍五入。在这例子中,毫秒值被精确到小数点后 1 位。

PowerShell 技能连载 - 展开对象数据结构

适用于 PowerShell 3.0 及以上版本

对象有可能包含嵌套的属性,您所关心的数据可能在一个对象中的“某个地方”。

要显示某个对象的所有属性和展开后的子属性,可将它转换为 JSON。这能很好地以文本的方式展现嵌套的属性。

这个例子获取当前的 PowerShell 进程,然后将它转化为 JSON,然后将文本输出到剪贴板。然后就可以将内容粘贴到任意的文本编辑器:

Get-Process -Id $pid  | ConvertTo-Json | clip.exe

要控制递归的深度,请使用 ConvertTo-Json 命令的 -Depth 参数。缺省值是 2(所以最多显示 2 层递归深度的内容)。

PowerShell 技能连载 - 禁止确认信息

适用于 PowerShell 所有版本

某些 cmdlet(例如 Remove-ADGroupMember)会自动提示确认信息。这在无人值守的脚本中会有问题。

要禁用这些不需要的确认对话框,请显式将 -Confirm 开关参数设置为 false

Remove-ADGroupMember -Identity 'Domain Admins' -Members user12 -Confirm:$false

或者,您可以修改安全级别。PowerShell 将会自动读取该设置。这行代码将所有 cmdlet 的自动确认关闭:

$ConfirmPreference = 'None'

请注意两个技能都只对缺省的确认对话框有效。如果一个 cmdlet 以 PowerShell 确认框架之外的方式提示确认,您需要参阅 cmdlet 的文档来查找如何禁止它的方法。

PowerShell 技能连载 - 随时获取 cmdlet 的帮助

适用于 PowerShell 3.0 及以上版本

从 PowerShell 3.0 开始,帮助文件不在随着 PowerShell 发布。相反,您需要通过 Update-Help 来下载它们,并且由于帮助文件是存储在(受保护的)PowerShell 文件夹中,所以一个普通用户无法实现该操作。

将来您需要某个 cmdlet 的帮助时,只需要直接使用在线版即可。以下代码将通过浏览器访问 Get-Process 的在线帮助(假设您有 Internet 连接):

PS> help Get-Process -Online

安装了帮助文件之后,在 PowerShell ISE 中获得帮助变得更容易了:只需要点击任何 cmdlet 名称,然后按 F1 键。

如果仔细观察,会发现当按下 F1 时,实际上是帮您输入了帮助命令。所以如果需要同样的操作方便性,但是显示的是在线的帮助,您以实现一个类似这样的函数:

function Get-Help($Name) { Get-Help $Name -Online }

然而,这可能会导致死循环,因为新创建的 Get-Help 会在内部调用自己。要让它正常工作,您需要您的函数内部是采用类似这样的方式调用原始的 Get-Help cmdlet:

function Get-Help($Name) { Microsoft.PowerShell.Core\Get-Help $Name -Online }

当您运行这个函数是,您可以点击 PowerShell ISE 中的任意 cmdlet 名称,然后按 F1 键,就能够访问该 cmdlet 的在线解释——忽略您本机安装的帮助文件。

PowerShell 技能连载 - 检测 Wi-Fi 适配器和电源

适用于 Windows 8.1/Server 2012 R2

Windows 8.1 和 Server 2012 R2 带来了一系列好用的网卡管理 cmdlet。例如当您希望调查 Wi-Fi 连接问题时,或是检查为什么 Wake-On-LAN 功能未能唤醒机器时,检查网卡电源管理设置就十分有意思了。

现在是小菜一碟了:

PS> Get-NetAdapter

Name                      InterfaceDescription                   ifIndex Status

----                      --------------------                    ------- -----
Bluetooth-Netzwerkverb... Bluetooth-Gerät (PAN)                         7 Di...
WiFi                      Intel(R) Wireless-N 7260                      3 Up



PS> Get-NetAdapter -Name WiFi

Name                      InterfaceDescription                   ifIndex Status

----                      --------------------                    ------- -----
WiFi                      Intel(R) Wireless-N 7260                      3 Up

只要您知道网卡的名称,那么查询它电源管理设置的方法是:

PS> Get-NetAdapter -Name WiFi | Get-NetAdapterPowerManagement


InterfaceDescription    : Intel(R) Wireless-N 7260
Name                    : WiFi
ArpOffload              : Enabled
NSOffload               : Enabled
RsnRekeyOffload         : Enabled
D0PacketCoalescing      : Enabled
SelectiveSuspend        : Unsupported
DeviceSleepOnDisconnect : Disabled
WakeOnMagicPacket       : Enabled
WakeOnPattern           : Enabled

请注意您需要管理员权限来查看电源管理设置,否则会得到一个误导性的错误信息,提示设备工作不正常。

PowerShell 技能连载 - 用 Finally 来处理关键的清理任务

适用于 PowerShell 2.0 及以上版本

在前一个技能中我们介绍了一个“有声的进度条”,它能令 PowerShell 在忙时播放一段声音。以下还是那段代码:

# find first available WAV file in Windows folder
$WAVPath = Get-ChildItem -Path $env:windir -Filter *.wav -Recurse -ErrorAction SilentlyContinue |
  Select-Object -First 1 -ExpandProperty FullName


# load file and play it

$player = New-Object Media.SoundPlayer $WAVPath
$player.PlayLooping()

1..100 | ForEach-Object {
  Write-Progress -Activity 'Doing Something. Hang in' -Status $_ -PercentComplete $_
  Start-Sleep -MilliSeconds (Get-Random -Minimum 300 -Maximum 1300)
  }
$player.Stop()

这个脚本工作是正常的——除非您把它中断,例如按下 CTRL+C。如果按下这个组合键,脚本立即停止执行,并且 $player.Stop() 没有机会执行所以没有机会停止声音。

这就使用 PowerShell 中的 finally() 最为合适。它确保一个脚本退出前执行清理代码:

# find first available WAV file in Windows folder
$WAVPath = Get-ChildItem -Path $env:windir -Filter *.wav -Recurse -ErrorAction SilentlyContinue |
Select-Object -First 1 -ExpandProperty FullName


# load file and play it

$player = New-Object Media.SoundPlayer $WAVPath

try
{

  $player.PlayLooping()

  1..100 | ForEach-Object {
    Write-Progress -Activity 'Doing Something' -Status $_ -PercentComplete $_
    Start-Sleep -MilliSeconds (Get-Random -Minimum 300 -Maximum 1300)
  }
}

finally
{
  $player.Stop()
}