PowerShell 技能连载 - 将网络连接模式从私有网络切到公有网络(反之亦然)

Starting with Windows Server 2012 R2 and Windows 8.1, PowerShell ships with many useful cmdlets for client and server configuration. This comes handy as some settings can no longer be controlled via UI.
从 Windows Server 2012 R2 和 Windows 8.1 开始,随着 PowerShell 发布了许多有用的客户端和服务器配置 cmdlet。这些 cmdlet 十分趁手,因为一些设置可以不再通过 UI 来控制。

例如,要改变网络的类型,只需要以管理员身份运行以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PS> Get-NetConnectionProfile


Name : internet-cafe
InterfaceAlias : WiFi
InterfaceIndex : 13
NetworkCategory : Private
IPv4Connectivity : Internet
IPv6Connectivity : Internet




PS> Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory Public -WhatIf
What if:

PowerShell 技能连载 - 移除 Windows 10 APP

PowerShell 可能是最简单的移除预装 Windows 10 APP 的方法。如果您知道想要移除的应用程序名称,只需要以管理员身份打开 PowerShell,然后像这样移除 APP:

1
2
3
4
PS> Get-AppxPackage *bingweather* | Remove-AppxPackage -WhatIf
What if: Performing the operation "Remove package" on target "Microsoft.BingWeather_4.20.1102.0_x64__8wekyb3d8bbwe".

PS>

注意:请去掉 -WhatIf 参数来实际移除 APP,不要删除作用不明的应用程序。可能其它 APP 会依赖这个 Appx 包。

PowerShell 技能连载 - Launching Daily Tools via Alias

您可能知道一些 PowerShell 预定义的缩写名称:例如 dirls 等别名能够节约您每天的打字时间。有许多好的原因值得扩展这些别名的列表并且增加您日常使用的工具。

例如,原先需要点击使用 SnippingTool 截屏工具,不如为它增加一个别名:

1
2
3
PS> Set-Alias -Name snip -Value snippingtool.exe

PS> snip

下一次您需要截取窗体的一部分到 bug 报告中时,只需要在 PowerShell 中运行 snip 即可。

另一个可能有用的工具是 osk.exe,您的 Windows 10 屏幕键盘,或者 mstsc.exe 来创建一个远程桌面连接。

要将您的别名持久化,只需要将它们增加到 PowerShell 配置文件脚本中。它的路径可以在这里找到:

1
2
PS> $profile.CurrentUserAllHosts
C:\Users\username\Documents\WindowsPowerShell\profile.ps1

这个文件默认不存在。如果您创建了它,脚本中的任何内容都会在您启动一个 PowerShell 宿主的时候执行。您只需要启用脚本执行一次即可:

1
PS> Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force

PowerShell 技能连载 - PowerShell 2 接近过期

Microsoft 刚刚宣布 PowerShell 2 很快将会标记为“已过期的”。它在一段时间内仍然可以用,但是友情提醒您最好不要使用它,并请关注 PowerShell 5。

PowerShell 2 是 Windows 7 缺省带的 PowerShell。但即使在现代的操作系统中,PowerShell 2 仍然存在。让我们看看 PowerShell 2 对你的系统有多大影响。

以下这行代码返回当前 PowerShell 的版本号:

1
2
PS> $PSVersionTable.PSVersion.Major
5

如果显示的版本号低于 5,那么您需要检查升级的策略。PowerShell 5 是 PowerShell 最新的版本,并且 Windows 7 和 Server 2008 R2 以上的版本都可以通过更新获得它。通常没有任何理由运行 PowerShell 5 以下的版本,除非在那些运行着过时的可能依赖于更早版本的 PowerShell 的软件组件的服务器上。

这行代码将告诉您 PowerShell 2 子系统是否仍然存在:

1
2
3
4
5
PS> powershell -version 2.0
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS>

如果这行代码运行后没有报任何错,并且启动了一个版权为“2009”的 PowerShell,那么说明 Windows 功能 PowerShell 2 还是启用状态。这不太好。这个功能原本是作为需要 PowerShell 2 的脚本的降级环境。现在该子系统基本不再使用,而变成一个恶意脚本代码的攻击维度,因为PowerShell 2 比起 PowerShell 5 缺少一些安全和保护功能。例如,相比于 PowerShell 5,运行在在 PowerShell 2 子系统中的恶意代码不会在反病毒引擎中有效地记录和报告。

除非有很强的理由保留 PowerShell 2,正常情况下您应该移除它。在客户端操作系统中,请打开控制面板,程序和功能,“启用或关闭 Windows 功能”,然后反选“Windows PowerShell 2.0”。

对于服务器系统,请使用 Remove-WindowsFeature

PowerShell 技能连载 - 准备磁盘驱动器

以前,我们用 chkdsk.exe 来修复磁盘。现在这个功能仍然能用。

从 Windows Server 2012 R2 和 Windows 8.1 开始,加入了一个新的 cmdlet,名字叫 Repair-Volume。类似 chkdsk.exe 它需要以管理员身份运行。

您可以用它来扫描驱动器的错误:

1
2
3
4
PS> Repair-Volume -Scan -DriveLetter c
NoErrorsFound

PS>

您也可以使用 cmdlet 来修复错误:

-OfflineScanAndFix 选项:将卷置于脱机,扫描并且修复所有遇到的错误(相当于 chkdsk /f)。

-SpotFix 选项:暂时将卷置于脱机,并只修复记录在 $corrupt 文件中的错误(相当于 chkdsk /spotfix)。

PowerShell 技能连载 - 查找 Windows 的产品密钥

当您需要从备份中还原电脑状态时,首先要知道您的 Windows 产品密钥。以下是一个简单的单行命令,可以获得产品密钥信息:

1
(Get-WmiObject -Class SoftwareLicensingService).OA3xOriginalProductKey

PowerShell 技能连载 - 获取缓存的凭据

在前一个技能中我们谈到一个名为“PSCredentialManager”的公共模块,可以用来管理缓存的凭据。有些时候,少即是多。当您阅读它的代码时,会发现它是通过一个名为 cmdkey.exe 的控制台命令在和 windows 系统打交道。

要获取您本机缓存的凭据,您只需要这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PS> cmdkey /list

Currently stored credentials:

Target: MicrosoftAccount:target=SSO_POP_User
Type: Domain Extended Credentials
User: XXXXX.com
Saved for this logon only

Target: MicrosoftAccount:target=SSO_POP_Device
Type: Domain Extended Credentials
User: 06jbdrfztrwsvsb
Saved for this logon only
...

它输出的是纯文本。然而,PowerShell 可以用 ForEach-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
27
28
29
30
cmdkey.exe /list | ForEach-Object {$found=$false} {
$line = $_.Trim()
if ($line -eq '')
{
if ($found) { $newobject }
$found = $false
$newobject = '' | Select-Object -Property Type, User, Info, Target
}
else
{
if ($line.StartsWith("Target: "))
{
$found = $true
$newobject.Target = $line.Substring(8)
}
elseif ($line.StartsWith("Type: "))
{
$newobject.Type = $line.Substring(6)
}
elseif ($line.StartsWith("User: "))
{
$newobject.User = $line.Substring(6)
}
else
{
$newobject.Info = $line
}

}
}

结果类似这样:

Type                        User                   Info                      Target
----                        ----                   ----                      ------
Domain Extended Credentials tabcabcabc@hicsawr.com Saved for this logon only Mi
Domain Extended Credentials 02jbqxcbqvsb           Saved for this logon only Mi
Generic                     tabcabcabc@hicsawr.com Local machine persistence Le
Generic                                            Local machine persistence Le
Generic                                            Local machine persistence Le
Generic                                            Local machine persistence Le
Generic                     tabcabcabc@hicsawr.com Local machine persistence Le
Generic                                            Local machine persistence Le
Generic                     02jdrxcbqvsb           Local machine persistence Wi
Generic                     Martin                                           Le
Domain Password             Martin                                           Do
Domain Password             Martin                                           Do
Domain Password             User                                             Do

PowerShell 技能连载 - 操作 PowerShell Gallery 内容

公共的 PowerShell Gallery (www.powershellgallery.com) 是一个 PowerShell 脚本作者们可以自由地交换脚本和模块的地方。您所需要的只是包含 PowerShellGet 的 PowerShell 5,它带了操作 Gallery 需要的 cmdlet。

当然,您需要自己确认代码,确保它可以完美运行,并且没有安全问题。

有一个模块叫做“PSCredentialManager”。以下是如何查看这个模块信息的方法:

1
2
3
4
5
6
7
8
9
10
11
12
PS> Find-Module -Name PSCredentialManager | Select-Object -Property *


Name : pscredentialmanager
Version : 1.0.1
Type : Module
Description : This module allows management and automation of Windows cached credentials.
Author : Adam Bertram
CompanyName : adamtheautomator
Copyright : (c) 2017 Adam Bertram. All rights reserved.
PublishedDate : 18.06.2017 22:14:27
...

要安装这个模块,请运行以下代码:

1
PS> Install-Module -Name PSCredentialManager -Scope CurrentUser -RequiredVersion 0.6

请注意我们显式地要求安装 0.6 版。在写这篇文章的时候,还有个 1.0.1 版,但存在一些问题。当您从一个公开的地方,例如 PowerShell Gallery 中获取内容,随时有可能得到非预期的结果,请留意。

如果您希望在安装一个模块前检查它的代码,可以使用 Save-Module,将模块下载到一个隔离的地方。

1
2
3
4
5
6
7
PS> Find-Module pscredentialmanager -AllVersions

Version Name Repository Description
------- ---- ---------- -----------
1.0.1 pscredentialmanager PSGallery This module allows
0.6 pscredentialmanager PSGallery This module allows
0.2 pscredentialmanager PSGallery This module allows

安装完成后,以下命令可以返回一个新 cmdlet 的列表:

1
2
3
4
5
6
7
PS> Get-Command -Module pscredentialmanager

CommandType Name Version Source
----------- ---- ------- ------
Function Get-CachedCredential 0.6 pscredentialmanager
Function New-CachedCredential 0.6 pscredentialmanager
Function Remove-CachedCredential 0.6 pscredentialmanager

您现在可以管理缓存的凭据。例如要返回一个缓存的凭据列表,请试试以下代码:

1
2
3
4
5
6
7
PS> Get-CachedCredential


Name : SSO_POP_User
Category : MicrosoftAccount
Type : Domain Extended Credentials
(...)

如果您想看看新的 cmdlet(也叫函数)如何工作,您还可以阅读它的源码。这行代码将函数的源码复制到剪贴板:

1
PS> ${function:Get-CachedCredential} | clip

要弃用这个模块,只需要卸载它:

1
PS> Uninstall-Module -Name pscredentialmanager -AllVersions

PowerShell 技能连载 - 计算文件夹大小

Measure-Object 也可以计算属性值的总和。它可以用来计算文件夹大小。以下代码计算用户配置文件(可能需要一些时间,视找到的文件数量而定)。它只是将所有文件的“Length”属性相加:

1
2
3
4
$size = (Get-ChildItem -Path $home -Force -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum

"Folder Size: $sum Bytes"
'Folder Size: {0:n2} MB' -f ($size/1MB)

输出的结果类似如下:

Folder Size: 172945767402 Bytes
Folder Size: 164.933,94 MB

您可为 Get-ChildItem 添加更多的参数,显式地控制哪些文件参加统计。例如这段代码添加了 -Filter 参数,并指定文件的扩展名,来只统计用户配置文件目录中找到的 PowerShell 脚本文件的大小。

1
2
3
4
$size = (Get-ChildItem -Path $home -Filter *.ps1 -Force -Recurse -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum

"Folder Size: $size Bytes"
'Folder Size: {0:n2} MB' -f ($size/1MB)

PowerShell 技能连载 - 高效统计文件数量(第二部分)

在前一个技能中我们学习了如何有效地统计一个文件夹中项目的数量。以下是更多的例子。

用 PowerShell 统计指定文件夹中文件的数量易如反掌:

1
2
3
4
5
$count = Get-ChildItem -Path "$home\Desktop" -Force |
Measure-Object |
Select-Object -ExpandProperty Count

"Number of files: $Count"

只需要调整 Get-ChildItem 的参数就可以找到更多。例如添加 -Recurse 开关,就可以包括子文件夹中的文件:

1
2
3
4
5
$count = Get-ChildItem -Path "$home\Desktop" -Force -Recurse -ErrorAction SilentlyContinue  |
Measure-Object |
Select-Object -ExpandProperty Count

"Number of files: $Count"

或者,只关注某些文件。这个例子只统计两层目录深度以内的 log 和 txt 文件:

1
2
3
4
5
$count = Get-ChildItem -Path $env:windir -Force -Recurse -Include *.log, *.txt -ErrorAction SilentlyContinue -Depth 2 |
Measure-Object |
Select-Object -ExpandProperty Count

"Number of files: $Count"

(请注意:-Depth 参数是 PowerShell 5 引入的)