PowerShell 技能连载 - 管理文件共享
在您的网络上创建新的文件共享需要管理员权限以及以下 PowerShell 代码:
1 | $Parameters = @{ |
或使用经典参数:
1 | PS> New-SmbShare -Name Packages -Path c:\repo1 -FullAccess 'domain\username' |
只需确保以管理员权限运行此程序,并确保本地文件夹(在 -Path
中指定)确实存在。
在您的网络上创建新的文件共享需要管理员权限以及以下 PowerShell 代码:
1 | $Parameters = @{ |
或使用经典参数:
1 | PS> New-SmbShare -Name Packages -Path c:\repo1 -FullAccess 'domain\username' |
只需确保以管理员权限运行此程序,并确保本地文件夹(在 -Path
中指定)确实存在。
为了安全地输入信息,脚本需要显示一个掩码输入。最简单的方法是使用 Read-Host -AsSecureString
命令:
1 | # Read-Host |
或者,你可以使用一个带有 [SecureString]
类型参数的函数,并将该参数设置为强制性:
1 | # mandatory parameter |
这样,您可以免费获得一个屏蔽的输入(在控制台窗口显示为“星号”,在ISE中显示为单独的输入框),但最终得到的是安全字符串,而不是明文。以下是一个简单的函数,可用于将安全字符串转换回纯文本:
1 | filter Convert-SecureStringToString |
现在您可以使用屏蔽输入来询问敏感用户信息,并在内部将其作为纯文本使用:
1 | # Read-Host |
Windows 控制面板是系统配置的图形用户界面中心。你也可以通过控制台命令来启动控制面板:输入 control [ENTER]
。然而,即使 PowerShell 也支持控制面板:
Get-ControlPanelItem
列出所有可用的控制面板项目,你可以通过名称或描述来搜索控制面板项目。以下命令可以找到与 “print” 相关的控制面板项目:
1 | PS> Get-ControlPanelItem -Name *print* |
Show-ControlPanelItem
可以用来打开一个或多个控制面板项目。请注意,这些 cmdlet 不能自动化设置更改,但它们可以帮助快速识别和打开基于 GUI 的控制面板项目。与其花费多次点击来打开控制面板并找到适当的控制面板项目进行管理(比如本地打印机),您也可以使用 PowerShell 控制台并输入以下命令:
1 | PS> Show-ControlPanelItem -Name *print* |
注意:*-ControlPanelItem
cmdlets 仅在 Windows PowerShell 中可用。
出于多种原因,你不应继续使用 Get-EventLog
,我们之前已经解释了一些原因。在 PowerShell 7 中,Get-EventLog`` 已经被弃用。相反,应该使用
Get-WinEvent。它可以做到
Get-EventLog`` 能做的所有事情,而且更多。
不过,Get-WinEvent
使用起来可能有些麻烦,因为它需要使用类似哈希表或 XML 的结构来定义你所需的事件。因此,在下面,我们为你提供了一个相当冗长的代理函数,用于为 Get-WinEvent
添加向后兼容性。运行下面的代理函数后,你可以使用 Get-WinEvent
并传入与之前使用 Get-EventLog
时相同的参数。而且,你还会获得全新的 IntelliSense 功能,提示所有包含可能有趣信息的日志名称。
1 | function Get-WinEvent |
我们来做一个测试并尝试从系统日志文件中获取最新的 20 个错误。正如你很快看到的,Get-WinEvent
现在接受与 Get-EventLog
相同的参数。在查看结果时,你会迅速发现 Get-EventLog
没有正确返回事件日志消息,而 Get-WinEvent
则做到了。
1 | PS> Get-EventLog -LogName System -EntryType Error -Newest 3 |
请在参数中添加 -Verbose
选项,以获取关于过滤哈希表值或XML查询的详细信息:
1 | PS> Get-WinEvent -LogName System -EntryType Error -Newest 3 -Verbose |
Get-EventLog
是 Windows PowerShell 中非常受欢迎的 cmdlet。通过仅使用几个简单的参数,它可以从主要的 Windows 事件日志中读取事件日志。然而,这个 cmdlet 使用的技术不仅很慢,而且越来越危险。
Get-EventLog
在查找正确的事件消息时存在困难,所以过去经常得不到有意义的消息。然而,越来越频繁地,Get-EventLog
返回完全无关的错误消息,这可能会触发错误警报。就像这个例子:
1 | PS> Get-EventLog -Source Microsoft-Windows-Kernel-General -Newest 2 -LogName System -InstanceId 1 |
CVE 检测是安全问题或入侵的指示器。你可不想成为那个在最后引发混乱的人,结果发现一切只是误报。任何其他工具都会返回相应的事件消息,正如官方替代 Get-EventLog
的工具: Get-WinEvent
也是如此:
1 | PS> Get-WinEvent -FilterHashtable @{ |
实际上,与 CVE 检测和安全问题不同,系统时间被调整了。
以后在脚本中不要再使用 Get-EventLog(除非你百分之百确定所关心的事件不受其缺点影响),而是要熟悉 Get-WinEvent
:它更快、更多功能,并且还可以读取导出的事件文件。
想过自动将日期转换成星座吗?这里有一个非常简单的脚本,可以帮你实现这个功能,支持英文和德文:
1 | param ( |
这里有一种简单通用的方法,可以将 `DateTime`` 信息转换为你所需的 ISO 字符串数据组件。例如,如果你只需要日期和月份,而不关心年份,可以按照以下方式操作:
1 | PS> (Get-Date).ToString('"0000-"MM-dd') |
(Get-Date)
表示当前日期,但可以替换为任何 `DateTime`` 对象:
1 | PS> $anyDate = Get-Date -Date '2024-12-24 19:22:11' |
假设你需要过去 48 小时内的所有错误和警告,但是从上午 8 点 45 分开始计算。以下是计算方法:
1 | PS> (Get-Date).AddHours(-48).ToString('yyyy-MM-dd "08:45:00"') |
基本上,您可以使用 ToString()
方法,并使用区分大小写的 .NET DateTime 占位符(例如,’yyyy’ 表示以 4位数字显示的年份)来组合所需的日期和时间字符串表示形式,再加上您自己控制的固定文本。请确保将固定文本放在额外引号中。
当你在 Windows 中右键单击任何 PowerShell 脚本时,上下文菜单会出现“使用 PowerShell 运行”的选项。然而,当你选择这个选项时,可能会看到一个 PowerShell 控制台弹出,询问关于“执行策略”的奇怪问题。让我们明确一点:这与你个人的执行策略设置无关,这些通常控制着 PowerShell 脚本是否可以运行。
相反,上下文菜单命令运行它自己的代码。你可以在 Windows 注册表中查找:
1 | $path = 'HKEY_CLASSES_ROOT\SystemFileAssociations\.ps1\Shell\0\Command' |
而这就是每当您调用它时上下文菜单命令运行的内容:
1 | if((Get-ExecutionPolicy ) -ne 'AllSigned') |
所以基本上,除非你使用的是超严格的执行策略 “AllSigned
“(几乎没有人这样做),否则执行策略会在临时情况下(仅限于此次调用)设置为 “Bypass
“,以允许你运行右键单击的脚本文件。实际上,执行策略会稍微放宽一些,使得即使在未定义明确的执行策略的系统上也可以使用上下文菜单命令。
然而,Set-ExecutionPolicy
有向用户询问回复的倾向,在这里可能会导致烦人的提示框出现。用户真的不想每次使用此上下文菜单命令启动某个脚本时都被问到“确定吗?”
要解决这个问题,只需调整所述注册表键中的代码。在调用 Set-ExecutionPolicy
时添加 “-Force
“ 参数,这样该 cmdlet 就能够进行调整而无需提问。
在之前的部分中,我们回顾了不同的文件类型以持久化数据,并了解了用于读写这些文件的 cmdlets。
今天,让我们将这些知识应用到一个真实的数据文件中,你可以自己创建它(前提是你拥有一台带有 Windows 系统的笔记本电脑,并带有电池供电)。
1 | $Path = "$env:temp\battery.xml" |
运行这行代码后,它会生成一个包含所有电池信息的XML文件,包括设计容量和实际容量,这样你就可以查看电池的状态是否良好。从前面的代码示例中选择适当的代码,读取XML文件的内容:
1 | # path to XML file: |
接下来,在您喜爱的编辑器中,通过在$xml中添加“.”来探索XML的对象结构,并查看 IntelliSense 或通过简单地输出变量来查看,这样 PowerShell 会打印下一个级别的属性名称。
通过这种方式,我找到了电池容量信息:
1 | PS> $xml |
现在我们可以将所有部分组合成一个脚本,返回面向对象的电池磨损信息(确保您的系统有电池,否则会出现红色异常):
1 | # temp path to XML file: |
只需非常少的努力,相同的内容可以成为一个有用的新命令。
1 | function Get-BatteryCapacity |
现在轻松检查电池磨损:
1 | PS> Get-BatteryCapacity | Select-Object Id, Manufacturer, FullChargeCapacity, DesignCapacity |
使用哈希表,Select-Object
现在甚至可以计算剩余电池容量的百分比(但这是我们今天不会深入探讨的另一个话题):
1 | PS> Get-BatteryCapacity | Select-Object Id, Manufacturer, FullChargeCapacity, @{N='Remain';E={'{0:P}' -f ($_.FullChargeCapacity/$_.DesignCapacity)}} |
PowerShell 支持多种文本文件格式,那么保存和读取数据的最佳方法是什么呢?
在本系列的前两部分中,我们提供了一个实用的指南,帮助您根据数据的性质选择最佳文件格式(和适当的 cmdlet)。
当您决定使用 XML 作为数据格式时,您会发现内置的 Export/Import-CliXml
cmdlet 是将 您自己的对象 保存到 XML 文件和反向操作的简单方法。但是如果您需要处理来自您自己未创建的源的 XML 数据,该怎么办呢?让我们来看一下名为“Xml”的 cmdlet:ConvertTo-Xml
。它可以将任何对象转换为 XML 格式:
1 | PS> Get-Process -Id $pid | ConvertTo-Xml |
结果是XML,只有在将其存储在变量中时才有意义,这样您可以检查XML对象并输出XML字符串表示:
1 | PS> $xml = Get-Process -Id $pid | ConvertTo-Xml |
虽然没有 Export-Xml
的命令,但你可以轻松地创建自己的 Export-CliXml
,将对象持久化到文件中,而无需使用专有的“CliXml”结构。
1 | # data to be persisted in XML: |
要走相反的路线,将XML转换回对象,没有 ConvertFrom-Xml`` - 因为这个功能已经内置在类型
[Xml]` 中。要将上面的示例文件转换回对象,您可以执行以下操作(假设您使用上面的示例代码创建了result.xml文件):
1 | # path to XML file: |
这段代码可以读取(任何)XML文件并将XML转换为对象。你可以使用这个模板来读取和处理几乎任何XML文件。
话虽如此,要使用这些数据,你需要了解它的内部结构。在我们的示例中,我们”序列化”了10个进程对象。结果发现,Convert-Xml
通过描述所有属性来保存这些对象。上面的代码演示了如何首先获取序列化对象(在 .Objects.Object` 中找到),然后如何读取属性信息(在
.Property` 中作为对象数组,每个属性一个对象)。