PowerShell 技能连载 - 查找嵌套的 AD 组成员

以下代码查找某个 Active Directory 用户属于哪些组(包括嵌套的组成员)。该代码需要 ActiveDirectory 模块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#requires -Module ActiveDirectory

function Get-NestedGroupMember
{
param
(
[Parameter(Mandatory,ValueFromPipeline)]
[string]
$Identity
)

process
{
$user = Get-ADUser -Identity $Identity
$userdn = $user.DistinguishedName
$strFilter = "(member:1.2.840.113556.1.4.1941:=$userdn)"
Get-ADGroup -LDAPFilter $strFilter -ResultPageSize 1000
}
}

要查找组成员,只需要执行 Get-NestedGroupMember,跟上用户名即可。该函数和 Get-ADUser 接受同样的身份信息,所以您可以传入 SamAccountName、SID、GUID,或 distinguishedName。

PowerShell 技能连载 - 检查网络连接

如果您的机器通过不同网络连接,连到了 internet(或 VPN),以下两个函数可能对您有用。

Get-ActiveConnection 列出当前所有获取到 IP 地址的网络连接。Test-ActiveConnection 接受一个关键字并检查是否有一个名字中包含该关键字的活动连接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Get-ActiveConnection
{
Get-WmiObject -Class Win32_NetworkAdapterConfiguration |
Where-Object { $_.IPAddress } |
Select-Object -ExpandProperty Description
}

function Test-ActiveConnection
{
param([Parameter(Mandatory)]$Keyword)


@(Get-WmiObject -Class Win32_NetworkAdapterConfiguration |
Where-Object { $_.IPAddress } |
Where-Object { $_.Description -like "*$Keyword*" }).Count -gt 0

}

以下是一个快速的演示输出:

1
2
3
4
5
6
7
8
9
10
PS> Get-ActiveConnection
Dell Wireless 1820A 802.11ac

PS> Test-ActiveConnection dell
True

PS> if ( (Test-ActiveConnection dell) ) { Write-Warning "Connected via DELL network card" }
WARNING: Connected via DELL network card

PS>

PowerShell 技能连载 - 从 Windows 10 中移除臃肿的软件

Windows 10 附带了各种预装的应用程序和其它特性,这些内容可能是某些人反感。Richard Newton 创建了一个 PowerShell 脚本,用来识别和移除许多预装的特性,并且加强了隐私设置。他在 https://github.com/Sycnex/Windows10Debloater 描述了他的项目。

源码可以在这里找到:https://github.com/Sycnex/Windows10Debloater/blob/master/Windows10Debloater.ps1

我们向您推荐这个脚本因为它包含了许多有用的技术,演示了在 Windows 10 中如何移除应用和注册表键。当然,不建议在不了解的情况下运行这个脚本。请确保您了解将会移除什么内容,以及您是否真的希望移除它。

PowerShell 技能连载 - 通过 PowerShell 管理 FTP

在 PowerShell 中没有内置 FTP 命令,但是您可以方便地下载和安装一个免费的扩展,该扩展提供了您想要的 FTP 管理功能。只需要运行这行代码:

1
PS> Install-Module -Name Posh-SSH -Scope CurrentUser

如果 PowerShell 无法找到 Install-Module 命令,那么您很有可能没有运行最新版本的 PowerShell (5.1)。请升级您的 PowerShell,或者添加 Microsoft 的 “PowerShellGet” 模块,该模块提供了 Install-Module 命令。

该命令会会从公共的 PowerShell Gallery 下载 Posh-SSH 模块。当您同意下载内容之后,便新增了以下指令:

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
42
43
44
PS> Get-Command -Module Posh-SSH

CommandType Name Version Source
----------- ---- ------- ------
Function Get-PoshSSHModVersion 2.0.2 Posh-SSH
Function Get-SFTPChildItem 2.0.2 Posh-SSH
Function Get-SFTPContent 2.0.2 Posh-SSH
Function Get-SFTPLocation 2.0.2 Posh-SSH
Function Get-SFTPPathAttribute 2.0.2 Posh-SSH
Function Get-SFTPSession 2.0.2 Posh-SSH
Function Get-SSHPortForward 2.0.2 Posh-SSH
Function Get-SSHSession 2.0.2 Posh-SSH
Function Get-SSHTrustedHost 2.0.2 Posh-SSH
Function Invoke-SSHCommand 2.0.2 Posh-SSH
Function Invoke-SSHCommandStream 2.0.2 Posh-SSH
Function Invoke-SSHStreamExpectAction 2.0.2 Posh-SSH
Function Invoke-SSHStreamExpectSecureAction 2.0.2 Posh-SSH
Function New-SFTPFileStream 2.0.2 Posh-SSH
Function New-SFTPItem 2.0.2 Posh-SSH
Function New-SFTPSymlink 2.0.2 Posh-SSH
Function New-SSHDynamicPortForward 2.0.2 Posh-SSH
Function New-SSHLocalPortForward 2.0.2 Posh-SSH
Function New-SSHRemotePortForward 2.0.2 Posh-SSH
Function New-SSHShellStream 2.0.2 Posh-SSH
Function New-SSHTrustedHost 2.0.2 Posh-SSH
Function Remove-SFTPItem 2.0.2 Posh-SSH
Function Remove-SFTPSession 2.0.2 Posh-SSH
Function Remove-SSHSession 2.0.2 Posh-SSH
Function Remove-SSHTrustedHost 2.0.2 Posh-SSH
Function Rename-SFTPFile 2.0.2 Posh-SSH
Function Set-SFTPContent 2.0.2 Posh-SSH
Function Set-SFTPLocation 2.0.2 Posh-SSH
Function Set-SFTPPathAttribute 2.0.2 Posh-SSH
Function Start-SSHPortForward 2.0.2 Posh-SSH
Function Stop-SSHPortForward 2.0.2 Posh-SSH
Function Test-SFTPPath 2.0.2 Posh-SSH
Cmdlet Get-SCPFile 2.0.2 Posh-SSH
Cmdlet Get-SCPFolder 2.0.2 Posh-SSH
Cmdlet Get-SFTPFile 2.0.2 Posh-SSH
Cmdlet New-SFTPSession 2.0.2 Posh-SSH
Cmdlet New-SSHSession 2.0.2 Posh-SSH
Cmdlet Set-SCPFile 2.0.2 Posh-SSH
Cmdlet Set-SCPFolder 2.0.2 Posh-SSH
Cmdlet Set-SFTPFile 2.0.2 Posh-SSH

powershellmagazine.com 有一篇延伸的文章介绍如何使用这些命令:

PowerShell 技能连载 - 格式化数字(第 2 部分)

在前一个技能中我们介绍了 Get-DisplayFileSize 函数,它可以自动将字节数转换成容易阅读的带单位的数字,例如 “KB” 和 “MB”。

使用 Select-Object 指令,您可以创建一个带有易读的文件尺寸的文件夹列表:

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
$Length = @{
Name = "Length"
Expression = {
if ($_.PSIsContainer) { return }
$Number = $_.Length
$newNumber = $Number
$unit = 'Bytes,KB,MB,GB,TB,PB,EB,ZB' -split ','
$i = 0
while ($newNumber -ge 1KB -and $i -lt $unit.Length)
{
$newNumber /= 1KB
$i++
}

if ($i -eq $null) { $decimals = 0 } else { $decimals = 2 }
$displayText = "'{0,10:N$decimals} {1}'" -f $newNumber, $unit[$i]
$Number = $Number | Add-Member -MemberType ScriptMethod -Name ToString -Value ([Scriptblock]::Create($displayText)) -Force -PassThru
return $Number
}
}


# pretty file sizes
dir $env:windir |
Select-Object -Property Mode, LastWriteTime, $Length, Name |
Sort-Object -Property Length

请注意计算属性 Length 仍然可以用于排序。它仍是字节数据,只是显示的方式改变了。

PowerShell 技能连载 - 格式化数字(第 1 部分)

以下 Get-DisplayFileSize 函数接受任何字节数值,并且返回一个以 “MB”、”GB” 或 “PB” 为单位的,格式良好的大小值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Get-DisplayFileSize
{
param([Double]$Number)

$newNumber = $Number

$unit = ',KB,MB,GB,TB,PB,EB,ZB' -split ','
$i = $null
while ($newNumber -ge 1KB -and $i -lt $unit.Length)
{
$newNumber /= 1KB
$i++
}

if ($i -eq $null) { return $number }
$displayText = "'{0:N2} {1}'" -f $newNumber, $unit[$i]
$Number = $Number | Add-Member -MemberType ScriptMethod -Name ToString -Value ([Scriptblock]::Create($displayText)) -Force -PassThru
return $Number
}

以下是一些例子:

1
2
3
4
5
6
7
8
PS> Get-DisplayFileSize -Number 800
800

PS> Get-DisplayFileSize -Number 678678674345
632,07 GB

PS> Get-DisplayFileSize -Number 6.23GB
6,23 GB

真正有趣的地方是这个函数返回的并不是字符串。它返回的是原始的数值,而只是覆盖了 ToString() 方法。您仍然可以对它进行排序、计算和对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
PS> $n = 1245646233213
PS> $formatted = Get-DisplayFileSize -Number $n
PS> $formatted
1,13 TB

PS> $formatted -eq $n
True

PS> $formatted * 2
2491292466426

PS> Get-DisplayFileSize ($formatted * 2)
2,27 TB

PowerShell 技能连载 - 过滤文件

您可能还没有注意到,Get-ChildItem(也叫做 dir 或者 ls) 的 -Filter 参数并不是像您所想的方式工作。以下代码的本意是只查找 PowerShell 脚本,但实际上找到的结果更多:

1
2
Get-ChildItem -Path $env:windir -Filter *.ps1 -Recurse -ErrorAction Silent |
Group-Object -Property Extension -NoElement

以下是查找结果:

1
2
3
4
Count Name
----- ----
800 .ps1
372 .ps1xml

-Filter 参数的作用和传统的 dir 命令的行为类似。要真正起到您想要的效果,您应该使用以下代码:

1
2
Get-ChildItem -Path $env:windir -Filter *.ps1 -Include *.ps1 -Recurse -ErrorAction SilentlyContinue |
Group-Object -Property Extension -NoElement

以下是正确的结果:

1
2
3
Count Name
----- ----
800 .ps1

虽然您可以省略 -Filter 参数,但强烈建议保留着它。首先,-Include 只能和 -Recurse 配合使用其次,-Include 速度很慢。先用一个粗略(但是快速)的 -Filter 过滤,然后用 Include 是最佳实践。

PowerShell 技能连载 - 用网格视图窗口显示列表视图(第 3 部分)

在前一个技能中我们介绍了 ConvertObject-ToHashTable 函数,它能方便地将对象显示在一个网格视图窗口中。

以下代码是一个改进的版本,能够根据字母顺序排列属性,并且可以由您决定每一列的名称。缺省情况下,Out-GridView 的列名为 “Property” 和 “Value”,但您将它们改为任意名称:

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
function ConvertObject-ToHashTable
{
param
(
[Parameter(Mandatory,ValueFromPipeline)]
$object,

[string]
$PropertyName = "Property",

[string]
$ValueName = "Value"
)

process
{
$object |
Get-Member -MemberType *Property |
Select-Object -ExpandProperty Name |
Sort-Object |
ForEach-Object { [PSCustomObject]@{
$PropertyName = $_
$ValueName = $object.$_}
}
}
}

Get-ComputerInfo |
# by default, columns are named "Property" and "Value"
ConvertObject-ToHashTable |
Out-GridView


Get-WmiObject -Class Win32_BIOS |
# specify how you'd like to call the columns displayed in a grid view window
ConvertObject-ToHashTable -PropertyName Information -ValueName Data |
Out-GridView

PowerShell 技能连载 - 用网格视图窗口显示列表视图(第 2 部分)

Out-GridView 是一个有用的 cmdlet。但如果只是用它来显示一个单一对象的所有属性时不太理想,因为这样显示出来只有一行。在前一个技能中我们解释了将一个对象转换为一个哈希表能解决这个问题。它实际上是将一个网格视图工作在“列表视图”模式。

因为这个方法在许多场景中十分有用,以下是一个封装好的名为 ConvertObject-ToHashTable 的函数,以及一系列示例代码:

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
function ConvertObject-ToHashTable
{
param
(
[Parameter(Mandatory,ValueFromPipeline)]
$object
)

process
{
$object |
Get-Member -MemberType *Property |
Select-Object -ExpandProperty Name |
Sort-Object |
ForEach-Object { [PSCustomObject]@{
Item = $_
Value = $object.$_}
}
}
}

systeminfo.exe /FO CSV | ConvertFrom-Csv | ConvertObject-ToHashTable | Out-GridView

Get-ComputerInfo | ConvertObject-ToHashTable | Out-GridView

Get-WmiObject -Class Win32_BIOS | ConvertObject-ToHashTable | Out-GridView

PowerShell 技能连载 - 用网格视图窗口显示列表视图(第 1 部分)

一个最简单的硬件清单功能可以用一行代码实现:

1
2
$data = systeminfo.exe /FO CSV | ConvertFrom-Csv
$data | Out-GridView

一个更现代的方法是使用新的 Get-ComputerInfo cmdlet:

1
2
$data = Get-ComputerInfo
$data | Out-GridView

一个最简单方法是用 Group-Object 创建一个哈希表:将原始数据用某个属性,例如 UserName` 来分组。然后,在网格视图窗口中显示哈希表的键。当用户选择了一个对象时,将选中的项目作为哈希表的键,找到原始项目:

1
2
3
4
5
6
7
$data = Get-ComputerInfo

$data |
Get-Member -MemberType *Property |
Select-Object -ExpandProperty Name |
ForEach-Object { $hash = @{}} { $hash[$_] = $data.$_ } { $hash } |
Out-GridView

现在网格视图窗口以更好的方式显示信息。这段代码用 Get-Member 来查找信息对象 $data 中暴露的属性名。它接下来创建一个哈希表,每个属性代表一个键,每个值代表一个属性值。

本质上,网格视图窗口现在显示的是多个键值对,而不是单一的一个对象。