PowerShell 技能连载 - 查找 MSI 产品代码(第 1 部分)
如果您需要已安装的 MSI 软件包及其产品代码列表,则可以使用 WMI 查询信息。以下操作可能需要几秒钟:
1 | Get-CimInstance -ClassName Win32_Product | |
如果您需要已安装的 MSI 软件包及其产品代码列表,则可以使用 WMI 查询信息。以下操作可能需要几秒钟:
1 | Get-CimInstance -ClassName Win32_Product | |
如果您需要访问 Windows 凭据管理器存储的凭据(已保存的密码),则 “CredentialManager” 模块可能有所帮助。运行此代码下载并安装它:
1 | Install-Module -Name CredentialManager -Scope CurrentUser |
安装该模块后,您可以列出其提供的新命令:
1 | PS> Get-Command -Module CredentialManager |
Get-StoredCredential
获取存储的凭据。并且 New-StoredCredential
可以与凭据管理器一起存储凭据:
获得存储的存储凭据。 而且,新存储者可以为您与凭据管理器一起存储凭据:
1 | New-StoredCredential -Target MyCred -Credentials (Get-Credential) -Type Generic -Persist LocalMachine |
现在,当脚本需要访问存储的凭据时,请像这样使用 Get-StoredCredential
:
1 | $cred = Get-StoredCredential -Target MyCred |
Windows 凭据管理器安全地为本地用户存储凭据。只有最初保存凭据的用户才能检索它。
HTML 方便地将数据格式化为输出报告。在这个最后的部分中,我们将介绍如何将最终 HTML 报告转换为 PDF,以便轻松地将其传递给同事和团队成员。
以下是我们在第二部分介绍的脚本:
1 | $path = "$env:temp\report.html" |
结果是位于 $Path
中指定的文件位置中的 HTML 报告。现在,缺少的是将 HTML 文件转换为 PDF 文件的方法。
有很多方法可以实现这一目标,但最方便的方法是使用 Chrome 浏览器。但是,要进行转换,首先需要安装 Chrome 浏览器(如果尚未安装)。
这是获取现有 HTML 文件并将其转换为 PDF 的最终代码:
1 | # path to existing HTML file |
HTML 是一种将数据格式化为输出报告的简单方法。在第二部分中,我们说明了如何将包含数组的属性转换为字符串列表。数组无法正确显示为文本,因此此问题适用于 HTML 报告和将数据导出到 CSV。
请看:下面的代码将您的所有服务生成 HTML 报告,这是我们在第一部分结束时停下的地方:
1 | $path = "$env:temp\report.html" |
当您查看报告时,您会注意到某些列包含数据类型而不是数据,即 RequiredServices
和 DependentServices
。 原因是因为这些属性包含数组。要正确显示属性内容,您需要首先将数组转换为字符串列表。
这是一个自动检测包含数组的属性并用字符串列表代替这些属性的函数:
1 | function Convert-ArrayToStringList |
为此,您首先必须通过 Select-Object
获取可以操纵的对象的副本。Convert-ArrayToStringList
也对创建 CSV 导出非常有帮助。下面的代码将服务列表创建为 CSV 文件,并确保所有属性都是可读的,然后将 CSV 文件加载到 Microsoft Excel 中:
1 | $Path = "$env:temp\report.csv" |
这是一个完整的脚本,能创建一个具有所有可读属性的服务报告:
1 | $path = "$env:temp\report.html" |
可以通过 HTML 轻松地将格式化的数据转换成输出报告。在这个三部分的系列中,我们首先说明您如何撰写 HTML 报告,然后展示一种将这些 HTML 报告转换为 PDF 文档的简单方法。
PowerShell 中有一个 ConvertTo-Html
cmdlet,可以轻松将输出保存到 HTML 表格:
1 | $path = "$env:temp\report.html" |
最终的报告可能仍然很丑陋,但是添加 HTML 样式表可以轻松美化报告并添加您的公司设计:
1 | $path = "$env:temp\report.html" |
如果您有时使用 Get-Help
和本地帮助,则应该偶尔运行 Update-Help
以更新本地帮助文件。在 Windows PowerShell 上,这需要本地管理特权,因为帮助文件存储在受保护的 Windows 文件夹中:
1 | PS> Update-Help -UICulture en-us -Force |
在 PowerShell 7 上,Update-Help
现在有一个附加的参数 -Scope CurrentUser
,因此您也可以在没有管理员特权的情况下更新本地帮助。
更新本地帮助很重要,因为每当您运行它时,它都会动态地查看机器上存在的 PowerShell 模块,并仅下载关于它们的帮助。如果以后添加更多模块,则不要忘记再次运行更新——还可以下载新模块的帮助文件——前提是该模块尚未发布它们。
请注意,Update-Module
可能会在结束时发出红色错误消息。不用担心:通常,它仅是由几个没有帮助的模块引起的。错误消息并未表明整个更新过程有问题。
当 PowerShell 启动时,它会自动查找一个特殊的自动启动脚本。默认情况下该脚本不存在,并且对于每个 PowerShell 环境是不同的。$profile
变量体现它的路径。这是在我机器的 Windows PowerShell 控制台环境中的路径:
1 | C:\Users\tobias\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 |
可以快速地检测这个文件是否存在,如果不存在的话,用 PowerShell 创建它:
1 | $exists = Test-Path -Path $profile |
有了这样的自启动脚本后,您可以在您的每个 PowerShell 会话中添加各种有用的东西。例如,创建一个较短的命令行提示符:
1 | function prompt |
或通过简化的登录使生活更轻松:
1 | function in365 |
只需确保您保存更改以及执行策略允许脚本运行即可。
-match
运算符经常在脚本中使用,但是似乎并不是每个人都了解它实际的工作方式。它可能是一个非常危险的过滤器操作符。
让我们先创建一些示例数据:
1 | $list = 'ServerName, Location, Status |
结果是假设服务器的列表:
ServerName Location Status
---------- -------- ------
Test1 Hannover Up
Test2 New York Up
Test11 Sydney Up
假设您希望 PowerShell 脚本从列表中选择服务器并操作它,例如关闭电源:
1 | # server to work with: |
一切看起来工作正常:
ServerName Location Status
---------- -------- ------
Test2 New York Up
但是, -match
期望的是正则表达式,而不仅仅是纯文本。另外,如果在文本中的任意位置找到了匹配的表达式,则它将返回 $true
。将 $filter
改为 “Test1” 以选择服务器 “Test1” 时,以下是执行结果:
ServerName Location Status
---------- -------- ------
Test1 Hannover Up
Test11 Sydney Up
您会意外选择了两个服务器,因为 “Test11” 也包含了文本 “Test1”。
更糟糕的是:如果出于某种愚蠢的原因,$filter
是空白的,则会选择所有内容——因为“空白”能匹配任何内容。请自己尝试,并将 $filter
的值设为 ''
。
选择比较运算符时要非常小心,并且使用 -match
时要格外小心。在上面的示例中,-eq
运算符(等于)会更合适,如果您必须使用通配符,那么 -like
使用起来更明确,因为它需要明确的 “*” 通配符,如果您真的只想比较数值的一部分。
作为调试和质量控制的一部分,您可能需要记录赋值给一个变量的数据。例如,您可能需要找出赋值给指定变量的实际数据类型是什么,以便以后可以以强类型的方式访问变量以增加安全性。
这是一个自定义验证器类,可以用于这类分析。只需先运行下面的代码。除了声明新属性外,它不做任何事情:
1 | # create a new custom validation attribute named "LogVariableAttribute": |
现在,在您的脚本中,在开始时,通过添加新属性来初始化要跟踪的所有变量:
1 | [IdentifyType()]$test = 1 |
然后正常运行脚本。结果将记录到全局变量 $loggedTypes
中,通过它可以查看所有结果:
1 | # looking at the log results: |
在我们以前的迷你系列中,我们展示了使用不同的 PowerShell 方法来获取安装 OS 语言名称的几种方法。结果都是语言 ID 的列表,类似这样:
de-DE
en-US
fr-FR
如果我需要将它们转换为完整的国家名称怎么办?幸运的是,这只是数据类型的问题。我们演示的所有方法都可以以字符串的形式返回安装的语言包。让我们以 WMI 示例为例:
1 | $os = Get-CIMInstance -ClassName Win32_OperatingSystem |
当您将结果转换到更合适的数据类型时,将获得合适的数据。相对于字符串,让我们使用表示国家名称的数据类型:CultureInfo
!
1 | $os = Get-CIMInstance -ClassName Win32_OperatingSystem |
瞬间,相同的数据现在可以以更丰富的格式表示:
LCID Name DisplayName
---- ---- -----------
1031 de-DE German (Germany)
1033 en-US English (United States)
1036 fr-FR French (France)