PowerShell 技能连载 - 解锁下载的文件

任何从 Internet 下载的以及从邮件接收到的文件,都被 Windows 隐式地标记为不安全的。如果文件包含可执行文件或二进制文件,它们必须解锁以后才可以运行。

PowerShell 3.0 以及以上的版本可以检测到包含“下载标记”的文件:

Get-ChildItem -Path $Home\Downloads -Recurse |
  Get-Item -Stream Zone.Identifier -ErrorAction Ignore |
  Select-Object -ExpandProperty FileName |
  Get-Item

这段代码或许不会返回任何文件(当没有文件具有下载标记的情况下),或许会返回一大堆文件(这也许意味着您解压了一个下载的 ZIP 文件,但忘了先对它解锁)。

要解锁这些文件,请使用 Unblock-File cmdlet。这段代码将解锁您下载文件夹中当前被锁定的文件(不涉及到其它任何文件):

Get-ChildItem -Path $Home\Downloads -Recurse |
  Get-Item -Stream Zone.Identifier -ErrorAction Ignore |
  Select-Object -ExpandProperty FileName |
  Get-Item |
  Unblock-File

PowerShell 技能连载 - 删除空结果

要排除某些包含空属性值的结果,您可以简单地使用 Where-Object 命令。例如,当您运行 Get-HotFix 时,假设您只希望查看 InstalledOn 属性包含时间值的补丁,以下是解决方案:

PS> Get-HotFix | Where-Object InstalledOn

类似地,要从 WMI 中获取分配了 IP 地址的网络适配器,请使用以下代码:

PS> Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object IPAddress

请注意在 PowerShell 2.0 以及以下版本,您需要使用完整的语法,类似如下:

PS> Get-WmiObject -Class Win32_NetworkAdapterConfiguration | Where-Object { $_.IPAddress }

Where-Object 将会排除您所选的属性包含以下任意一种情况的对象:null 值、空字符串,或者数字 0。因为这些值在转换为 Boolean 类型的时候将会被转换成 $false

PowerShell 技能连载 - PowerShell 4.0 中隐藏的数组扩展方法

PowerShell 4.0 (Windows 8.1 自带)中的数组原生支持 Foreach 和 Where 操作。这是一个 geek 的写法,所以并不见得比传统的管道有明显的优势(除了也许性能有所提升之外)。

这行代码将从一个数字列表中过滤出奇数来:

@(1..10).Where({$_ % 2})

以下代码将获取正在运行中的服务:

@(Get-Service).Where({$_.Status -eq 'Running'})

还有一些更多的(不在文档中)的东西。这行代码将获取大于 2 的前 4 个数字:

@(1..10).Where({$_ -gt 2}, 'skipuntil', 4)

最后,以下代码将做类似的事情,但是将它们转换为 TimeSpan 对象:

@(1..10).Where({$_ -gt 2}, 'skipuntil', 5).Foreach([Timespan])

PowerShell 技能连载 - 在 ISE 编辑器中打开文件

如果您想在 ISE 编辑器中打开一个脚本,一个快捷的方法是使用命令“ise”。例如要打开您的配置脚本(每次 ISE 启动时自动调用的脚本),请试试一下代码:

PS> ise $profile

您现在可以方便地增加或删除您希望 ISE 每次启动时自动执行的命令。

如果您的配置脚本不存在,以下单行的代码可以为您创建一个(它将覆盖已经存在的文件,所以只能在文件确实还不存在的时候运行它):

PS> New-Item -Path $profile -ItemType File -Force

您也可以从一个 PowerShell.exe 控制台中使用“ise”命令来启动一个 ISE 编辑器。

(顺便提一下:有一个叫做 psEdit 的函数使用效果十分相似,但是只在 PowerShell ISE 内部有效,在 PowerShell.exe 控制台中无效。)

PowerShell 技能连载 - 在 PowerShell ISE 中使用块注释

从 PowerShell 3.0 开始,您可以按住 ALT 键并选择一些内容,来获取一个矩形选区。

如果您尽可能地缩窄这个选区(您将只看到一条细细的蓝线),您可以方便地在选区之内增加或删除字符。只需要按下“#”键即可块注释它们,或者删除 # 号重新启用这段代码。

PowerShell 技能连载 - 查找远程计算机上已登录的用户

在上一个技巧当中我们使用 quser.exe 来查询本机当前登录的用户。以下是一个支持查询远程计算机上已登录用户的函数。有个额外的好处是,返回的信息附加了一个名为“ComputerName”的属性,所以当您查询多台计算机时,您将可以知道结果是属于那一台计算机的:

function Get-LoggedOnUser
{
  param([String[]]$ComputerName = $env:COMPUTERNAME)

    $ComputerName | ForEach-Object {
      (quser /SERVER:$_) -replace '\s{2,}', ',' |
        ConvertFrom-CSV |
        Add-Member -MemberType NoteProperty -Name ComputerName -Value $_ -PassThru
  }
}

以下是一个调用的例子,查询本地计算机以及一台远程计算机:

PowerShell 技能连载 - 查询已登录的用户

有一个十分有用的控制台程序叫做 quser.exe 可以告诉您哪些用户登录到了一台机器上。该可执行程序返回的是纯文本,但通过一点点正则表达式,该文本可以转换成 CSV 并导入 PowerShell。

以下代码以对象的形式返回所有当前登录到您机器上的用户信息:

(quser) -replace 's{2,}', ',' | ConvertFrom-Csv

PowerShell 技能连载 - 查询登录失败记录

只要有人使用错误的凭据登录,就会在安全日志中产生一条日志记录。以下是一个可以从安全日志中读取这些事件的函数(需要管理员特权)。它能够列出所有日志中非法的登录信息:

# requires Admin privileges!
function Get-LogonFailure
{
      param($ComputerName)
      try
      {
          Get-EventLog -LogName security -EntryType FailureAudit -InstanceId 4625 -ErrorAction Stop @PSBoundParameters |
                  ForEach-Object {
                    $domain, $user = $_.ReplacementStrings[5,6]
                    $time = $_.TimeGenerated
                    "Logon Failure: $domain\$user at $time"
                }
      }
      catch
      {
            if ($_.CategoryInfo.Category -eq 'ObjectNotFound')
            {
                  Write-Host "No logon failures found." -ForegroundColor Green
            }
            else
            {
                  Write-Warning "Error occured: $_"
            }

      }

}

请注意这个函数还可以在远程主机上运行。请使用 -ComputerName 参数来查询一台远程主机。远程主机需要运行 RemoteRegistry 服务,并且您需要在目标机器上的本地管理员权限。

PowerShell 技能连载 - 更改桌面背景

PowerShell 可以通过调用 Windows API,实现更改当前桌面背景并且立即生效。以下函数实现立刻更换桌面背景:

function Set-Wallpaper
{
    param(
        [Parameter(Mandatory=$true)]
        $Path,

        [ValidateSet('Center', 'Stretch')]
        $Style = 'Stretch'
    )

    Add-Type @"
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace Wallpaper
{
public enum Style : int
{
Center, Stretch
}
public class Setter {
public const int SetDesktopWallpaper = 20;
public const int UpdateIniFile = 0x01;
public const int SendWinIniChange = 0x02;
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int SystemParametersInfo (int uAction, int uParam, string lpvParam, int fuWinIni);
public static void SetWallpaper ( string path, Wallpaper.Style style ) {
SystemParametersInfo( SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange );
RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
switch( style )
{
case Style.Stretch :
key.SetValue(@"WallpaperStyle", "2") ;
key.SetValue(@"TileWallpaper", "0") ;
break;
case Style.Center :
key.SetValue(@"WallpaperStyle", "1") ;
key.SetValue(@"TileWallpaper", "0") ;
break;
}
key.Close();
}
}
}
"@

    [Wallpaper.Setter]::SetWallpaper( $Path, $Style )
}

Set-Wallpaper -Path 'C:\Windows\Web\Wallpaper\Characters\img24.jpg'

PowerShell 技能连载 - 在 ISE 编辑器中使用块注释

在 PowerShell 3.0 中,引入了一个小技巧,可以整块注释/取消注释某一段代码。

在 ISE 编辑器中,单击插入点(比如说一段代码的开头)。然后,按住 SHIFT+ALT,然后按下 键。

这时在 ISE 编辑器中将显示一条细细的绿线。当您高亮选中了这个块以后,在绿线消失前,按下 #(或任何您打算放在标记的行前的字符)。类似地,您也可以整块删除字符。