PowerShell 技能连载 - 在 PowerShell ISE 中使用“more”

适用于 PowerShell ISE

在 PowerShell 控制台中,您可以将命令通过管道输出到旧式的“more.com”命令中,或者更高级一些的 Out-Host -Paging 中。这将分页显示数据,每按一个键翻一页:

PS> Get-Process | more
PS> Get-Process | Out-Host -Paging

在 PowerShell ISE 中,这些都不支持。这是因为 ISE 没有控制台,所以没有“可见的行数”概念,只有一个无限的文本缓冲区。

要避免大量的结果刷屏问题,只需要自己创建一个兼容 ISE 的“more”命令:

function Out-More
{
    param
    (
        $Lines = 10,

        [Parameter(ValueFromPipeline=$true)]
        $InputObject
    )

    begin
    {
        $counter = 0
    }

    process
    {
        $counter++
        if ($counter -ge $Lines)
        {
            $counter = 0
            Write-Host 'Press ENTER to continue' -ForegroundColor Yellow
            Read-Host
        }
        $InputObject
    }
}

将您的结果通过管道输出到 Out-More,命令,并使用 -Lines 来指定接收到多少行以后暂停:

PS> Get-Process | Out-More -Lines 4

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    100       9     1436       1592    51            6896 adb
    307      42    22332      12940   123            1424 AllShareFrameworkDMS
     42       4     1396       1284    19            1404 AllShareFrameworkManagerDMS
Press ENTER to continue


     81       7     1004        724    43            1388 armsvc
    202      25    50376      55320   234     8,06  13720 chrome
   1131      65    68672      93892   361   116,73  13964 chrome
    199      24    53008      52700   225     5,56  14768 chrome
Press ENTER to continue


    248      26    31348      44984   239    44,31  15404 chrome
    173      20    23756      25540   179     1,27  16492 chrome
    190      22    36316      39208   207     2,81  16508 chrome
    184      23    41800      44212   223     1,77  17244 chrome
Press ENTER to continue

PowerShell 技能连载 - 从注册表中读取用户配置文件

适用于 PowerShell 所有版本

要查看哪个用户在您的机器上拥有(本地)配置文件,以及配置文件位于什么位置,请使用这段代码:

$path = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*'

Get-ItemProperty -Path $path |
  Select-Object -Property PSChildName, ProfileImagePath

它将自动枚举配置文件列表中的所有键,并返回用户 SID 和配置文件的路径:

PSChildName                              ProfileImagePath
-----------                              ----------------
S-1-5-18                                 C:\WINDOWS\system32\config\systemprofile
S-1-5-19                                 C:\Windows\ServiceProfiles\LocalService
S-1-5-20                                 C:\Windows\ServiceProfiles\NetworkSer...
S-1-5-21-1907506615-3936657230-268413... C:\Users\Tobias
S-1-5-80-3880006512-4290199581-164872... C:\Users\MSSQL$SQLEXPRESS

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 的在线解释——忽略您本机安装的帮助文件。