First, Win32_产品是癌症。尽管名称暗示它是只读操作它将针对任何未通过完整性检查的软件默默地执行修复安装。避免使用它,因为:
-
这可能会在受控环境中引入意外和计划外的变化;and
-
只读操作导致状态改变是不可接受的;and
-
即使不会因重新安装而导致中断,完整性检查也可能会占用 CPU 和磁盘资源,重新安装软件也会占用大量资源,从而导致与系统上运行的其他应用程序发生资源争用。
微软此前曾表示这是一个“无法解决”的问题。由于这就是该类长期以来的行为方式,“修复”它可能会破坏今天依赖错误行为的人们。
通过重新利用上面链接答案中的一些代码,我们可以检查注册表中的软件清单,获取当前计算机名称,并返回[hashtable]
以计算机名称作为键,其值是系统上已安装软件的数组:
# We need to check for both 64-bit and 32-bit software
$regPaths = "HKLM:\SOFTWARE\Wow6432node\Microsoft\Windows\CurrentVersion\Uninstall",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
# Get the name of all installed software registered in the registry
$softwareInventory = @{
$env:ComputerName = $regPaths | Foreach-Object {
( Get-ItemProperty "${_}\*" DisplayName -EA SilentlyContinue ).DisplayName
}
}
Note:这不会捕获未使用 Microsoft Installer 安装的软件,但大多数软件是通过 MSI 安装的(通常.exe
安装人员只需环绕即可.msi
安装人员)。
$softwareInventory
现在是一个以计算机名称作为键的哈希表。因此,一旦从服务器/计算机收集到此信息,您就可以引用名为的计算机的软件清单PlanetExpressServer01
像这样:
$softwareInventory['PlanetExpressServer01']
# OR (must still wrap property name in quotes for specially parsed characters
# such as the hyphen (-)
$softwareInventory.PlanetExpressServer01
$softwareInventory.'PlanetExpressServer-02'
如果您希望计算机名称成为其自己的属性,而不是计算机的密钥hashtable
,我们可以在创建时再进行一次调整$softwareInventory
:
$softwareInventory = [PSCustomObject]@{
ComputerName = $env:ComputerName
Software = $regPaths | Foreach-Object {
( Get-ItemProperty "${_}\*" DisplayName -EA SilentlyContinue ).DisplayName
}
}
只需创建一个新的hashtable
称为键ComputerName
,分配$env:ComputerName
对此,将软件清单放在一个名为的新密钥下Software
,并将哈希表转换为PSCustomObject
所以它的操作更像是一个传统的对象而不是一个数组。现在每个“行”都会有一个ComputerName
“列”和Software
“柱子”。
附加信息
有关原因的更多信息 *Win32_产品不好,下面的文章值得一读,并提供了其他技术来避免使用它:
请停止使用 Win32_Product 查找已安装的软件
感谢@FoxDeploy 提供了现已删除的问题的链接。