PowerShell 技能连载 - 使用 PSGraph

PSGraph 是一个非常棒的免费 PowerShell 库,您可以用它来将关系可视化。在使用 PSGraph 之前,需要安装它的依赖项(graphviz 引擎)。两者都需要管理员特权:

1
2
3
4
5
6
7
8
#requires -RunAsAdministrator

# install prerequisite (graphviz)
Register-PackageSource -Name Chocolatey -ProviderName Chocolatey -Location http://chocolatey.org/api/v2/
Find-Package graphviz | Install-Package -ForceBootstrap

# install PowerShell module
Install-Module -Name PSGraph

安装完成后,这是如何将对象关系可视化的代码:

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
$webServers = 'Web1','Web2','web3'
$apiServers = 'api1','api2'
$databaseServers = 'db1'

graph site1 {
# External/DMZ nodes
subgraph 0 -Attributes @{label='DMZ'} {
node 'loadbalancer' @{shape='house'}
rank $webServers
node $webServers @{shape='rect'}
edge 'loadbalancer' $webServers
}

subgraph 1 -Attributes @{label='Internal'} {
# Internal API servers
rank $apiServers
node $apiServers
edge $webServers -to $apiServers

# Database Servers
rank $databaseServers
node $databaseServers @{shape='octagon'}
edge $apiServers -to $databaseServers
}
} | Export-PSGraph -ShowGraph

这个例子中创建的图形使用脚本文件中的 hypothetical 服务器并向其添加合适的关系,并显示图像。

查看更多

评论

PowerShell 技能连载 - 使用 AD 过滤器配合 cmdlet(第 4 部分)

在前一个技能中,我们开始学习 ActiveDirectory 模块(免费的 RSAT 工具)中的 cmdlet 如何过滤执行结果,并且学习了如何合并过滤器表达式。今天我们将学习如何处理日期和时间。

有些 AD 属性包含日期和时间信息,例如上次登录的日期。这类信息是以一串非常长的 64 位整数标识的。您可以在 LDAP 过滤器中以这种格式使用日期和时间。

例如,要查找近 4 个星期中没有修改密码的所有用户:

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
$weeks = 4
# first, find out the AD time format from
# 4 weeks ago that will be used in the LDAPFilter

$today = Get-Date
# 4 weeks ago
$cutDate = $today.AddDays(-($weeks * 7))
# translate in AD time format
$cutDateAD = $cutDate.ToFileTimeUtc()

# next, find a way to convert back the AD file format
$realDate = @{
Name = 'Date'
Expression = { if ($_.pwdLastset -eq 0)
{
'[never]'
}
else
{
[DateTime]::FromFileTimeUtc($_.pwdLastset)
}
}

}

Get-ADUser -LDAPFilter "(pwdLastSet<=$cutDateAD)" -Properties pwdLastSet |
Select-Object -Property samaccountname, $realDate

实际上,当调用一个 DateTime 对象的 ToFileTimeUtc() 方法之后,将返回 AD 格式的数据。类似地,当您运行 [DateTime]::FromFileTimeUtc() 时,将会把 AD 格式转换为一个真实的 DateTime 对象。

查看更多

评论

PowerShell 技能连载 - 使用 AD 过滤器配合 cmdlet(第 3 部分)

在之前的技能中,我们开始学习 ActiveDirectory 模块(免费的 RSAT 工具)中的 cmdlet 如何过滤执行结果,并且开始以我们的方式插入快捷且完善的 LDAP 过滤器。

LDAP 过滤器有一个强制的需求。您必须使用原始的 ActiveDirectory 属性名,而不是许多 PowerShell cmdlet 中的友好名称。所以 “country” 需要改为 AD 的属性名 “co”。当您坚持使用这些名字后,创建 LDAP 过滤器十分容易。

这行代码将会从 Active Directory 中获取所有 Windows 10 计算机:

1
2
Get-ADComputer -LDAPFilter '(operatingSystem=*10*)' -Properties operatingSystem |
Select-Object samaccountname, operatingSystem

如果您想合并多个过滤器,请将它们加到小括号中,然后在前面添加 “&” 进行逻辑与操作,添加 “|” 进行逻辑或操作。所以这行代码查找所有从 Wuppertal 城市,名字以 “A” 开头的用户:

1
Get-ADUser -LDAPFilter '(&(l=Wuppertal)(name=a*))'

查看更多

评论

PowerShell 技能连载 - 使用 AD 过滤器配合 cmdlet(第 2 部分)

在前一个技能中,我们开始学习 ActiveDirectory 模块(免费的 RSAT 工具)中的 cmdlet 如何过滤执行结果。您学到了过滤器看起来像 PowerShell 代码,但是实际上不是。

对于简单的过滤,该过滤器工作正常。然而,当您使用操作符以外的 PowerShell 语言特性时,您很快会发现实际中使用的过滤器并不是 PowerShell 代码。

如果您想获得一个未配置文件路径的 AD 用户列表,您可能会好奇地尝试以下的代码:

1
2
Get-ADUser -Filter { profilePath -eq $null} -ResultSetSize 5
Get-ADUser -Filter { profilePath -eq ''} -ResultSetSize 5

两个过滤器都会失败。PowerShell 报告 $null 变量是未知的。而在第二行中,报告该该搜索查询不合法。

这是为什么大多数情况下使用在 Active Directory 常见的原生 LDAPFilters 是更方便(而且更快)的。LDAP 过滤器是括号中的表达式。它们包含一个名称和一个操作符。以下代码返回前 5 个有配置文件路径的用户:

1
Get-ADUser -LDAPFilter '(profilePath=*)' -ResultSetSize 5

加上 “!” 以后,可以将结果反转,所以以下代码将返回前 5 个没有配置文件路径的用户:

1
Get-ADUser -LDAPFilter '(!profilePath=*)' -ResultSetSize 5

以下代码将返回用户和他们的配置文件路径的列表:

1
2
Get-ADUser -LDAPFilter '(profilePath=*)' -Properties profilePath |
Select-Object samaccountName, profilePath

查看更多

评论

PowerShell 技能连载 - 使用 AD 过滤器配合 cmdlet(第 1 部分)

ActiveDirectory Powershell 模块中包含了免费的 RSAT 工具。您可以使用这个模块中的 cmdlet 来获取 AD 信息,例如用户或者组名。例如 Get-ADUserGet-ADComputer 等 cmdlet 支持服务端过滤器。不过,它们的工作方式可能和您设想的略有不同。

对于简单的查询,这些过滤器使用起来很容易。例如,这行代码筛选出前五个名字以 “A” 开头的用户,而且过滤器的语法看起来很像 PowerShell 代码:

1
Get-ADUser -Filter { name -like 'A*' } -ResultSetSize 5

不过它还不是真的 PowerShell 语法:-Filter 参数接受的是纯文本,所以您也可以使用引号代替大括号:

1
Get-ADUser -Filter " name -like 'A*' " -ResultSetSize 5

使用大括号(脚本块)仍是一个好主意,因为大括号包括的是 PowerShell 代码,所以在大括号内写代码时可以获得代码高亮和语法错误特性。脚本块稍后可以方便地转换为字符串(Get-ADUser 会自动处理)。

查看更多

评论

PowerShell 技能连载 - 创建临时文件名

当您需要写入信息到磁盘时,使用唯一的临时文件名是合理的。如果您使用静态的文件名并且多次运行您的代码,会一次又一次地覆盖写入同一个文件。如果某个人打开该文件并锁定它,将导致脚本执行失败。

以下是一些简单的生成唯一的临时文件名的方法:

1
2
3
4
5
6
7
8
9
10
11
# use a random number (slight chance of duplicates)
$path = "$env:temp\liste$(Get-Random).csv"
"Path is: $path"

# use a GUID. Guaranteed to be unique but somewhat hard on the human eye
$path = "$env:temp\liste$([Guid]::NewGuid().toString()).csv"
"Path is: $path"

# use timestamp with milliseconds
$path = "$env:temp\liste$(Get-Date -format yyyy-MM-dd_HHmmss_ffff).csv"
"Path is: $path"

查看更多

评论

PowerShell 技能连载 - 文件系统压力测试

如果您想生成一个超大文件来做压力测试,您不需要浪费时间写入大量数据到一个文件中,使它体积增大。相反,只需要设置一个期望的文件大小来占据磁盘空间即可。

以下是创建一个 1GB 测试文件的方法:

1
2
3
4
5
6
7
8
9
10
# create a test file
$path = "$env:temp\dummyFile.txt"
$file = [System.IO.File]::Create($path)

# set the file size (file uses random content)
$file.SetLength(1gb)
$file.Close()

# view file properties
Get-Item $path

查看更多

评论

PowerShell 技能连载 - 通过参数传递命令

函数参数有一个很少见的用法:用户可以传入一个输出命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Get-ProcessList
{
param
(
[string]
[ValidateSet('GridView','String')]
$OutputMode = 'String'
)

Get-Process | & "Out-$OutputMode"

}

# output as a string
Get-ProcessList -OutputMode String
# output in a grid view window
Get-ProcessList -OutputMode GridView

查看更多

评论

PowerShell 技能连载 - 处理文件编码和 BOM

当您将文本内容写入到文件时,PowerShell cmdlet 可以指定文件编码。编码决定了字符的存储方式,并且当某个字符显示乱码时,通常是由于编码不匹配造成的。

然而,有一些编码设置是无法通过 cmdlet 参数控制的。以下是一个例子。将一个进程列表保存到 CSV 文件:

1
2
3
4
$Path = "$env:temp\export.csv"

Get-Process |
Export-CSV -NoTypeInformation -UseCulture -Encoding UTF8 -Path $Path

您现在可以在 Excel 或任意文本编辑器中打开生成的 CSV 文件。当您使用 Notepad++ 打开文件时,状态栏显示编码格式为:UTF-8-BOM。

这段 PowerShell 代码以 UTF-8 编码生成文件,所以这段没有问题。BOM 代表“字节顺序标记” (Byte Order Mark)。当使用 BOM 时,将在文件的起始处增加一个特定的字节顺序标识,这样程序可以自动识别使用的编码格式。

不过,一些编辑器和数据处理系统无法处理 BOM。要移除 BOM 并使用纯文本编码,请使用类似这样的 PowerShell 代码:

1
2
3
4
5
6
function Remove-BomFromFile($OldPath, $NewPath)
{
$Content = Get-Content $OldPath -Raw
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines($NewPath, $Content, $Utf8NoBomEncoding)
}

在上述例子中,要将 UTF-8-BOM 转化为纯 UTF-8,请运行这段代码:

1
2
3
$Path = "$env:temp\export.csv"
$NewPath = "$env:temp\export_new.csv"
Remove-BomFromFile -OldPath $Path -NewPath $NewPath

查看更多

评论

PowerShell 技能连载 - 查找嵌套的 Active Directory 成员(第 3 部分)

在前一个技能中我们演示了如何使用 ActiveDirectory 模块中的 cmdlet 来查找某个 Active Directory 用户所有直接和间接的成员。如果您想知道当前用户的成员信息,还有一个更简单(而且更快)的方法:用当前用户的 access token 来获取当前有效的组成员:

1
2
3
4
5
$groups = [System.Security.Principal.WindowsIdentity]::GetCurrent().Groups.Translate([System.Security.Principal.NTAccount]) 

$groups

$groups.Count

查看更多

评论