PowerShell 技能连载 - 获得一个干净的 PowerShell 环境

适用于 PowerShell 3.0 及以上版本

当您在 PowerShell ISE 中开发 PowerShell 脚本时,您可能做了很多更改和修订,并且测试运行了脚本。

这将“污染”您的环境:所有在脚本作用域内定义的变量仍然是定义过的状态,所以后续的测试不再是在一个干净的缺省环境中执行。

要确保一个脚本是在一个完全干净的测试环境中执行,您当然可以重启 PowerShell ISE。一个更便捷的方法是打开一个新的 PowerShell 选项卡:在 PowerShell ISE 中,选择文件/新建 PowerShell 选项卡。

这个操作将在脚本面板中新建一个选项卡。该选项卡代表一个全新的 PowerShell 宿主。您可以在这个新选项卡中加载您的测试脚本,并且在那儿进行测试。当测试完毕后,只需要点击关闭选项卡,即可从内存中消除掉它的所有相关内容。

请注意您可以在多个标签页中连续打开同一个脚本。当您这么操作时,ISE 会警告您该脚本已在另一个选项卡中打开了。当您编辑该脚本时,所有的编辑操作都会作用到所有打开该脚本的选项卡实例。

PowerShell 技能连载 - 将 PowerShell 工具增加到 Windows 8 启动屏幕

适用于 Windows 8/Windows 8.1

您可能注意到了 Windows 8 启动屏幕默认没有 PowerShell ISE 之类的 PowerShell 工具。当您转到开始屏幕并且输入 “ISE” 时,搜不到任何结果。

要改变这种情况,请确保开始屏幕显示了“管理员工具”。在开始屏幕上,将鼠标移动到最右侧,直到出来一个菜单。然后,点击“设置”,然后点击“磁贴”。

现在打开“显示管理员工具”的滑块。

当您做完这步,Windows 8 启动屏幕将会显示 PowerShell 工具,并且当您键入 “ISE” 时内置的搜索工具将会显示 PowerShell ISE。

在搜索结果中右键单击 “Windows PowerShell ISE” 可以看到额外的选项,并且可以将编辑器钉在任务栏上。

PowerShell 技能连载 - 查找 AD 复制失败信息

适用于 Windows 8.1、Server 2012 R2

在 Windows 8.1 和 Server 2012 R2 中,查看 Active Directory 复制失败的信息变得更简单了。Get-ADReplicationFailure 这个新的 cmdlet 将会输出最近的复制失败信息。用它来检查一个特定的域控制器的方法:

PS> Get-ADReplicationFailure dc1.test.com

或者检查整个站点:

PS> Get-ADReplicationFailure -Scope Site -Target Hannover

该 cmdlet 是随 Windows 8.1 和 Server 2012 R2 发布的 ActiveDirectory 模块的一部分。在您使用它之前,请确保您在控制面板/软件/启用或关闭 Windows 功能中启用了它。它是“远程服务器管理工具 (RSAT)”的一部分。如果您的 Windows 8.1 没有预装 RSAT,您可以从这里下载它:http://www.microsoft.com/de-de/download/details.aspx?id=39296。

要查看该模块提供的其它 cmdlet,请试试这行代码:

PS> Get-Command -Module ActiveDirectory

CommandType     Name                                               ModuleName
-----------     ----                                               ----------
Cmdlet          Add-ADCentralAccessPolicyMember                    ActiveDir...
Cmdlet          Add-ADComputerServiceAccount                       ActiveDir...
Cmdlet          Add-ADDomainControllerPasswordReplicationPolicy    ActiveDir...
Cmdlet          Add-ADFineGrainedPasswordPolicySubject             ActiveDir...
(...)

请注意针对 Windows 8.1/Server 2012 R2 的 RSAT提供了一些额外的 cmdlet,这些 cmdlet 在针对 Windows 早期版本的 RSAT 中并没有提供。

PowerShell 技能连载 - 有用的静态 .NET 方法

适用于 PowerShell 所有版本

PowerShell 可以调用 .NET 类型的静态方法。以下是一些很好用的单行代码:

[Math]::Round(7.9)

[Convert]::ToString(576255753217, 8)

[Guid]::NewGuid()

[Net.Dns]::GetHostByName('schulung12')

[IO.Path]::GetExtension('c:\test.txt')

[IO.Path]::ChangeExtension('c:\test.txt', 'bak')

要查看更多的用法,请删除类型(方括号中的文字)后的代码,然后键入两个冒号。PowerShell ISE 将会自动弹出一个快捷菜单列出该类型可用的方法。在 PowerShell 控制台中,只需要按下 TAB 键即可得到自动完成的建议。

您也可以将一个类型通过管道输出到 Get-Member 命令:

PS> [Math] | Get-Member -MemberType *Method -Static


   TypeName: System.Math

Name            MemberType Definition
----            ---------- ----------
Abs             Method     static sbyte Abs(sbyte value), static int16 Abs(int16 value), static int Abs(int value), sta...
Acos            Method     static double Acos(double d)
Asin            Method     static double Asin(double d)
Atan            Method     static double Atan(double d)
Atan2           Method     static double Atan2(double y, double x)
BigMul          Method     static long BigMul(int a, int b)
Ceiling         Method     static decimal Ceiling(decimal d), static double Ceiling(double a)
Cos             Method     static double Cos(double d)
Cosh            Method     static double Cosh(double value
DivRem          Method     static int DivRem(int a, int b, [ref] int result), static long DivRem(long a, long b, [ref] ...
Equals          Method     static bool Equals(System.Object objA, System.Object objB)
Exp             Method     static double Exp(double d)
Floor           Method     static decimal Floor(decimal d), static double Floor(double d)
IEEERemainder   Method     static double IEEERemainder(double x, double y)
Log             Method     static double Log(double d), static double Log(double a, double newBase)
Log10           Method     static double Log10(double d)
Max             Method     static sbyte Max(sbyte val1, sbyte val2), static byte Max(byte val1, byte val2), static int1...
Min             Method     static sbyte Min(sbyte val1, sbyte val2), static byte Min(byte val1, byte val2), static int1...
Pow             Method     static double Pow(double x, double y)
ReferenceEquals Method     static bool ReferenceEquals(System.Object objA, System.Object objB)
Round           Method     static double Round(double a), static double Round(double value, int digits), static double ...
Sign            Method     static int Sign(sbyte value), static int Sign(int16 value), static int Sign(int value), stat...
Sin             Method     static double Sin(double a)
Sinh            Method     static double Sinh(double value)
Sqrt            Method     static double Sqrt(double d)
Tan             Method     static double Tan(double a)
Tanh            Method     static double Tanh(double value)
Truncate        Method     static decimal Truncate(decimal d), static double Truncate(double d)

要查看某个方法的所有重载的签名,请去掉圆括号:

PS> Get-Something -Path test
You entered test.

PS> [Math]::Round

OverloadDefinitions
-------------------
static double Round(double a
static double Round(double value, int digits)
static double Round(double value, System.MidpointRounding mode)
static double Round(double value, int digits, System.MidpointRounding mode
static decimal Round(decimal d
static decimal Round(decimal d, int decimals)
static decimal Round(decimal d, System.MidpointRounding mode)
static decimal Round(decimal d, int decimals, System.MidpointRounding mode)

PowerShell 技能连载 - 为必须的参数弹出一个对话框

适用于 PowerShell 所有版本

通常,但您将一个参数定义为必选的,并且用户没有传入对应的实参,PowerShell 能够处理好这种情况并提示用户输入这个值:

function Get-Something
{
  param
  (
    [Parameter(Mandatory = $true)]
    $Path
  )

  "You entered $Path."
}

结果类似这样(您无法控制提示信息):

PS> Get-Something -Path test
You entered test.

PS> Get-Something
Cmdlet Get-Something at command pipeline position 1
Supply values for the following parameters:
Path: test
You entered test.

PS>

但是您是否知道还可以通过这种方式获取一个必选参数?

function Get-Something
{
  param
  (
    $Path = $(Read-Host 'Please, enter a Path value')
  )

  "You entered $Path."
}

这种方法将控制权交给您,以下是它看起来的样子:

PS> Get-Something -Path test
You entered test.

PS> Get-Something
Please, enter a Path value: test
You entered test.

PS>

PowerShell 技能连载 - 使用打开文件夹对话框

适用于 PowerShell 所有版本

为了在您的脚本中输入一些东西,以下是一个简单的打开“打开文件”对话框并让用户选择一个文件的函数。

function Show-OpenFileDialog
{
  param
  ($Title = 'Pick a File', $Filter = 'All|*.*|PowerShell|*.ps1')

  $type = 'Microsoft.Win32.OpenFileDialog'


  $dialog = New-Object -TypeName $type
  $dialog.Title = $Title
  $dialog.Filter = $Filter
  if ($dialog.ShowDialog() -eq $true)
  {
    $dialog.FileName
  }
  else
  {
    Write-Warning 'Cancelled'
  }
}

如您所见,您可以控制该对话框的标题栏和显示的文件类型。

PowerShell 技能连载 - 记录拒绝存取的文件夹

适用于 PowerShell 所有版本

当您用 Get-ChildItem 浏览文件系统的时候,您可能偶尔会碰到没有查看权限的文件夹。如果您希望将抛出次异常的所有文件夹都记录下来,请试试这个方法:

$result = Get-ChildItem -Path c:\Windows -Filter *.ps1 -Recurse -ErrorAction SilentlyContinue -ErrorVariable abcd

Write-Warning 'Unable to access these folders:'
Write-Warning ($abcd.TargetObject -join "`r`n")

这个技巧是隐藏所有错误提示(-ErrorAction SilentlyContinue)但将错误都保存到一个变量中(-ErrorVariable abce)。

PowerShell 技能连载 - 管理终端服务设置

_需要 ActiveDirectory 模块

有些时候您也许希望在一个 AD 账户中直接存取终端服务相关的属性。以下是一些演示如何实现该功能的示例代码:

$Identity = 'SomeUserName'

$distinguishedName = (Get-ADUser -Identity $Identity -Properties distinguishedName).distinguishedName
$ADUser = [ADSI]"LDAP://$distinguishedName"

$TSProfilePath = $ADUser.psbase.InvokeGet('terminalservicesprofilepath')
$TSHomeDir = $ADUser.psbase.InvokeGet('TerminalServicesHomeDirectory')
$TSHomeDrive = $ADUser.psbase.InvokeGet('TerminalServicesHomeDrive')
$TSAllowLogOn = $ADUser.psbase.InvokeGet('allowLogon')

PowerShell 技能连载 - 凭据混淆器

适用于 PowerShell ISE 3.0 及以上版本

虽然一般不建议将密码硬编码在脚本里,但有些情况下已经这么做了。相比于硬编码明文密码,一个最基本的改进是将密码混淆。密码混淆是一种弱的保护方式,但它能确保非掌握 PowerShell 知识的人员轻易地得到密码。

这是段小脚本会询问用户名和密码,然后生成一段混淆脚本来产生凭据对象。

当您运行下面这段脚本生成的脚本,在 $cred 变量将会保存一个包含用户名和密码的凭据对象,它可以用于任何带 -Credential 参数的 cmdlet。

$cred = Get-Credential -Message 'Enter Domain\Username and Password'
$pwd = $cred.Password
$user = $cred.UserName
$key = 1..32 | ForEach-Object { Get-Random -Maximum 256 }
$pwdencrypted = $pwd | ConvertFrom-SecureString -Key $key

$private:ofs = ' '

$generatedScript = @()
$generatedScript += '$password = ''{0}''' -f $pwdencrypted
$generatedScript += '$key = ''{0}''' -f "$key"

$generatedScript += '$passwordSecure = ConvertTo-SecureString -String $password -Key ([Byte[]]$key.Split('' ''))'
$generatedScript += '$cred = New-Object system.Management.Automation.PSCredential(''{0}'', $passwordSecure)' -f $user
$generatedScript += '$cred'

$file = $psise.CurrentPowerShellTab.Files.Add()
$file.Editor.Text = $generatedScript | Out-String
$file.Editor.SetCaretPosition(1,1)

自动生成的密码脚本看起来类似这样:

$password = '76492d1116743f0423413b16050a5345MgB8AHMAUQA3AFAAVwB0AGkAUQBUAC8AdwBqADYAUABVAFYAUwB4AEYAYgB4AFEAPQA9AHwAZgA0ADgAOQA4AGYANwA0AGEAMAA0ADUANwA5ADkAMwA5ADkAMwA1ADUANQA0AGYANwA5AGQANwBkAGYAOQBmAGEAYQA3ADMAYgBkADIAOQA3AGMAYQBmADUAMgA3ADEANwA3AGEAYgBmADAAYgA1AGYAYwAyADYAYgAzADkAOAA='
$key = '187 98 34 82 148 52 13 86 246 2 130 197 217 97 147 98 75 197 149 246 74 35 27 7 211 15 131 93 182 231 171 3'
$passwordSecure = ConvertTo-SecureString -String $password -Key ([Byte[]]$key.Split(' '))
$cred = New-Object system.Management.Automation.PSCredential('mickey\mouse', $passwordSecure)
$cred

PowerShell 技能连载 - 自动展开和内存消耗

适用于 PowerShell 3.0 及以上版本

在 PowerShell 3.0 中,增加了一个称为“自动回滚”的特性。通过这个特性,您可以这样书写代码:

(Get-ChildItem -Path $env:windir\system32 -Filter *.dll).VersionInfo

这行代码查找 System32 子文件夹下的所有 DLL 文件并且对它们进行迭代,对每个文件返回其 VersionInfo 属性(实际上是 DLL 版本)。在使用自动展开功能之前,您需要手工编写循环语句:

Get-ChildItem -Path $env:windir\system32 -Filter *.dll | ForEach-Object { $_.VersionInfo }

当您运行以上两段代码时,它们返回完全相同的结果。然而,您将立刻发现自动展开特性所带来的代价:它消耗了更多的时间才返回结果。第一行结果出来时可能要消耗 10 秒之多的时间,而“传统”的方法几乎是连续地返回信息。

总体消耗的时间是差不多的。实际上,自动展开特性等价的代码如下:

$data = Get-ChildItem -Path $env:windir\system32 -Filter *.dll
Foreach ($element in $data) { $element.VersionInfo }

自动展开代码更直观,更容易书写手写循环兼容性更好,更快输出结果。