PowerShell 技能连载 - 自动获取重要的支持响应信息

Here is a fun function to provide you with a good first level support response in case everyone is off for Christmas:
这是一个有趣的函数,当所有人都下班去过圣诞时将给您提供重要的支持响应信息。

#requires -Version 3

function Get-FirstLevelSupportResponse
{
  $url = 'http://pages.cs.wisc.edu/~ballard/bofh/bofhserver.pl'
  $ProgressPreference = 'SilentlyContinue'
  $page = Invoke-WebRequest -Uri $url -UseBasicParsing
  $pattern = '(?s)<br><font size\s?=\s?"\+2">(.+)</font'

  if ($page.Content -match $pattern)
  {
    $matches[1]
  }
}

您需要 Internet 连接来运行这段脚本。

PowerShell 技能连载 - 查询当前登录的用户名

有两种方式可以查询当前登录的用户:

# User logged on to a physical box
Get-WmiObject -Class Win32_ComputerSystem | Select-object -ExpandProperty UserName


# Owners of explorer.exe processes (desktop is an Explorer process)
Get-WmiObject -Class Win32_Process -Filter 'Name="explorer.exe"'  |
  ForEach-Object {
    $owner = $_.GetOwner()
    '{0}\{1}' -f  $owner.Domain, $owner.User
  } |
  Sort-Object -Unique

两种使用 Get-WmiObject 的方式都支持本地和远程方式调用。

PowerShell 技能连载 - 获取操作系统清单

如果您的老板需要一份您 AD 中所有计算机的操作系统清单,这也许是个好办法:

#requires -Version 1 -Modules ActiveDirectory

$max = 100

$os = Get-ADComputer -Filter * -Properties OperatingSystem -ResultPageSize $max |
Group-Object -Property OperatingSystem -NoElement |
Select-object -ExpandProperty Name |
ForEach-Object { '"{0}"' -f $_ }

$list = $os -join ','
$list
# copy list to clipboard
$list | clip

该脚本将从您的 AD 中获取计算机账户并将它们根据操作系统分组,然后将它整理成一个清单。请注意使用 PageSize 因为在一个大型的组织中获取所有计算机信息可能会花费很长时间。

PowerShell 技能连载 - 根据 OU 分析操作系统

以下是一个快捷的脚本,扫描 Active Directory 中的所有 OU,得到所有的计算机账户,然后将每个 OU 的信息按照操作系统分组:

#requires -Version 2 -Modules ActiveDirectory

Get-ADOrganizationalUnit -Filter * |
  ForEach-Object {
    $OU = $_

    Get-ADComputer -Filter * -SearchBase $OU.DistinguishedName -SearchScope SubTree -Properties Enabled, OperatingSystem |
      Where-Object { $_.Enabled -eq $true } |
      Group-Object -Property OperatingSystem -NoElement |
      Select-Object -Property Count, Name, OU, OUDN |
      ForEach-Object {
        $_.OU = $OU.Name
        $_.OUDN = $OU.DistinguishedName
        $_
      }
  } |
  Out-GridView

PowerShell 技能连载 - 理解 -f 操作符

您也许已经遇到过 -f 操作符并且很好奇它做了什么。它是一个格式化操作符并且提供了一种相当简单的方法来操作数组元素并创建字符串。

让我们从一个值数组开始,比如这个:

$info = 'PowerShell', $PSVersionTable.PSVersion.Major, $pshome

您可以通过序号访问单个数组元素。

PS> $info[0]
PowerShell

PS> $info[1]
4

PS> $info[2]
C:\Windows\System32\WindowsPowerShell\v1.0

如果您需要将该数组的元素合并为一个字符串,这时候 -f 操作符就能够大显身手了。它能够使用相同的序号来读取数组元素并将它们组成一个字符串。以下是一些例子,它们使用 $info 中的信息来组成不同的字符串:

PS> '{0} Version is {1}. Location "{2}' -f $info

PowerShell Version is 4. Location "C:\Windows\System32\WindowsPowerShell\v1.0

PS> '{0} {1}' -f $info

PowerShell 4

PS> '{0} {1:0.0}' -f $info

PowerShell 4.0

PS> '{0}: {2}' -f $info

PowerShell: C:\Windows\System32\WindowsPowerShell\v1.0

PowerShell 技能连载 - 为大量文件建立拷贝备份

PowerShell 可以为您的文件建立备份。您所需要调整的只是需要备份的文件类型,以及您需要备份的目标文件扩展名。

这个例子将影响(直接)存储在您的用户目录下的 PowerShell 脚本。也许这个文件夹下并没有这类文件,所以要么拷入一个文件来测试这个脚本,要么指定一个不同的文件夹路径。

每个脚本将被备份到相同的主文件名,而扩展名为“.ps1_old”的文件中。

当您改变 $Recurese 的值时,脚本将会为您的用户文件夹下的所有 PowerShell 创建备份。

#requires -Version 1

$ExtensionToBackup = '.ps1'
$BackupExtension = '.ps1_old'
$FolderToProcess = $HOME
$Recurse = $false


Get-ChildItem -Path $FolderToProcess -Filter $ExtensionToBackup -Recurse:$Recurse |
  ForEach-Object {
    $newpath = [System.IO.Path]::ChangeExtension($_.FullName, $BackupExtension)
    Copy-Item -Path $_.FullName -Destination $newpath
 }

PowerShell 技能连载 - 将结果通过管道直接传给 Office Word

只需要几行代码,您就可以实现一个 Out-OfficeWord 指令。它接受传入的数据并将它们插入一个新的 Word 文档中(假设 Word 已经安装)。

#requires -Version 1

function Out-OfficeWord
{
  param
  (
    $Font = 'Courier',

    $FontSize = 12,

    $Width = 80,

    [switch]
    $Landscape
  )

  $Text = $Input | Out-String -Width $Width

  $WordObj = New-Object -ComObject Word.Application
  $document = $WordObj.Documents.Add()
  $document.PageSetup.Orientation = [Int][bool]$Landscape
  $document.Content.Text = $Text
  $document.Content.Font.Size = $FontSize
  $document.Content.Font.Name = $Font
  $document.Paragraphs | ForEach-Object { $_.SpaceAfter = 0 }
  $WordObj.Visible = $true
}

要在 Word 中建立一个正在运行中的进程列表,只需要运行这段代码:

Get-Process | Out-OfficeWord -Landscape -Font Consolas -FontSize 8

接下来,您可以将结果另存为 PDF、改进格式,或打印出来。

PowerShell 技能连载 - 从 WMI 中搜索有用的信息

WMI 是一个很好的信息源,但要找到正确的 WMI 类来查询并不总是那么容易。

一下是一个小小的搜索工具:它提示输入一个关键字,然后根据在 WMI 中搜索所有合适的关键字。结果将显示在一个网格视图窗口中,然后您可以选择一个类并按下“确定”按钮,该工具将查询出匹配的结果:

#requires -Version 3

function Search-WMI
{
    param([Parameter(Mandatory=$true)]$Keyword)

    Get-WmiObject -Class "Win32_*$Keyword*" -List |
    Where-Object { $_.Properties.Count -gt 6 } |
    Where-Object { $_.Name -notlike 'Win32_Perf*' } |
    Sort-Object -Property Name |
    Select-Object -Property @{Name='Select one of these classes'; Expression={$_.Name }} |
    Out-GridView -Title 'Choose one' -OutputMode Single |
    ForEach-Object {
        Get-WmiObject -Class $_.'Select one of these classes' | Out-GridView
    }
}

Search-WMI -Keyword network

PowerShell 技能连载 - 使用网格窗口作为一个通用的对话框

Out-GridView 不止可以用于显示结果。您可以将它转换为一个很有用的通用对话框。

假设您希望显示一系列运行中的程序,然后结束掉选中的程序。传统的方式大概是这样:

Get-Process |
  Where-Object { $_.MainWindowTitle } |
  Out-GridView -OutputMode Single |
  Stop-Process -WhatIf

当您将源对象通过管道传给 Out-GridView 命令时,用户将能看到所有的普通对象属性。这也许没问题,但如果您希望用户体验更好一些,您可以使用一些更高级的 PowerShell 技巧:

#requires -Version 3

$prompt = 'Choose the process you want to terminate:'

Get-Process |
  Where-Object { $_.MainWindowTitle } |
  ForEach-Object {
    New-Object PSObject -Property @{$prompt = $_ | Add-Member -MemberType ScriptMethod -Name ToString -Force -Value  { '{0} [{1}]' -f $this.Description, $this.Id } -PassThru }
  } |
  Out-GridView -OutputMode Single -Title $prompt |
  Select-Object -ExpandProperty $prompt |
  Stop-Process -WhatIf

请先看用户体验:该网格窗口不再让人感到疑惑。现在让我们检查一下如何实现这种用户体验。

在结果通过管道传给 Out-GridView 之前,它们被重新打包成一个只有单个属性的对象。该属性包含了您在 $prompt 中定义的名称,所以它基本上就是您想呈现给用户的信息。

当您做完这些并将包裹后的对象通过管道传给 Out-GridView 后,您可以看到该对象的文字呈现。要控制文字呈现的方式,我们将它的 ToString() 方法用一个显示您期望的值的方法来覆盖。在这个例子里,它显示进程的描述和进程的 ID。

最后,被用户选中的对象将再被拆包。通过这种方法,您可以获取源对象。

PowerShell 技能连载 - 以不同的格式输出文件大小

当您将一个数值赋给一个变量时,您也许希望按不同的单位显示该数字。字节的方式很清晰,但是有些时候以 KB 或 MB 的方式显示更合适。

以下是一个聪明的技巧,它用一个更多样化的版本覆盖了内置的 ToString() 方法。该方法包括了单位,您希望的位数,以及后缀文字。通过这种方式,您可以根据需要按各种格式显示数字。

变量的内容并没有被改变,所以变量仍然存储着 Integer 数值。您可以安全地用于排序及和其它值比较:

#requires -Version 1


$a = 1257657656
$a = $a | Add-Member -MemberType ScriptMethod -Name tostring -Force -Value { param($Unit = 1MB, $Digits=1, $Suffix=' MB') "{0:n$Digits}$Suffix" -f ($this/($Unit)) } -PassThru

以下是多种使用 $a 的例子:

PS> $a
1.199,4 MB

PS> $a.ToString(1GB, 0, ' GB')
1 GB

PS> $a.ToString(1KB, 2, ' KB')
1.228.181,30 KB

PS> $a -eq 1257657656
True

PS> $a -eq 1257657657
False

PS> $a.GetType().Name
Int32