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()
}

PowerShell 技能连载 - 播放 WAV 文件

适用于 PowerShell 所有版本

以下是一个简单的用 PowerShell 播放 WAV 声音文件的方法:

# 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
"Playing $WAVPath..."

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

"Done!"

这段脚本的第一部分在 Windows 文件夹中查找第一个 WAV 文件。当然,您可以将您喜欢的 WAV 文件路径赋给 $WAVFile

下一步, Media.SoundPlayer 读取并播放 WAV 文件。请注意 Play() 如何播放声音:它在一个单独的线程中播放,而 PowerShell 将会立即继续运行。

您可以用这种方法来创建一个有声的进度条:当 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()

现在,PlayLooping() 用于循环播放声音。该声音会一直播放下去,所以您需要手动调用 Stop()。这是脚本结束的时候需要做的事情。

PowerShell 技能连载 - PowerShell ISE 自动化

适用于 PowerShell 3.0 及以上版本

PowerShell ISE 是可以通过 $psISE 脚本化编程的。这个变量只在 PowerShell ISE 环境中有效。

要获得当前可见的脚本内容,请试试以下代码:

PS> $psise.CurrentFile.Editor.Text

这段代码可以实现一个简单的重命名方法,将 PowerShell ISE 当前打开的脚本中的 所有 “testserver” 替换成 “productionserver”(前提是在您当前的脚本代码中有一系列 “testserver” 字眼出现):

$psise.CurrentFile.Editor.Text = $psise.CurrentFile.Editor.Text -replace 'testserver', 'ProductionServer'