PowerShell 技能连载 - 获取关机信息

适用于 PowerShell 所有版本

Windows 在系统事件日志中记录了所有的关机事件。您可以从那儿提取和分析信息。

以下是一个读取适当的事件日志记录、从 ReplacementStrings 数组中读取相关的信息,并以对象数组的方式返回关机信息的函数。

function Get-ShutdownInfo
{

  Get-EventLog -LogName system -InstanceId 2147484722 -Source user32 |
  ForEach-Object {

    $result = 'dummy' | Select-Object -Property ComputerName, TimeWritten, User, Reason, Action, Executable

    $result.TimeWritten = $_.TimeWritten
    $result.User = $_.ReplacementStrings[6]
    $result.Reason = $_.ReplacementStrings[2]
    $result.Action = $_.ReplacementStrings[4]
    $result.Executable = Split-Path -Path $_.ReplacementStrings[0] -Leaf
    $result.ComputerName = $_.MachineName

    $result
  }
}

现在要检查关机问题就容易多了:

PS> Get-ShutdownInfo |  Out-GridView

PowerShell 技能连载 - 复制命令行历史

适用于所有 PowerShell 版本

如果您操作了一阵子 PowerShell,然后突然意识到想保存刚才输入过的命令,那么请试试这行简单的代码:

(Get-History).CommandLine | clip

这段代码将您的所有命令行历史复制到剪贴板中。您可以把它粘贴到任何您喜欢的编辑器中,然后将命令保存到文件中。

如果您将命令粘贴到 PowerShell ISE 编辑器中,那么这些命令将会成为一段 PowerShell 脚本。

PowerShell 技能连载 - 用正则表达式搜索文件

适用于 PowerShell 所有版本

Get-ChildItem 不支持高级的文件过滤。当您使用简单的通配符时,无法利用上正则表达式。

要用上正则表达式,需要增加一个过滤用的 cmdlet 和 -match 操作符。

这个例子将在 Windows 目录中查找所有文件名包含至少 2 位数字,且文件名不超过 8 个字符的文件:

Get-ChildItem -Path $env:windir -Recurse -ErrorAction SilentlyContinue |
  Where-Object { $_.BaseName -match '\d{2}' -and $_.Name.Length -le 8 }

请注意 BaseName 属性的使用。它只返回主文件名(不包含扩展名)。通过这种方式,扩展名中的数字不会被包含在内。

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 提示符,并且在标题栏上显示当前的路径。这还算是有益的功能。搞破坏的部分是每次执行一条命令,都会发出随机频率的刺耳的三连音:)。