PowerShell 技能连载 - Out-GridView 自定义列

当您使用 -OutputMode-PassThru 参数时,Out-GridView 可以是一个通用对话框。执行此操作时,网格视图窗口会在其右下角显示其他按钮,以便您可以选择项目并将它们传递给其他 cmdlet。

此行代码可以帮助选择要停止的服务,例如:

1
Get-Service | Where-Object CanStop | Out-GridView -Title 'Service to stop?' -OutputMode Single | Stop-Service -WhatIf

但是,Out-GridView 无法控制它显示的属性。在上面的示例中,用户实际上只需要查看服务名称以及可能的依赖服务。

当然,您可以使用 Select-Object 来选择要显示的属性。现在网格视图窗口将准确显示您要求的列,但由于您永久删除了所有其他属性并更改了对象类型,后续 cmdlet 可能会如你所想的不能正常工作:

1
Get-Service | Where-Object CanStop | Select-Object -Property DisplayName, DependentServices | Out-GridView -Title 'Service to stop?' -OutputMode Single | Stop-Service -WhatIf

运行上面这行代码时,网格视图窗口现在看起来很棒,但 Stop-Service 将不再停止选择您选择的服务,因为 Select-Object 将对象类型从 Service 更改为自定义对象:

Stop-Service : The specified wildcard character pattern is not valid: @{DisplayName=Windows Audio Endpoint Builder;
DependentServices=System.ServiceProcess.ServiceController[]}

在上一个技能中,我们已经使用了一种隐藏的技术,您可以使用它来告诉 Out-GridView 它应该显示哪些列——无需删除任何属性或更改对象类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# create object that tells PowerShell which column(s) should be visible:
# show "DisplayName", and "DependentServices"
[string[]]$visible = 'DisplayName', 'DependentServices'
$type = 'DefaultDisplayPropertySet'
[System.Management.Automation.PSMemberInfo[]]$info =
[System.Management.Automation.PSPropertySet]::new($type,$visible)


Get-Service |
Where-Object CanStop |
# add the secret object to each object that you pipe into Out-GridView:
Add-Member -MemberType MemberSet -Name PSStandardMembers -Value $info -PassThru |
Out-GridView -Title 'Service to stop?' -OutputMode Single |
Stop-Service -WhatIf

不幸的是,当您这样做时,您可能会遇到红色错误消息。某些 PowerShell 对象(例如 Service)已经使用了我们尝试添加的巧妙技巧,因此您无法覆盖 PSStandardMembers 属性。要解决此问题,只需通过 Select-Object * 运行它们来克隆对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# create object that tells PowerShell which column(s) should be visible:
# show "DisplayName", and "DependentServices"
[string[]]$visible = 'DisplayName', 'DependentServices'
$type = 'DefaultDisplayPropertySet'
[System.Management.Automation.PSMemberInfo[]]$info =
[System.Management.Automation.PSPropertySet]::new($type,$visible)


Get-Service |
Where-Object CanStop |
# clone the objects so they now belong to you:
Select-Object -Property * |
# add the secret object to each object that you pipe into Out-GridView:
Add-Member -MemberType MemberSet -Name PSStandardMembers -Value $info -PassThru |
Out-GridView -Title 'Service to stop?' -OutputMode Single |
Stop-Service -WhatIf

现在一切都很神奇,Out-GridView 仅显示您选择的属性。尽管如此,Stop-Process 继续获得输出信息并停止您选择的服务(删除 -WhatIf 来真实地停止服务,请确保您有管理员权限进行此操作)。

虽然通过 Select-Object 运行对象确实会更改其对象类型,但大多数 cmdlet 仍会继续处理这些对象,因为它们仍包含所有属性。这是最后一个示例:即使 Out-GridView 仅显示您选择的属性,对象仍包含所有属性,包括隐藏在网格视图窗口中的属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# create object that tells PowerShell which column(s) should be visible:
# show "Name", "Description" and "MainWindowTitle"
[string[]]$visible = 'Name', 'Description', 'MainWindowTitle'
$type = 'DefaultDisplayPropertySet'
[System.Management.Automation.PSMemberInfo[]]$info =
[System.Management.Automation.PSPropertySet]::new($type,$visible)


Get-Process |
Where-Object MainWindowTitle |
Sort-Object -Property Name |
# clone the objects so they now belong to you:
Select-Object -Property * |
# add the secret object to each object that you pipe into Out-GridView:
Add-Member -MemberType MemberSet -Name PSStandardMembers -Value $info -PassThru |
Out-GridView -Title 'Select a process' -OutputMode Single |
# still all properties available:
Select-Object -Property *

PowerShell 技能连载 - 修复 PowerShellGet 和 Publish-Module

Publish-Module 是一个 cmdlet,用于将模块发布(上传)到 NuGet 仓库。有时,此 cmdlet 会引发奇怪的异常。这种情况下的原因是 nuget.exe 的过时版本。该应用程序负责打包一个模块并保存为.nupkg 文件,并且在您第一次使用 Publish-Module 时会自动下载该应用程序。

要更正此问题并刷新您的 nuget.exe 版本,请运行以下命令:

1
Invoke-WebRequest -Uri https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile "$env:LOCALAPPDATA\Microsoft\Windows\PowerShell\PowerShellGet\NuGet.exe"

确保在此之后关闭并重新启动所有 PowerShell 会话。如果 Publish-Module 仍然拒绝工作,您可能需要运行以下命令(需要管理员权限):

1
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force

PowerShell 技能连载 - 检测挂起的重启

下面的代码检测是否有挂起的重启:

1
2
$rebootRequired = Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending"
"Pending reboot: $rebootRequired"

PowerShell 技能连载 - 禁用摄像头

寻求保护隐私吗?这是一个简短的脚本,用于在您的系统上查找已启用的摄像头,并让您禁用任何不想使用的摄像头:

1
2
3
4
  # find working cameras
$result = Get-PnpDevice -FriendlyName *Camera* -Status OK -ErrorAction Ignore |
Out-GridView -Title 'Select Camera Device To Disable' -OutputMode Single |
Disable-PnpDevice -Confirm:$false -Passthru -whatif # remove -WhatIf to actually disable devices)

PowerShell 技能连载 - 使用 SOAP Webservice

尽管 SOAP 尚未广泛用于公共的 Webservice(通常使用更简单的 REST 服务),但在内部,许多公司确实将 SOAP 用于他们的 Webservice。

PowerShell 具有出色的 SOAP 支持,因此您无需大量复杂的代码即可连接和使用 SOAP Webservice。这是少数剩余的免费公共 SOAP Webservice 之一(将德语“bankleitzahl”翻译成银行详细信息):

1
2
$o = New-WebServiceProxy -Uri http://www.thomas-bayer.com/axis2/services/BLZService?wsdl
$o.getBank('25050180')

如您所见,要开始使用 SOAP Webservice,您需要 Webservice 提供的 WSDL URL。此网页以 XML 格式返回整个接口定义,New-WebServiceProxy 根据此信息创建包装 SOAP 数据类型所需的所有代码。

一旦您可以访问(任何)SOAP Webservice,您就可以使用以下代码来检查其方法:

1
2
3
4
5
6
7
8
9
10
11
$o = New-WebServiceProxy -Uri http://www.thomas-bayer.com/axis2/services/BLZService?wsdl

# common methods
$blacklist = 'CreateObjRef', 'Dispose', 'Equals', 'GetHashCode', 'GetLifetimeService', 'InitializeLifetimeService', 'ToString', 'GetType'

# exclude async and common methods
$o | Get-Member -MemberType *method |
Where-Object Name -notlike '*Async*' |
Where-Object Name -notlike 'Begin*' |
Where-Object Name -notlike 'End*' |
Where-Object { $_.Name -notin $blacklist }

PowerShell 技能连载 - 通过 PowerShell 调用 COVID 服务

您想及时了解 Covid 疫情数据吗?试试这个简单的 webservice:

1
2
3
$result = Invoke-RestMethod -Uri "https://coronavirus-19-api.herokuapp.com/countries"

$result -match "Germany"

结果类似于:

country             : Germany
cases               : 4480066
todayCases          : 0
deaths              : 95794
todayDeaths         : 0
recovered           : 4215200
active              : 169072
critical            : 1336
casesPerOneMillion  : 53248
deathsPerOneMillion : 1139
totalTests          : 73348901
testsPerOneMillion  : 871788

PowerShell 技能连载 - 启用 Active Directory cmdlet

在服务器和客户端上,Windows 都附带了 “ActiveDirectory” PowerShell 模块。它添加了许多 cmdlet 来管理 Active Directory 中的用户和资源。

默认情况下,该模块是隐藏的。要在客户端上启用它,请以管理员权限运行:

1
2
$element = Get-WindowsCapability -Online -Name "Rsat.ActiveDirectory.DS*"
Add-WindowsCapability -Name $element.Name -Online

在服务器上,再次使用管理员权限并运行:

1
2
Install-WindowsFeature RSAT-AD-PowerShell
Add-WindowsFeature RSAT-AD-PowerShell

PowerShell 技能连载 - 四个 PowerShell 关键先决条件

如果您要切换到新计算机,您可能需要快速检查一下 PowerShell 是否设置正确。以下是您绝对应该检查的四件事:

1 检查 PowerShell 版本

运行 $PSVersionTable 以检查您的 PowerShell 版本。

1
2
3
4
5
6
7
8
9
10
11
12
PS> $PSVersionTable

Name Value
---- -----
PSVersion 5.1.19041.1237
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.19041.1237
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1

由于 $PSVersionTable 是一个哈希表,您还可以将其转换为对象以选择某些属性:

1
2
3
4
5
PS> [PSCustomObject]$PSVersionTable | Select-Object -Property PSVersion, PSEdition

PSVersion PSEdition
--------- ---------
5.1.19041.1237 Desktop

如果 “PSEdition“ 是 “Desktop“,则您使用的是内置的 Windows PowerShell。应该是 5.1 版。任何旧版本均已弃用,使用旧版本可能会引发安全风险。由于 Windows PowerShell 功能齐全,因此没有超过 5.1 的新版本。

如果 “PSEdition“ 是 “Core“,那么您使用的是新的跨平台 PowerShell。当前版本为 7.1.5,更新频繁。

2 检查运行策略

如果你不能运行脚本,PowerShell 就没有意义了。执行策略应设置为 “RemoteSigned“(仅允许本地脚本)或 “Bypass“(位于任何地方的脚本都可以运行,包括下载的脚本):

1
2
PS> Get-ExecutionPolicy
Bypass

如果需要,使用以下代码来更改执行策略:

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

3 检查 PowerShellGet

PowerShellGet 是一个重要的附加组件,因为它代表了 PowerShell 包管理。使用 PowerShellGet,您可以通过 Install-Module 安装其他模块。如果此模块已过时,您可能无法再下载和安装其他模块:

1
2
3
4
5
PS> Get-Module -Name PowerShellGet -ListAvailable | Sort-Object -Property Version -Descending | Select-Object -First 1 -Property Version

Version
-------
2.2.5

如果报告的版本低于 2.2.0,则需要更新此模块。如果您看到版本 1.0.0 或 1.0.1(最初随 Windows 一起提供并且此后从未更新过的初始模块),则尤其如此。

要更新该模块,您需要重新安装它及其必备的 PackageManagement 模块:

1
2
Install-Module -Name PowerShellGet -Scope CurrentUser -Force -AllowClobber
Install-Module -Name Packagemanagement -Scope CurrentUser -Force -AllowClobber

TLS 1.2 支持

最后要检查的是 Windows 是否设置为支持传输层协议 1.2:

1
2
PS> ([System.Net.ServicePointManager]::SecurityProtocol -band 'Tls12') -eq 'Tls12'
True

If this is $false, then your Windows still uses outdated settings, and PowerShell may not be able to connect to HTTPS: webservices and sites. You should update Windows. Meanwhile, you can manually enable TLS 1.2 on a per-application setting:
如果返回 $false,那么您的 Windows 仍然使用过时的设置,并且 PowerShell 可能无法连接到 HTTPS:网络服务和网站。您应该更新 Windows。同时,您可以在每个应用程序独立的设置上手动启用 TLS 1.2:

1
2
3
[System.Net.ServicePointManager]::SecurityProtocol =
[System.Net.ServicePointManager]::SecurityProtocol -bor
[System.Net.SecurityProtocolType]::Tls12

PowerShell 技能连载 - 改进 PowerShell ISE 的帮助

仍有许多专业的脚本编写者使用内置 PowerShell ISE 编辑器,它仍然是一个快速可靠的脚本开发环境。如果您使用 PowerShell ISE,可能希望将它内置的帮助系统切换为在线帮助。请运行这段代码(在 PowerShell ISE 中):

1
PS> $psise.Options.UseLocalHelp = $false

运行此代码后,只要您在脚本窗格或控制台部分中单击命令,然后按 F1,PowerShell ISE 将对命令运行 Get-Help 并添加 -Online 开关参数,因此浏览器打开并显示复杂的、排版好的最新在线帮助。

尽管如此,您可能希望记住上面的命令:如果命令没有在线帮助,则可能仍有本地帮助文件。将 PowerShell ISE 选项恢复为 $true 将打开本地帮助。

PowerShell 技能连载 - 打开 Windows 设置对话框(快速)(第 2 部分)

上一个技能中,我们介绍了 Start-Process 支持的命令 “ms-settings:“,可用于打开各种 Windows 设置对话框。例如,要打开个人注册信息页面,请执行以下操作:

1
PS> Start-Process ms-settings:yourinfo

每当您需要经常打开特定对话框时,例如检查更新,那么现在可以直接做到:

1
PS> Start-Process ms-settings:windowsupdate-action

但是,您需要记住相当隐蔽的命令。您无法定义新的命令别名,因为这些代码不是命令,而是命令加参数。

但是,您可以为此做些什么,也就是创建简单的函数。当您需要方便地记忆命令参数时,这一直是一种好方法:

1
function update { Start-Process ms-settings:windowsupdate-action }

运行此代码后,您现在可以使用新的 “update“ 命令快速检查 Windows 更新。如果要保留这些功能,请将它们导出为一个 module,或将功能代码放入其中一个配置文件(自动启动)脚本中。 可以在 $profile 中找到默认配置文件脚本的路径。如果尚不存在,您可能必须创建文件。如果还没有允许脚本执行,请先启用它。