PowerShell 技能连载 - 到处 ActiveDirectory 模块

要在 PowerShell 中管理 Active Directory 的用户和计算机,您需要 Microsoft 提供的免费的 RSAT 工具中的 Active Directory 模块。

假设您是一个域管理员并且拥有远程管理域控制器的权限,您也可以从 DC 中导出 ActiveDirectory 模块,并且可以通过隐式远程操作在本地使用它。

以下是使用方法:

1
2
3
4
5
6
7
8
9
$DC = 'dc1'  # rename, must be name of one of your domain controllers

# create a session
$s = New-PSSession -ComputerName dc1
# export the ActiveDirectory module from the server to a local module "ADStuff"
Export-PSSession -Session $s -OutputModule ADStuff -Module ActiveDirectory -AllowClobber -Force

# remove session
Remove-PSSession $s

当您运行这段代码时,并且您拥有连接到 DC 的权限时,这段代码创建了一个名为 “ADStuff” 的本地 module,其中包含了所有 AD cmdlet。您可以通过隐式远程处理使用 AD cmdlet而不需要安装 RSAT 工具。

警告:由于所有 cmdlet 实际上都是运行在服务器端,所有结果都被序列化后传到本地。这会改变对象类型,所以当您用将对象通过管道从一个 AD cmdlet 传到另一个 AD cmdlet 时,您可能会遇到绑定问题。只要您在管道之外使用 cmdlet,那么一切都没问题。

PowerShell 技能连载 - 管理 NTFS 权限

由于没有内置的管理 NTFS 权限的 cmdlet,所以有越来越多的开源 PowerShell module 实现这个功能。一个有前途的 module 是由 Raimund Andree,一个德国的 Microsoft 工程师写的。他也将在即将到来的 PowerShell 欧洲会议 (www.psconf.eu) 中演讲。

如果您使用的是 PowerShell 5 或已经安装了 PowerShellGet (www.powershellgallery.com),以下是从 PowerShell Gallery 下载并安装 “NTFSSecurity” module 的方法:

1
2
3
4
5
# review module details
Find-Module -Repository PSGallery -Name NTFSSecurity | Select-Object -Property * | Out-GridView

# download module
Install-Module -Repository PSGallery -Name NTFSSecurity -Scope CurrentUser

要查看所有的新 cmdlet,请试试这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
PS C:\> Get-Command -Module NTFSSecurity

CommandType Name Version

----------- ---- -------
Cmdlet Add-NTFSAccess 4.2.3
Cmdlet Add-NTFSAudit 4.2.3
Cmdlet Clear-NTFSAccess 4.2.3
Cmdlet Clear-NTFSAudit 4.2.3
Cmdlet Copy-Item2 4.2.3
Cmdlet Disable-NTFSAccessInheritance 4.2.3
Cmdlet Disable-NTFSAuditInheritance 4.2.3
Cmdlet Disable-Privileges 4.2.3
Cmdlet Enable-NTFSAccessInheritance 4.2.3
Cmdlet Enable-NTFSAuditInheritance 4.2.3
Cmdlet Enable-Privileges 4.2.3
Cmdlet Get-ChildItem2 4.2.3
Cmdlet Get-DiskSpace 4.2.3
Cmdlet Get-FileHash2 4.2.3
Cmdlet Get-Item2 4.2.3
Cmdlet Get-NTFSAccess 4.2.3
Cmdlet Get-NTFSAudit 4.2.3
Cmdlet Get-NTFSEffectiveAccess 4.2.3
Cmdlet Get-NTFSHardLink 4.2.3
Cmdlet Get-NTFSInheritance 4.2.3
Cmdlet Get-NTFSOrphanedAccess 4.2.3
Cmdlet Get-NTFSOrphanedAudit 4.2.3
Cmdlet Get-NTFSOwner 4.2.3
Cmdlet Get-NTFSSecurityDescriptor 4.2.3
Cmdlet Get-NTFSSimpleAccess 4.2.3
Cmdlet Get-Privileges 4.2.3
Cmdlet Move-Item2 4.2.3
Cmdlet New-NTFSHardLink 4.2.3
Cmdlet New-NTFSSymbolicLink 4.2.3
Cmdlet Remove-Item2 4.2.3
Cmdlet Remove-NTFSAccess 4.2.3
Cmdlet Remove-NTFSAudit 4.2.3
Cmdlet Set-NTFSInheritance 4.2.3
Cmdlet Set-NTFSOwner 4.2.3
Cmdlet Set-NTFSSecurityDescriptor 4.2.3
Cmdlet Test-Path2 4.2.3

当您获取到这些 cmdlet,那么增加或设置 NTFS 权限就轻而易举:

1
2
3
4
5
6
$path = 'c:\test1'

mkdir $path

Get-NTFSAccess -Path $Path |
Add-NTFSAccess -Account training14\student14 -AccessRights CreateFiles -AccessType Allow

警告:您需要管理员权限才能更改 NTFS 权限,即使是操作您拥有的文件系统对象。

PowerShell 技能连载 - 使用通配符确定数组是否包含值

当您想了解一个数组是否包含某个指定的元素,PowerShell 提供了 -contains 操作符。然而这个操作符不支持通配符,所以您只能使用精确匹配。

以下是一个帮助您使用通配符过滤数组元素的解决方法:

1
2
3
4
5
6
7
8
9
$a = 'Hanover', 'Hamburg', 'Vienna', 'Zurich'

# is the exact phrase present in array?
$a -contains 'Hannover'
# is ANY phrase present in array that matches the wildcard expression?
(@($a) -like 'Ha*').Count -gt 0

# list all phrases from array that match the wildcard expressions
@($a) -like 'Ha*'

PowerShell 技能连载 - 处理 LDAP 和日期

LDAP 过滤器是一个快速和强大的从 Active Directory 中获取信息的方法。然而,LDAP 过滤器使用的是一个很底层的日期和时间格式。它基本上是一个很大的整形数。幸运的是 PowerShell 包含多种将实际 DateTime 对象转换为这些数字,以及相反操作的方法。

以下是一个使用 ActiveDirectory 模块中 Get-ADUser 方法来查找所有近期更改了密码的用户的示例代码。如果您没有这个 module,请从 Microsoft 下载免费的 RSAT 工具。

1
2
3
4
5
6
7
8
# find all AD Users who changed their password in the last 5 days
$date = (Get-Date).AddDays(-5)
$ticks = $date.ToFileTime()


$ldap = "(&(objectCategory=person)(objectClass=user)(pwdLastSet>=$ticks))"
Get-ADUser -LDAPFilter $ldap -Properties * |
Select-Object -Property Name, PasswordLastSet

PowerShell 技能连载 - 使用 PowerShell 参数验证器

PowerShell 的函数参数支持 ValidateScript 属性,可以关联到一段 PowerShell 代码。当该参数接收到一个值时,该代码将会被调用,并且返回 $true$false。如果该代码返回 $false 则该参数被拒绝。

以下是一个仅接受 Windows 文件夹中存在的文件的文件名的例子:

1
2
3
4
5
6
7
8
9
10
11
12
function Get-File
{
param
(
[Parameter(Mandatory)]
[ValidateScript({ Test-Path -Path "$env:windir\$_" })]
[string]
$File
)

"$File exists in your Windows folder."
}

以下是使用效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
PS C:\> Get-File  -File explorer.exe
explorer.exe exists in your Windows folder.

PS C:\> Get-File -File something.exe
Get-File : Cannot validate argument on parameter 'File'. The " Test-Path -Path "$env:windir\$_" " validation script for the argument with value "something.exe" did not return a result of True. Determine why the validation script failed, and then try the command again.
At line:1 char:16
+ Get-File -File something.exe
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-File], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Get-File

PS C:\> Get-File -File memory.dmp
memory.dmp exists in your Windows folder.

PowerShell 技能连载 - 按区域转换数据

当转换数据(将它转换为不同的数据类型)时,PowerShell 支持两种不同的方式方式。

以下是一个例子:

1
2
[DateTime]'12.1.2017'
'12.1.2017' -as [DateTime]

两行代码都将一个字符串转为一个 DateTime 对象。第一行代码代表强制转换。它可能成功也有可能失败,并且它总是使用语言中性的格式(US 格式),所以它应为一个 月-日-年 格式。

第二行代表“尝试转换”:该转换要么成功要么静默地返回 $null。该转换遵循当前的区域设置,所以如果您在一个德文系统众运行这段代码,这段文字被解释成 日-月-年 格式。

PowerShell 技能连载 - 调用一个脚本块

可以通过调用操作符,例如 “&“、”.“ 或调用 Invoke() 方法调用在一个脚本块中的代码。

一个区别是当有多于一个结果时的输出:调用操作符返回一个扁平的对象数组,而 Invoke() 返回一个集合:

1
2
3
4
5
6
7
$code = { Get-Process }

$result1 = & $code
$result2 = $code.Invoke()

$result1.GetType().FullName
$result2.GetType().FullName

通过 Invoke() 方法返回的集合拥有额外的方法,例如 RemoveAt()Insert(),它们能够帮您修改结果数据,能高效地插入或删除元素。

您可以手动将一个 cmdlet 的返回值手动转为一个 ArrayList:

1
$arrayList = [Collections.ArrayList]@(Get-Process)

PowerShell 技能连载 - 不带动词运行 Cmdlet

这是从 PowerShell 1.0 开始就具有的一个特性:调用动词为 “get” 的 cmdlet 可以省略动词。所以调用 “Get-Service“ 时您可以仅执行 “Service“调用 “Get-Date“ 时可以仅执行 “Date“。

以下不是别名,甚至 PowerShell 引擎并不知道为什么它能工作。请试试这些代码:

1
2
PS> Date
PS> Get-Command Date

使用这个快捷方式的前提是没有冲突的命令或语法元素。这也是为什么您可以运行 “Get-Process“,但不能运行 “Process“ 的原因:”Process“ 是 PowerShell 语言中的一个保留关键字。

PowerShell 技能连载 - 限制文本的长度(第二部分)

以下是确保一段文本不超过指定长度的另一种策略。和前一个技能不同的是,当文本长度小于最大长度时,这段代码不会补齐空格:

1
2
3
4
$text = 'this'
$MaxLength = 10
$CutOff = [Math]::Min($MaxLength, $text.Length)
$text.Substring(0,$CutOff)

关键点在 Min() 函数,它决定了两个值中小的哪个。

PowerShell 技能连载 - 限制文本的长度(第一部分)

如果您想将一个文本的长度限制在某一个长度,以下是一个简单的方法:

1
2
3
4
$text = 'this is a long text'
$MaxLength = 10

$text.PadRight($MaxLength).Substring(0,$MaxLength)

这段代码首先对文本填充,以防它比最大长度还短,然后使用 Substring() 裁剪掉多余的文本。