PowerShell 技能连载 - 通过前缀对文件夹分组

您知道吗?Group-Object 可以方便地以自定义的规则来对元素分组。以下通过简单的一行代码实现根据前三个字母对文件夹分组:

Get-ChildItem -Path C:\Windows -Directory |
   Group-Object -Property { $_.Name.PadRight(3).Substring(0,3)}

稍微做一些额外的改动,您可以以这三个首字母做为键,创建一个哈希表:

$lookup = Get-ChildItem -Path $env:windir -Directory  |
   Group-Object -Property { $_.Name.PadRight(3).Substring(0,3).ToUpper()} -AsHashTable -AsString

$lookup.Keys

现在我们可以很容易地取得其中的文件夹,比如说我们要取以“SYS”开头的文件夹:

PS C:\Windows\System32> $lookup.SYS


    目录: C:\Windows


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----         2013/9/24     21:50            System
d-r--         2013/12/8     13:40            System32
d----         2013/8/22     23:36            SystemResources
d----         2013/12/5     11:29            SysWOW64

这有什么实用价值呢?有些公司使用文件夹前缀作为业务单元。用上这个技术之后,我们可以很容易地把所有的业务单元文件夹“收拢”起来——您可以秒杀地计算它们的存储容量并且创建一个自动化的报表。

PowerShell 技能连载 - 查找已知的 USB 驱动器

您知道吗?Windows 维护着一个关于所有插入过您机器中的 USB 存储设备列表。要导出这个列表十分简单:

$Path = 'HKLM:\SYSTEM\CurrentControlSet\Enum\USBSTOR\*\*'
Get-ItemProperty -Path $Path |
  Select-Object -Property FriendlyName, CompatibleIDs, Mfg

结果看起来如下:

FriendlyName                                CompatibleIDs                              Mfg
------------                                -------------                              ---
SCANNER USB Device                          {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Android UMS Composite USB Device            {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Android UMS Composite USB Device            {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Generic Flash Disk USB Device               {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Hitachi HTS545050B9A300 USB Device          {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Landi A015 USB Device                       {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Landi A015 USB Device                       {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Landi A015 USB Device                       {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Linux File-CD Gadget USB Device             {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Linux File-CD Gadget USB Device             {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Linux File-CD Gadget USB Device             {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Linux File-CD Gadget USB Device             {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Multiple Card  Reader USB Device            {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
SAMSUNG GT-I9000 USB Device                 {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
SAMSUNG GT-I9000 Card USB Device            {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
SAMSUNG GT-I9000 Card USB Device            {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
Ut165 USB Flash Disk USB Device             {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...
WD Elements 1042 USB Device                 {USBSTOR\Disk, USBSTOR\RAW, GenDisk}       @disk.inf,%genmanufacturer%;(Standard d...

列表越长,说明您的计算机插入过越多种不同的 USB 存储设备。

PowerShell 技能连载 - 获取 DLL 文件版本信息

是否需要获取一个 DLL 文件列表以及它们的版本信息?Get-ChildItem 可以为您获取这些信息。您只需要解开其中的一些属性,例如:

Get-ChildItem c:\windows\system32\*.dll |
  Select-Object -ExpandProperty VersionInfo |
  Select-Object -Property FileName, Productversion, ProductName

以上实际上将原始的 FileInfo 对象替换(-ExpandProperty)成了 VersionInfo 对象。您所做的大概是将一个对象转换成另一个对象,并且丢掉前者的一部分信息。例如,您无法再存取某些属性,如 LastWriteTime 等。

如果您希望保持原有的 FileInfo 对象,但是为它加入某些额外的信息,那么请像这样使用 Add-Member

Get-ChildItem c:\windows\system32\*.dll |
  Add-Member -MemberType ScriptProperty -Name Version -Value {
  $this.VersionInfo.ProductVersion
  } -PassThru |
  Select-Object -Property LastWriteTime, Length, Name, Version |
  Out-GridView

“$this”是您需要扩展的对象。

PowerShell 技能连载 - 远程执行代码

在一个域环境中,PowerShell 远程操作功能几乎是开箱即用的。您所需要做的知识在目标机器上启用远程功能(从 Server 2012 开始,PowerShell 远程操作功能对于 Administrators 组用户缺省是启用的)。

在 PowerShell 3.0 中,需要人为地启用远程功能,这就是一切要做的事了(需要管理员权限):

PS> Enable-PSRemoting -SkipNetworkProfileCheck -Force

你不需要在客户端(准备发送命令的机器)上配置任何东西。

下一步,任何管理员可以将命令发送到启用了远程操作功能的机器上去执行它。以下例子将列出目标机器上所有和 PowerShell 相关的进程:

$code =
{
      Get-Process -Name powershell*, wsmprovhost -ErrorAction SilentlyContinue
}

$list = 'server1', 'w2k12-niki', 'pc11box'
Invoke-Command -ScriptBlock $code #-ComputerName $list

当您原样执行这段代码的时候,Invoke-Command 在您自己的机器上运行存储在 $code 中的代码块。

它列出所有运行中的 PowerShell 控制台的实例、ISE PowerShell 编辑器,以及所有由您机器上别人初始化的 PowerShell 隐藏远程会话。

而当您去掉 -ComputerName 参数的注释,代码将会在 $list 变量存储的所有计算机上执行。请确保它们存在并且已启用了远程操作功能。当您从远程计算机收到数据时,PowerShell 自动在返回的信息上附加一个 "PSComputerName" 属性,用来存储返回信息的计算机名。

PowerShell 技能连载 - 访问所有用户的桌面

Resolve-Path 是一个相当棒的查找相同深度路径用的 Cmdlet。例如,以下是一段很短小的代码,它在您机器的每个用户桌面上创建一个文本文件:

$root = Split-Path $env:USERPROFILE

Resolve-Path $root\*\Desktop |
  ForEach-Object {
    $Path = Join-Path -Path $_ -ChildPath 'hello there.txt'
    'Here is some content...' | Out-File -FilePath $Path
    Write-Warning "Creating $Path"
  }

以管理员权限运行您的脚本,它将在您机器中所有用户的桌面上创建一个文件:

WARNING: Creating C:\Users\Administrator\Desktop\hello there.txt
WARNING: Creating C:\Users\CustomerService\Desktop\hello there.txt
WARNING: Creating C:\Users\Guest\Desktop\hello there.txt
WARNING: Creating C:\Users\PSTestGer\Desktop\hello there.txt
WARNING: Creating C:\Users\Tester\Desktop\hello there.txt
WARNING: Creating C:\Users\Tobias\Desktop\hello there.txt

PowerShell 技能连载 - 在 ISE 中快速选中结果

如果您想快速地选中并复制 PowerShell 3.0 ISE 编辑器中控制台窗格的结果到您的博客或您喜欢的文字处理器中,例如将结果保存为文档或者贴到文章中。以下是实现的方法:

当您运行一个命令后,光标位于 ISE 控制台窗格中并且等待输入新的命令。只需要按住 CTRL 并按下 键。光标将向左移动一位。然后按下 CTRL+A 选取所有的结果,然后按下 CTRL+C 将它们复制到剪贴板。完成!

PowerShell 技能连载 - 加速多个 WMI 查询

当您远程执行 Get-WmiObject 命令时,它将会创建一个新的连接。所以如果您查询不同的 WMI 类时,每个查询会使用一个不同的连接,这样将会影响总体性能。

从 PowerShell 3.0 开始,有一些列新的 Cmdlet。使用这些 Cmdlet 可以容易地使用现有的连接高效地运行多个查询:

$session = New-CimSession –ComputerName localhost
$os = Get-CimInstance –ClassName Win32_OperatingSystem –CimSession $session
$bios = Get-CimInstance -ClassName Win32_BIOS -CimSession $session

会话缺省使用 WSMAN 协议:

PS> $session

Id           : 1
Name         : CimSession1
InstanceId   : 0bb38128-3633-4eb8-8b55-6d2910b89bcd
ComputerName : localhost
Protocol     : WSMAN

当您创建会话是,您可以显式地指定一个不同的远程传输协议,例如 DCOM。

PowerShell 技能连载 - 访问终极 PowerShell 生存指南

您熟悉 PowerShell 生存指南吗?它是终极的 PowerShell 维基页面,包括视频、Module,和您很可能需要的关于 PowerShell 的一切资源。最棒的部分:它是一个开放式维基,所以如果您自己创建了一个 PowerShell 资源,希望让其他人知道它,那么您完全可以编辑 PowerShell 生存指南来让别人知道它。

http://social.technet.microsoft.com/wiki/contents/articles/183.windows-powershell-survival-guide.aspx

PowerShell 技能连载 - 获取 WMI 智能感知信息

Get-WmiObject 并未对 WMI 类提供智能感知信息,所以您要么事先知道 WMI 类的名字,要么使用 -List 参数来搜索它。

不过有一个聪明的技巧:Get-CimInstance 命令几乎完成相同的事情,并且它的参数 -ClassName 也接受一个 WMI 类名。而这个参数提供了智能感知支持。

在 PowerShell 3.0 ISE 中进行以下操作:

PS> Get-CimInstance -ClassName Win32_

然后按下 CTRL+SPACE 键来调用智能感知。请观察状态栏提示。由于有几百个 WMI 类名,所以首次尝试的时候,智能感知在获取所有类信息的时候可能会超时。过一段时间,或者您稍微限定以下类名,它就可以正常工作了。

所以只要用 Get-CimInstance 来代替 Get-WmiObject,然后在智能感知的支持下选择类名,然后将 Cmdlet 和参数改回 Get-WmiObject -Class 即可。

或者,从头到尾都使用 Get-CimInstance。它返回基本相同价值的信息。但在缺省情况下,它使用 WSMan 协议来进行远程操作,而不是 DCOM。

PowerShell 技能连载 - 列出“真实”的硬盘

WMI 可以提供一个系统的很多信息,但是有些时候这些信息太多了。当您查询逻辑磁盘时,您得到的往往不止是物理磁盘。

设置额外的过滤器可以解决此问题。以下这行代码通过设置 DriveType=3 来获取物理驱动器:

PS> Get-WmiObject -Class Win32_LogicalDisk -Filter 'DriveType=3'

DeviceID     : C:
DriveType    : 3
ProviderName :
FreeSpace    : 4468535296
(...)

由于 Get-WmiObject 有一个 -ComputerName 参数,所以您也可以远程获取该信息。如果您想知道有哪些其他的驱动器类型,只需要去掉过滤条件,或者用搜索引擎搜索 "Win32_LogicalDisk DriveType"