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 中暴露的属性名。它接下来创建一个哈希表,每个属性代表一个键,每个值代表一个属性值。

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

PowerShell 技能连载 - 快速创建逗号分隔的字符串(第 2 部分)

在前一个技能中我们演示了如何用 PowerShell 命令模式方便地创建引号包围的字符串列表。这可以很方便地创建代码,节省很多打字工作。

以下是一个在日常 PowerShell 编码工作中有用的函数:

1
function s+ { "'$($args -join "','")'" | Set-ClipBoard }

下一次您在代码中需要一个引号包围的字符串列表时,只需要键入:

1
2
3
4
5
6
7
8
9
10
PS> s+ start stop pause end whatever

PS> 'start','stop','pause','end','whatever'
start
stop
pause
end
whatever

PS>

执行完之后,引号包围的字符串就会存在您的剪贴板中,接下来您可以将它们粘贴到任何需要的地方。

PowerShell 技能连载 - 快速创建逗号分隔的字符串(第 1 部分)

这是一个非常简单的创建引号包起来的字符串的列表的例子:

1
& { "'$($args -join "','")'" } hello this is a test

以下是执行结果:

1
'hello','this','is','a','test'

这个例子有效利用了 PowerShell 的“命令模式”,字面量被当作参数使用。您还可以将结果通过管道导出到 Set-Clipboard 指令执行,然后将结果贴回代码中。这比起手工为每个字符串添加引号方便多了。

1
2
3
4
PS> & { "'$($args -join "','")'" } hello this is a test  | Set-ClipBoard

PS> Get-ClipBoard
'hello','this','is','a','test'