PowerShell 技能连载 - 获取指定扩展名的文件

适用于 PowerShell 所有版本

当您使用 Get-ChildItem 来获取一个文件列表时,您可能会注意到 -Filter 参数有时候会导致返回比你预期的更多的文件。

以下是一个例子。这段代码并不只是返回“.ps1”扩展名的文件,而也会返回“.ps1xml”扩展名的文件:

Get-ChildItem -Path C:\windows -Recurse -ErrorAction SilentlyContinue -Filter *.ps1

要限制只返回您需要的扩展名的文件,请用一个 cmdlet 来过滤结果:

Get-ChildItem -Path C:\windows -Recurse -ErrorAction SilentlyContinue -Filter *.ps1 |
  Where-Object { $_.Extension -eq '.ps1' }

这将只返回您指定的扩展名的文件。

PowerShell 技能连载 - 修正 ISE 的编码

适用于所有 PowerShell 版本

当您在 ISE 编辑器中运行一个控制台程序时,非标准字符,例如“ä”或“ß”将会显示不正常。要修正 ISE 和隐藏的控制台之间通信的编码,请使用这段代码:

# Repair encoding. This REQUIRES a console app to run first because only
# then will ISE actually create its hidden background console

$null = cmd.exe /c echo
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8

# Now all is fine

cmd.exe /c echo ÄÖÜäöüß

PowerShell 技能连载 - 使用“打开文件”对话框

适用于 PowerShell 3.0 及以上版本

以下是一个快捷的函数,可以用在 ISE 编辑器和 PowerShell 控制台中(适用于 PowerShell 3.0 及以上版本):Show-OpenFileDialog

function Show-OpenFileDialog
{
  param
  (
    $StartFolder = [Environment]::GetFolderPath('MyDocuments'),

    $Title = 'Open what?',

    $Filter = 'All|*.*|Scripts|*.ps1|Texts|*.txt|Logs|*.log'
  )


  Add-Type -AssemblyName PresentationFramework

  $dialog = New-Object -TypeName Microsoft.Win32.OpenFileDialog


  $dialog.Title = $Title
  $dialog.InitialDirectory = $StartFolder
  $dialog.Filter = $Filter


  $resultat = $dialog.ShowDialog()
  if ($resultat -eq $true)
  {
    $dialog.FileName
  }
}

这个函数将打开一个“打开文件”对话框。用户可以选择一个文件,并且选择的文件对象将返回给 PowerShell。所以下次您的脚本需要打开一个 CSV 文件时,您可能就能用上。

PowerShell 技能连载 - 用 Group-Object 来创建哈希表

适用于所有 PowerShell 版本

Group-Object 能把对象输送到管道中,然后在一个管道中把属性相同的对象排在一起。

这个功能十分有用,特别是当您用 Group-Object 来返回哈希表时。它将生成一个按服务状态分组的哈希表:

$hash = Get-Service |
  Group-Object -Property Status -AsHashTable -AsString

您现在可以通过这种方式获取所有正在运行(或已停止的)服务:

$hash.Running
$hash.Stopped

可以用任何想要的属性来分组。这个例子将用三个组来分组文件:一组为小文件,一个组为中等文件,另一个组位大文件。

$code =
{
  if ($_.Length -gt 1MB)
  {'huge'}
  elseif ($_.Length -gt 10KB)
  {'average'}
  else
  {'tiny'}
}

$hash = Get-ChildItem -Path c:\windows |
  Group-Object -Property $code -AsHashTable -AsString


#$hash.Tiny
$hash.Huge

PowerShell 技能连载 - 用 PowerShell 来励志

适用于所有 PowerShell 版本

编写 PowerShell 代码是十分带劲的,但是某些时候会令人感到沮丧。这是一个用 PowerShell 来励志的函数。只需要打开音箱,PowerShell 会在您执行每一条命令之后鼓励你。

function prompt
{
  $text = 'You are great!', 'Hero!', 'What a checker you are.', 'Champ, well done!', 'Man, you are good!', 'Guru stuff I would say.', 'You are magic!'
  'PS> '
  $host.UI.RawUI.WindowTitle = Get-Location
  (New-Object -ComObject Sapi.SpVoice).Speak(($text | Get-Random))
}

PowerShell 技能连载 - 记录脚本做了什么事

适用于所有 PowerShell 版本

您应该知道在 PowerShell 控制台(不是 ISE 编辑器)中,您可以打开记录功能:

PS> Start-Transcript

这将会把所有键入的命令以及所有的命令执行结果都记录到一个文件中。不幸的是,当您运行一个脚本的时候,作用就受限了,因为您无法看到实际的脚本命令。

以下是一个激进的技巧,能够记录包括所有脚本中执行的命令。在您尝试这个技巧之前,请注意这将增加您的日志文件大小并且会导致脚本执行变慢,因为在循环体中,每一次循环都会被记录下来。

只要执行这行代码就可以打开脚本命令记录了:

PS> Set-PSDebug -Trace 1

PowerShell 技能连载 - 有趣的声音提示

适用于所有 PowerShell 版本

如果您的计算机装有声卡,那么这段代码可以让您的同事们吓一跳:

function prompt
{
  1..3 | ForEach-Object {
    $frequency = Get-Random -Minimum 400 -Maximum 10000
    $duration = Get-Random -Minimum 100 -Maximum 400
    [Console]::Beep($frequency, $duration)
  }
  'PS> '
  $host.ui.RawUI.WindowTitle = Get-Location
}

这段代码将会缩短您的 PowerShell 提示符,并且在标题栏上显示当前的路径。这还算是有益的功能。搞破坏的部分是每次执行一条命令,都会发出随机频率的刺耳的三连音:)。

PowerShell 技能连载 - 产生多个返回值

适用于所有 PowerShell 版本

如果一个 PowerShell 函数需要产生多个返回信息,最佳的实践方式是返回多个对象,然后将信息分别存储在对象的各个属性中。

以下是一个有趣的例外情况,它在某些场景中较为适用。尽管返回多个信息就可以了,并且要确保将结果赋值给多个变量:

function Get-MultipleData
{
  Get-Date
  'Hello'
  1+4
}

$date, $text, $result = Get-MultipleData

"The date is $date"
"The text was $text"
"The result is $result"

这个测试函数产生 3 段信息,然后将结果存储在 3 个不同的变量中。

PowerShell 技能连载 - 编辑“hosts”文件

适用于所有 PowerShell 版本

如果您常常需要修改“hosts”文件,那么手工用提升权限的记事本实例来打开文件是相当乏味的事情。这是因为该文件只能被 Administrators 用户修改,所以普通的记事本实例无法修改它。

以下是一段您可以直接使用,或者调整一下用来打开任何需要提升权限的程序的脚本。

function Show-HostsFile
{
  $Path = "$env:windir\system32\drivers\etc\hosts"
  Start-Process -FilePath notepad -ArgumentList $Path -Verb runas
}

PowerShell 技能连载 - 请注意 UNC 路径!

适用于所有 PowerShell 版本

许多 cmdlet 可以处理 UNC 路径,但是使用 UNC 路径会导致很多古怪的情况。请看以下:

PS> Test-Path -Path \\127.0.0.1\c$
True

这段代码返回了 true,该 UNC 路径存在。现在将当前驱动器变为一个非文件系统驱动器,然后再次实验:

PS> cd hkcu:\

PS> Test-Path -Path \\127.0.0.1\c$
False

同样的路径现在返回了 false。这是因为 UNC 路径并不包含驱动器号,而 PowerShell 需要驱动器号来指定正确的提供器。如果一个路径不包含驱动器号,那么 PowerShell 假设使用当前驱动器的提供器。所以如果您将当前的目录改为注册表,PowerShell 尝试在那儿查找 UNC 路径,那么就会失败。

更糟糕的是,出于某些未知的原因,但您用 net use 来映射驱动器时,PowerShell 在使用 cmdlet 来访问驱动器时可能会也可能不会产生混淆。

解决方案十分简单:当您用 cmdlet 访问 UNC 时,始终在 UNC 路径前面加上正确的提供器名称。这将消除该问题:

PS> Test-Path -Path FileSystem::\\127.0.0.1\c$
True

PS> cd hkcu:\

PS> Test-Path -Path \\127.0.0.1\c$
False

PS> Test-Path -Path FileSystem::\\127.0.0.1\c$
True

如果您遇到了 net use 产生的问题,也可以使用同样的办法,在路径前面加上 “FileSystem::。该问题可以立刻得到解决。