PowerShell 技能连载 - 从 DN 中获得 Domain

“DN” 指的是是 Active Directory 对象的路径,看起来大概如下:

'CN=Tobias,OU=Authors,DC=powershell,DC=local'

要获取 DN 中的域部分,请使用如下代码:

$DN = 'CN=Tobias,OU=Authors,DC=powershell,DC=local'
$pattern = '(?i)DC=\w{1,}?\b'

([RegEx]::Matches($DN, $pattern) | ForEach-Object { $_.Value }) -join ','

这段代码用一个正则表达式来查找 DN 的所有 DC= 部分然后将它们用逗号分隔符连接起来。

执行结果如下:

DC=powershell,DC=local

PowerShell 技能连载 - 将二进制 SID 转换为 SID 字符串

Active Directory 账户有一个二进制形式存储的 SID。要将字节数组转换为字符串的表达形式,可以用如下的 .NET 函数:

# get current user
$searcher = [ADSISearcher]"(&(objectClass=User)(objectCategory=person)(sAMAccountName=$env:username))"
$user = $searcher.FindOne().GetDirectoryEntry()

# get binary SID from AD account
$binarySID = $user.ObjectSid.Value

# convert to string SID
$stringSID = (New-Object System.Security.Principal.SecurityIdentifier($binarySID,0)).Value

$binarySID
$stringSID

在这个例子中,一个 ADSI 搜索器获取当前的用户账户(返回当前登录到一个域中的用户)。然后,将二进制的 SID 转换为 SID 字符串。

PowerShell 技能连载 - 查找当前的脚本文件夹

从 PowerShell 3.0 开始,有一个很简单的办法来确定一个脚本所在的文件夹:$PSScriptRoot。这个变量总是保存了指定脚本所存放的文件夹路径。

通过这种方法,可以很方便地加载额外的资源,比如说其它脚本。以下代码将读取位于同一个文件夹中,一个名为 myFunctions.ps1 的脚本文件:

"$PSScriptRoot\myFunctions.ps1"

别忘了用“dot-source”语法(在路径之前加点号)。否则只会输出该路径名(而不是执行该路径表示的脚本)。

PowerShell 技能连载 - 获取 Active Directory 账户信息

在上一段脚本中,您应该已经发现了可以多么轻易地用几行 PowerShell 代码来获取 Active Directory 账户。它的结果是一个搜索结果对象,而不是实际的账户对象。

要获取一个账户的更详细信息,请使用 GetDirectoryEntry() 将搜索结果转换为一个实际的账户对象:

# get 10 results max
$searcher.SizeLimit = 10

# find account location
$searcher.FindAll() |
  # get account object
  ForEach-Object { $_.GetDirectoryEntry() } |
  # display all properties
  Select-Object -Property * |
  # display in a grid view window (ISE needs to be installed for this step)
  Out-GridView

PowerShell 技能连载 - 查找 Active Directory 用户账号

有很多用于 Active Directory 的 Module 和 Cmdlet,但是有些时候用 .NET 代码来做反而更方便快捷。

比如说,如果您只是想知道,某个用户是否存在于您的 Active Directory中,那么实现查找一个用户是很容易的:

# sending LDAP query to Active Directory
$searcher = [ADSISearcher]'(&(objectClass=User)(objectCategory=person)(SamAccountName=tobias*))'
# finding first match
$searcher.FindOne()
# finding ALL matches
$searcher.FindAll()

这段代码将查找所有 SamAccountName 以 “tobias” 开头的用户账号。您可以接着用这个方法来便捷地找出这个用户所在的位置:

# find account location
$searcher.FindAll() | Select-Object -ExpandProperty Path

PowerShell 技能连载 - 在 ISE 中重设 PowerShell 宿主

想象一下您在 ISE 编辑器中长时间地编写一个脚本。当您开发的时候,您也许定义了变量、创建了函数、加载了对象,等等。

要确保您的脚本能像所希望的那样运行,您最终需要一个干净的测试环境。

获得一个干净的 PowerShell 并且移除所有变量和函数的最简单办法如下:

在 ISE 编辑器中,选择 文件 > 新建 PowerShell 选项卡。这实际上将创建一个新的 PowerShell 选项卡,以及一个全新的 PowerShell 宿主。这将确保没有任何不希望存在的旧变量和函数存在。

PowerShell 技能连载 - 查找 Cmdlet

Get-Command 可以用来查找 Cmdlet,但是在 PowerShell 3.0 中,它往往会返回比想象中还要多的 Cmdlet。由于自动加载模块的原因,Get-Command 不仅返回当前已加载 Module 中的 Cmdlet,还会返回所有可用 Module 中的 Cmdlet。

如果您仅希望在当前已加载的 Module 中查找一个 Cmdlet,请使用新的 -ListImported 参数:

PS> Get-Command -Verb Get | Measure-Object
Count    : 422

PS> Get-Command -Verb Get -ListImported | Measure-Object
Count    : 174

PowerShell 技能连载 - 从ISE编辑器中粘贴 PowerShell 代码

PowerShell ISE 编辑器的代码复制粘贴功能十分强大,例如将代码复制粘贴到 Microsoft Word 和其它文字处理器。由于 ISE 将剪贴板文字格式化为 RTF 格式,颜色代码将不会丢失。

然而,粘贴的时候字体往往太大或太小。

您可以在 ISE 编辑器中更改它。打开工具 > 选项,然后选择一个不同的字号。您在这儿选择的字号将用于粘贴的代码中。

当您更改完字号并关闭对话框之后,试着用 ISE 编辑器窗口右下角的滑块调整字体显示大小。这里的缩放级别只会影响 ISE 编辑器中的代码,并且不会影响粘贴的代码。

您也可以用鼠标滚轮来调整 ISE 编辑器中的显示字体大小。

PowerShell 技能连载 - 创建日历(和日期列表)

以下是一段创建 DateTime 集合的脚本片段。只需要指定年和月,脚本将会针对该月的每一天创建一个 DateTime 对象:

$month = 8
$year = 2013

1..[DateTime]::DaysInMonth($year,$month) |
  ForEach-Object { Get-Date -Day $_ -Month $month -Year $year }

这段代码十分有用:只要加一个日期过滤器,您就可以过滤出工作日来。它将列出指定月份的所有周一至周五(因为它排除了 weekday 0(星期日)和 weekday 6(星期六)):

$month = 8
$year = 2013

1..[DateTime]::DaysInMonth($year,$month) |
  ForEach-Object { Get-Date -Day $_ -Month $month -Year $year } |
  Where-Object { 0,6 -notcontains $_.DayOfWeek }

类似地,以下代码将统计指定月份所有星期三和星期五的天数:

$month = 8
$year = 2013

$days = 1..[DateTime]::DaysInMonth($year,$month) |
  ForEach-Object { Get-Date -Day $_ -Month $month -Year $year } |
  Where-Object { 3,5 -contains $_.DayOfWeek }

$days
"There are {0} Wednesdays and Fridays" -f $days.Count

PowerShell 技能连载 - 发生了什么?

经常地,您需要用 PowerShell 来获取数据,并且您需要提取信息的一部分并且把它们用于报表。类似如下:

$serial = Get-WmiObject -Class Win32_OperatingSystem |
  Select-Object -Property SerialNumber

"Serial Number is $serial"

但是上述代码产生的结果如下:

Serial Number is @{SerialNumber=00261-30000-00000-AA825}

当您查看 $serial 的值,它看起来似乎很正常:

PS> $serial

SerialNumber
------------
00261-30000-00000-AA825

但问题出在列头(译者注:我们只需要 SerialNumber 的值,而不是需要一个包含 SerialNumber 属性的临时对象)。您可以用 Select-Object 只选出一列,用 -ExpandProperty 而不是 -Property 就可以消除列头:

$serial = Get-WmiObject -Class Win32_OperatingSystem |
  Select-Object -ExpandProperty SerialNumber

"Serial Number is $serial"

现在,一切正常了:

Serial Number is 00261-30000-00000-AA825