用于软件清单的 PowerShell

0 powershell

我想知道如何有两列包含已安装的软件和电脑名称:

$Path = "C:\Gabriel"
$LogPath = "C:\Gabriel"
Select Name,Directory,@{Name="Outlook";Expression={(Get-WmiObject -Class Win32_Product | where vendor -eq Outlook)}},
                      @{Name='Desktop';Expression={(Get-wmiobject win32_computersystem)}} | Export-Csv C:\Gabriel\Outlook.csv -NoTypeInformation
Run Code Online (Sandbox Code Playgroud)

Ben*_*est 6

首先,Win32_Product是毒瘤。尽管名称暗示它是只读操作,但它会默默地对任何未通过完整性检查的软件执行修复安装。避免使用它,因为:

  1. 这可能会在受控环境中引入意外和计划外的变化;

  2. 只读操作导致状态改变是不可接受的;

  3. 即使不会因重新安装而导致中断,完整性检查也可能会占用 CPU 和磁盘资源,重新安装软件也会占用大量资源,从而导致与系统上运行的其他应用程序发生资源争用。

微软此前曾表示这是一个“无法解决”的问题。由于这就是该类长期以来的行为方式,“修复”它可能会破坏今天依赖错误行为的人们。


通过重新利用上面链接答案中的一些代码,我们可以检查软件清单的注册表,获取当前计算机名称,并返回[hashtable]以计算机名称为键的 a ,其值是系统上已安装软件的数组:

# 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
  }
}
Run Code Online (Sandbox Code Playgroud)

注意:这不会捕获不是使用 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'
Run Code Online (Sandbox Code Playgroud)

如果您希望计算机名称成为其自己的属性,而不是 a 的键hashtable,我们可以在创建时再进行一项调整$softwareInventory

$softwareInventory = [PSCustomObject]@{
  ComputerName = $env:ComputerName
  Software = $regPaths | Foreach-Object {
    ( Get-ItemProperty "${_}\*" DisplayName -EA SilentlyContinue ).DisplayName
  }
}
Run Code Online (Sandbox Code Playgroud)

只需创建一个hashtable名为 的新键ComputerName,将 分配$env:ComputerName给它,将软件清单放在名为 的新键下Software,然后将哈希表转换为 a PSCustomObject,这样它的操作方式就更像传统对象而不是数组。现在每个“行”都会有一个ComputerName“列”和Software“列”。


附加信息

有关为什么 * Win32_Product不好的其他信息,以下文章值得一读,并提供了避免使用它的其他技术:

请停止使用 Win32_Product 查找已安装的软件

感谢@FoxDeploy 提供了现已删除的问题的链接。