PowerShell 技能连载 - 启用或禁用实时防病毒保护
如果您以完全管理员权限运行,则可以使用 PowerShell 启用和禁用实时防病毒保护。当明确需要运行可能会被阻止的合法脚本时,暂时禁用实时防病毒保护有时可能会有所帮助。通常,实时保护很有价值,只有在有充分理由的情况下才应将其禁用。
要禁用实时保护,请运行以下命令:
1 | Set-MpPreference -DisableRealtimeMonitoring $true |
要启用它,请将 $true
替换为 $false
。
如果您以完全管理员权限运行,则可以使用 PowerShell 启用和禁用实时防病毒保护。当明确需要运行可能会被阻止的合法脚本时,暂时禁用实时防病毒保护有时可能会有所帮助。通常,实时保护很有价值,只有在有充分理由的情况下才应将其禁用。
要禁用实时保护,请运行以下命令:
1 | Set-MpPreference -DisableRealtimeMonitoring $true |
要启用它,请将 $true
替换为 $false
。
在上一个技能中,我们学习了如何查询 WMI 来查找 Windows 计算机上存在的防病毒产品:
1 | $info = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct |
ProductState
属性对其他信息进行编码,告诉您防病毒引擎是否可运行并使用最新的签名。不过该信息是一个数字,并且是一个位标记:
1 | PS> $info = Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct |
要解密数字中各个位的含义,可以使用 PowerShell 对枚举类型新支持。定义好位及其含义,并用 [Flags()]
属性修饰枚举(表明可以设置多个位):
1 | # define bit flags |
要检查位组的状态,请屏蔽与您要执行的操作相关的位,然后将这些位转换为枚举。结果是当前设置的位的明文名称。结果看起来像这样:
ProductState SignatureStatus Owner
------------ --------------- -----
On UpToDate Windows
如果您使用的是 Windows 10 上内置的防病毒引擎 “Defender”,则无需使用上面的通用防病毒界面。而是使用内置的 Get-MpPreference
cmdlet,它提供了更多详细信息。
这行 PowerShell 代码可以帮助您识别 Windows 系统中安装的防病毒产品:
1 | PS> Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct |
添加 -ComputerName
参数以查询远程系统。
请注意,此行仅返回正确注册的防病毒产品。结果看起来类似这样,并为您提供了防病毒产品和安装位置:
1 | displayName : Windows Defender |
如果您使用 Microsoft Teams 进行视频会议,则有时可能需要清理缓存文件并删除驻留在许多子文件夹中的残留数据。
您可以调整上一个示例中的代码来进行清理:
1 | # the folder that contains the Microsoft Teams data |
如果您具有管理员权限,并想为所有用户删除缓存的 Microsoft Teams 数据,请按如下所示更改 $parentFolder
:
1 | $parentFolder = "c:\users\*\AppData\Roaming\Microsoft\Teams\*" |
有时,可能有必要删除给定文件夹中的一组子文件夹。这是一段简单的代码,可从文件夹名称列表中删除文件夹。
警告:此代码将删除 $list
中列出的子文件夹,而无需进一步确认。如果子文件夹没有退出,则什么也不会发生。
1 | # the folder that contains the subfolders to remove |
如果要删除父文件夹内任何位置的子文件夹,请通过向 Get-ChildItem
添加 -Recurse
来扩展搜索以通过子文件夹进行递归。
下面的示例在父文件夹的文件夹结构内的任何位置删除 $list
中的子文件夹。
请注意,这样做可能有风险,因为您现在正在查找可能并不是由您所有并控制的文件夹内的子文件夹,这就是为什么我们向 -Remove-Item
添加 -WhatIf
的原因:该代码实际上不会删除子文件夹,而只是报告其内容完成了。如果您知道自己在做什么,请删除该参数:
1 | # the folder that contains the subfolders to remove |
要在 Windows 上管理自动启动程序,不必费心编写大量脚本。 PowerShell 可以直接打开任务管理器中包含的自动启动管理器,您只需执行以下操作即可:
1 | PS C:\> Taskmgr /7 /startup |
这将打开一个窗口,并列出所有自动启动程序及其对启动时间的影响。要阻止这些程序中的任何一个自动启动,请单击列表中的一个程序,然后单击右下角的“禁用”按钮。
如果您愿意,可以将命令转换为函数,然后将其放入配置文件脚本中,以备不时之需:
1 | function Show-Autostart |
PowerShell Gallery 不仅提供带有新 PowerShell 命令的公共模块,而且还提供公共脚本。在投入时间之前,您可能希望调查是否有人创建了可以执行所需功能的 PowerShell 代码。
这是一个简单的示例,说明了如何通过 PowerShell Gallery 搜索和下载脚本的工作方式:
1 | # create temporary folder |
当您运行此代码时,Find-Script
将查找使用 Get 动词的任何脚本。您当然可以更改此设置并搜索您喜欢的任何内容。接下来,所有与您的搜索匹配的脚本都将显示在网格视图窗口中。现在,您可以选择一个或多个听起来很有趣的东西。
然后,PowerShell 将所选脚本下载到一个临时文件夹,然后在 PowerShell ISE 中打开这些脚本。现在,您可以查看源代码并从中选择有用的内容。
注意:由于 Out-GridView
中的 bug,您需要等待所有数据到达后才能选择脚本。如果选择脚本并在 Out-GridView
仍在接收数据的同时单击“确定”,则不会传递任何数据,也不会下载脚本。
要解决此问题,请等待足够长的时间以完全填充网格视图窗口,或者通过首先收集所有数据然后仅在网格视图窗口中显示数据来关闭实时模式:
1 | # create temporary folder |
PowerShell 远程操作功能极其强大:借助 Invoke-Command
,您可以将任意 PowerShell 代码发送到一台或多台远程计算机,并在其中并行执行。
在 Windows 服务器上,通常会启用 PowerShell 远程处理,因此您所需要的只是管理员权限。这是一个简单的示例:
1 | PS> Invoke-Command -ScriptBlock { "I am running on $env:computername!" } -ComputerName server1 -Credential domain\adminuser |
本技巧不是关于设置 PowerShell 远程操作的,因此我们假定上述调用确实对您有效。相反,我们将重点放在 PowerShell 远程操作的最重要瓶颈之一上,以及如何解决它。
这是一个访问远程系统并从 Windows 文件夹中转储 DLL 的代码。使用一个 stopwatch 测量所需时间:
1 | # change this to the computer you want to access |
令人惊讶的是,此代码运行了很长时间。当我们在自己的本地计算机上尝试它时,花费了 95 秒。从 Invoke-Command
返回信息的速度可能非常慢,因为对象需要序列化为 XML 以跨越进程边界,并在它们返回调用者时重新反序列化。
为了加快远程处理速度,请记住这一点,并仅返回尽可能少的信息。通常,信息量很容易减少。
例如,如果您确实需要 Windows 文件夹中所有 DLL 文件的列表,则很可能只需要一些属性,例如 path 和 size。通过添加一个 Select-Object
并指定您真正需要的属性,之前花费了 95 秒的相同代码现在可以在不到一秒钟的时间内运行:
1 | # change this to the computer you want to access |
New-Item
可以在任何PowerShell驱动器上创建新对象,包括功能:具有所有 PowerShell 功能的驱动器。
如果需要,您可以在代码内部动态定义新功能。这些新功能将仅存在于定义它们的作用域内。要使它们成为脚本全局脚本,请添加脚本:作用域标识符。这是一个例子:
1 | function New-DynamicFunction |
要测试效果,请运行 New-DynamicFunction
。完成后,会有一个称为 Test-NewFunction
的新函数:
1 | # this function does not (yet) exist: |
请注意,我们如何将新功能的代码定义为大括号中的脚本块。这不是必需的。您还可以将其定义为纯文本字符串,这可以为您提供更多灵活性来编写新函数的源代码:
1 | $a = "not" |
还要注意,除非指定 -Force
,否则 New-Item
不会覆盖现有函数。
在前面的部分中,我们创建了 Test-Password
函数,该函数可以测试本地和远程用户的密码。
在最后一部分,我们将错误处理添加到 Test-Password
函数中,以便当用户输入不存在或不可用的域时它可以正常响应:
1 | function Test-Password |
运行此代码后,将有一个新命令 “Test-Password
“。运行它时,系统会提示您输入域(或用于测试本地帐户的本地计算机名称),用户名和掩码密码。
下面是在 PowerShell 7 中运行的示例:第一次调用(测试本地帐户)成功,并产生 $true
。第二个调用(指定一个不可用的域)失败,并显示一条自定义错误消息:
1 | PS C:\> Test-Password |