PowerShell 技能连载 - 摆脱 Get-EventLog

Get-EventLog 命令可以轻松访问主要的 Windows 事件日志中的事件日志条目,但是它既不能访问许多应用程序级事件日志,也不能在PowerShell 7中使用。

如果计划在 PowerShell 7 中运行代码,则应该开始习惯其后继程序:Get-WinEvent。此cmdlet功能强大,并支持许多参数。这是一个类似于 Get-EventLog 的示例:

1
2
3
Get-WinEvent -FilterHashtable @{Logname = 'System';Level=2,3} -MaxEvents 10 |
Select-Object TimeCreated, LevelDisplayName, Id, ProviderName, Message |
Format-Table

您的查询以哈希表的形式提交,您可以看到如何指定日志名称和想要获取的事件数量。与 Get-EventLog 相比,您现在可以指定和检索任何日志,而不仅仅是少数经典日志。您可能需要运行 Show-EventLog 来打开事件日志查看器,并发现许多可用的应用程序级别的日志。

哈希表 “Level” 键定义您要查看的事件日志条目的类型。数字越低,条目越严重。“2” 代表错误,“3”代表警告。如您所见,您可以将级别组合为逗号分隔的列表。

结果看起来像这样:

TimeCreated         LevelDisplayName    Id ProviderName                     Message
-----------         ----------------    -- ------------                     -------
04.08.2020 13:03:42 Warning          10016 Microsoft-Windows-DistributedCOM The Anwendungsspezifisch permission settings do...
04.08.2020 13:03:20 Error                1 MTConfig                         An attempt to configure the input mode of a mul...
04.08.2020 13:03:19 Error                1 MTConfig                         An attempt to configure the input mode of a mul...
04.08.2020 12:58:18 Error                1 MTConfig                         An attempt to configure the input mode of a mul...
04.08.2020 11:53:38 Error            10010 Microsoft-Windows-DistributedCOM The server Microsoft.SkypeApp_15.61.100.0_x86__...
04.08.2020 11:23:48 Error            10010 Microsoft-Windows-DistributedCOM The server microsoft.windowscommunicationsapps_...
04.08.2020 11:23:41 Error            10010 Microsoft-Windows-DistributedCOM The server Microsoft.SkypeApp_15.61.100.0_x86__...
04.08.2020 11:23:37 Warning            701 Win32k                           Power Manager has not requested suppression of ...
04.08.2020 11:23:37 Warning            701 Win32k                           Power Manager has not requested suppression of ...
04.08.2020 11:23:37 Error            10317 Microsoft-Windows-NDIS           Miniport Microsoft Wi-Fi Direct Virtual Adapter...
评论

PowerShell 技能连载 - 设置和清除信任的主机

PowerShell 远程处理在客户端(发出命令并在服务器上进行身份验证的计算机)上维护受信任的 IP 地址和/或计算机名称的列表。此列表对您很重要,因为它控制着您如何对远程计算机进行身份验证。

默认情况下,PowerShell 仅支持 Kerberos 身份验证,因为它最安全,并且可以同时对客户端和服务器进行身份验证。但是,它需要一个 Active Directory,并且不能与 IP 地址一起使用。

1
2
# execute PowerShell code remotely
Invoke-Command { Get-Service } -ComputerName storage2 -Credential AdminUser

在此示例中,AdminUser 必须是在 storage2 上具有适当权限才能访问的域帐户。

通过将 IP 地址和/或计算机名称添加到 TrustedHosts,您也可以使用 NTLM身份验证。这样,您可以使用本地帐户进行身份验证,并使用远程帐户访问独立系统,域外的系统以及通过IP地址指定的系统。

也允许使用通配符,因此当将 TrustedHosts 设置为 “*” 时,任何计算机都可以使用 NTLM 身份验证。但是,这并不太明智,因为现在黑客可以断开服务器并用另一台机器代替它来捕获密码,因为您不会注意到它不再是您要访问的机器。因此,仅对于您知道的位于“信任”的安全环境中的计算机,对 TrustedHosts 进行更改。

仅管理员和 WinRM 服务运行时才能访问 TrustedHosts 列表。启动提升的 PowerShell 环境,并确保 WinRM 服务正在运行:

1
PS> Start-Service -Name WinRM

要查看 TrustedHosts 的当前内容,请运行以下命令:

1
2
3
4
5
6
7
8
PS> Get-ChildItem -Path WSMan:\localhost\Client\TrustedHosts


WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Client

Type Name SourceOfValue Value
---- ---- ------------- -----
System.String TrustedHosts

默认情况下,列表为空。要重置其内容(即指定IP范围),请使用 Set-Item

1
PS> Set-Item -Path WSMan:\localhost\Client\TrustedHosts -Value 192.168.* -Force

要添加更多条目,请添加 -Concatenate 参数。这将添加一个不同的计算机名称:

1
PS> Set-Item -Path WSMan:\localhost\Client\TrustedHosts -Value storage2 -Concatenate -Force

现在尝试转储更改的内容。结果是一个逗号分隔的列表,支持通配符:

1
2
3
4
5
6
7
8
PS> Get-ChildItem -Path WSMan:\localhost\Client\TrustedHosts


WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Client

Type Name SourceOfValue Value
---- ---- ------------- -----
System.String TrustedHosts 192.168.*,storage2

要将 TrustedHosts 还原为默认值并将其清空,请使用 Clear-Item 命令:

1
PS> Clear-Item -Path WSMan:\localhost\Client\TrustedHosts -Force
评论

PowerShell 技能连载 - 在 PowerShell ISE 中使用 PowerShell 7

Windows 内置的 PowerShell ISE 仅能与 Windows PowerShell 一起使用,并且停留在 PowerShell 5.1 版。通常,当您想使用编辑器编写 PowerShell 7 代码时,可以使用 Visual Studio Code 和 PowerShell 扩展。

尽管如此,您仍可以使 PowerShell ISE 兼容 PowerShell 7。然后,它为 PowerShell 7 提供了丰富的 IntelliSense,并包含 PowerShell 7 中引入的所有语言功能。

为此,您可以从 PowerShell ISE 中启动本地远程会话,并指定配置名称 “powershell.7”。

1
PS> Enter-PSSession -ComputerName localhost -ConfigurationName powershell.7

当然,这需要满足一些先决条件:

  • 您需要先安装 PowerShell 7,然后才能使用它。 Windows 7 并不附带 PowerShell 7。
  • 您需要在 PowerShell 7中启用远程处理。您可以在安装期间通过选中安装对话框中的相应框来执行此操作。或者,您从提升权限的 PowerShell 7 控制台运行此命令:Enable-PSRemoting -SkipNetworkProfileCheck -Force
  • 您可能需要在提升权限的 Windows PowerShell 中再次运行此行命令:Enable-PSRemoting -SkipNetworkProfileCheck -Force

现在您已经准备就绪,并使用上述参数运行 Enter-PSSession 时,您将远程连接到 PowerShell 7。

如果您当前的用户不是管理员,或者您使用电子邮件地址和 Microsoft 帐户登录,则需要创建一个具有管理员权限的本地用户帐户,并将其明确用于身份验证:

1
PS> Enter-PSSession -ComputerName localhost -ConfigurationName powershell.7 -Credential localAdminUser
评论

PowerShell 技能连载 - 使用 $Is* 变量

在PowerShell 7 中,有一组新的变量都以 “Is” 开头。它们可帮助您了解脚本运行的环境:

1
2
3
4
5
6
7
PS> Get-Variable -Name is*
Name Value
---- -----
IsCoreCLR True
IsLinux False
IsMacOS False
IsWindows True

在 Windows 附带的 Windows PowerShell 中,这些变量尚不存在。这是可以理解的,因为 Windows PowerShell 是 Windows 的一部分,而且无论如何都不能跨平台兼容。

要在Windows(或任何其他受支持的平台)上运行PowerShell 7,请访问发布页面[https://github.com/PowerShell/PowerShell/releases](https://github.com/PowerShell/PowerShell/releases) ,向下滚动到 “Assets” 标题,然后下载最适合您的安装软件包。

在 Windows PowerShell中,只需运行以下代码即可:

1
iex "& { $(irm https://aka.ms/install-powershell.ps1) } -UseMSI"

要启动 PowerShell 7,请运行 pwsh.exe

评论

PowerShell 技能连载 - 启用或禁用实时防病毒保护

如果您以完全管理员权限运行,则可以使用 PowerShell 启用和禁用实时防病毒保护。当明确需要运行可能会被阻止的合法脚本时,暂时禁用实时防病毒保护有时可能会有所帮助。通常,实时保护很有价值,只有在有充分理由的情况下才应将其禁用。

要禁用实时保护,请运行以下命令:

1
Set-MpPreference -DisableRealtimeMonitoring $true

要启用它,请将 $true 替换为 $false

评论

PowerShell 技能连载 - 检测防病毒引擎状态

在上一个技能中,我们学习了如何查询 WMI 来查找 Windows 计算机上存在的防病毒产品:

1
2
3
$info = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct

$info

ProductState 属性对其他信息进行编码,告诉您防病毒引擎是否可运行并使用最新的签名。不过该信息是一个数字,并且是一个位标记:

1
2
3
4
PS> $info = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct

PS> $info.productState
397568

要解密数字中各个位的含义,可以使用 PowerShell 对枚举类型新支持。定义好位及其含义,并用 [Flags()] 属性修饰枚举(表明可以设置多个位):

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
# define bit flags

[Flags()] enum ProductState
{
Off = 0x0000
On = 0x1000
Snoozed = 0x2000
Expired = 0x3000
}

[Flags()] enum SignatureStatus
{
UpToDate = 0x00
OutOfDate = 0x10
}

[Flags()] enum ProductOwner
{
NonMs = 0x000
Windows = 0x100
}

# define bit masks

[Flags()] enum ProductFlags
{
SignatureStatus = 0x00F0
ProductOwner = 0x0F00
ProductState = 0xF000
}

# get bits
$info = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct
[UInt32]$state = $info.productState

# decode bit flags by masking the relevant bits, then converting
[PSCustomObject]@{
ProductState = [ProductState]($state -band [ProductFlags]::ProductState)
SignatureStatus = [SignatureStatus]($state -band [ProductFlags]::SignatureStatus)
Owner = [ProductOwner]($state -band [ProductFlags]::ProductOwner)
}

要检查位组的状态,请屏蔽与您要执行的操作相关的位,然后将这些位转换为枚举。结果是当前设置的位的明文名称。结果看起来像这样:

ProductState SignatureStatus   Owner
------------ ---------------   -----
          On        UpToDate Windows

如果您使用的是 Windows 10 上内置的防病毒引擎 “Defender”,则无需使用上面的通用防病毒界面。而是使用内置的 Get-MpPreference cmdlet,它提供了更多详细信息。

评论

PowerShell 技能连载 - 检测已安装的防病毒产品

这行 PowerShell 代码可以帮助您识别 Windows 系统中安装的防病毒产品:

1
PS> Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct

添加 -ComputerName 参数以查询远程系统。

请注意,此行仅返回正确注册的防病毒产品。结果看起来类似这样,并为您提供了防病毒产品和安装位置:

1
2
3
4
5
6
7
displayName              : Windows Defender
instanceGuid : {D68DDC3A-831F-4fae-9E44-DA132C1ACF46}
pathToSignedProductExe : windowsdefender://
pathToSignedReportingExe : %ProgramFiles%\Windows Defender\MsMpeng.exe
productState : 397568
timestamp : Wed, 29 Jul 2020 18:37:24 GMT
PSComputerName
评论

PowerShell 技能连载 - 删除 Microsoft Teams 缓存数据

如果您使用 Microsoft Teams 进行视频会议,则有时可能需要清理缓存文件并删除驻留在许多子文件夹中的残留数据。

您可以调整上一个示例中的代码来进行清理:

1
2
3
4
5
6
7
8
9
# the folder that contains the Microsoft Teams data
$parentFolder = "$env:userprofile\AppData\Roaming\Microsoft\Teams\*"
# list of subfolders that cache data
$list = 'application cache','blob storage','databases','GPUcache','IndexedDB','Local Storage','tmp'

# delete the folders found in the list
Get-ChildItem $parentFolder -Directory |
Where-Object name -in $list |
Remove-Item -Recurse -Verbose

If you have Administrator privileges and would like to remove cached Microsoft Teams data for all users, change $parentFolder like this:
如果您具有管理员权限,并想为所有用户删除缓存的 Microsoft Teams 数据,请按如下所示更改 $parentFolder

1
$parentFolder = "c:\users\*\AppData\Roaming\Microsoft\Teams\*"
评论

PowerShell 技能连载 - 删除多个子文件夹

有时,可能有必要删除给定文件夹中的一组子文件夹。这是一段简单的代码,可从文件夹名称列表中删除文件夹。

警告:此代码将删除 $list 中列出的子文件夹,而无需进一步确认。如果子文件夹没有退出,则什么也不会发生。

1
2
3
4
5
6
7
8
9
10
11
# the folder that contains the subfolders to remove
# (adjust to your needs)
$parentFolder = $env:userprofile

# list of folder names to remove (adjust to your needs)
$list = 'scratch', 'temp', 'cache'

# delete the folders found in the list
Get-ChildItem $parentFolder -Directory |
Where-Object name -in $list |
Remove-Item -Recurse -Force -Verbose

如果要删除父文件夹内任何位置的子文件夹,请通过向 Get-ChildItem 添加 -Recurse 来扩展搜索以通过子文件夹进行递归。

下面的示例在父文件夹的文件夹结构内的任何位置删除 $list 中的子文件夹。

请注意,这样做可能有风险,因为您现在正在查找可能并不是由您所有并控制的文件夹内的子文件夹,这就是为什么我们向 -Remove-Item 添加 -WhatIf 的原因:该代码实际上不会删除子文件夹,而只是报告其内容完成了。如果您知道自己在做什么,请删除该参数:

1
2
3
4
5
6
7
8
9
# the folder that contains the subfolders to remove
$parentFolder = $env:userprofile
# list of folder names to remove
$list = 'scratch', 'temp', 'cache'

# delete the folders found in the list
Get-ChildItem $parentFolder -Directory -Recurse |
Where-Object name -in $list |
Remove-Item -Recurse -Verbose -WhatIf
评论

PowerShell 技能连载 - 管理自启动项

要在 Windows 上管理自动启动程序,不必费心编写大量脚本。 PowerShell 可以直接打开任务管理器中包含的自动启动管理器,您只需执行以下操作即可:

1
PS C:\> Taskmgr /7 /startup

这将打开一个窗口,并列出所有自动启动程序及其对启动时间的影响。要阻止这些程序中的任何一个自动启动,请单击列表中的一个程序,然后单击右下角的“禁用”按钮。

如果您愿意,可以将命令转换为函数,然后将其放入配置文件脚本中,以备不时之需:

1
2
3
4
function Show-Autostart
{
Taskmgr /7 /startup
}
评论