我尝试在计算机上枚举已安装的软件。我主要在远程系统上使用注册表中的一些键来执行此操作。我写的函数在某些机器上工作正常,但在其他机器上却没有。问题似乎是将数组从散列表复制到PSCustomObject类型的数组。 为了避免双重条目(在注册表中查询32位和64位配置单元),我生成了一个哈希表,其中包含一个由软件名称和版本组成的密钥。然后在将数据添加到哈希表之前检查密钥是否已存在。在处理结束时,我将哈希表的值复制到预先分配的数组。这是代码:
Function Get-InstalledSoftware
{
[CmdletBinding()]
param (
[ValidateNotNull()]
[Parameter(Mandatory = $true)]
[string]$ComputerName
)
$RegistryLocation = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\',
'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\'
$htSoftware = @{ }
$RegBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $ComputerName)
foreach ($CurrentReg in $RegistryLocation)
{
if ($RegBase)
{
$CurrentRegKey = $RegBase.OpenSubKey($CurrentReg)
if ($CurrentRegKey)
{
foreach ($key in $CurrentRegKey.GetSubKeyNames())
{
$newreglocation = $CurrentReg + $key + '\'
$cv = $RegBase.OpenSubKey($newreglocation)
if ($cv.GetValue('DisplayName') -ne $null)
{
$software = [PSCustomObject]@{
'Name' = $cv.GetValue('DisplayName')
'Version' = $cv.GetValue('DisplayVersion')
'Publisher' = $cv.GetValue('Publisher')
'Installationsort' = $cv.GetValue('InstallLocation')
'Installationsdatum' = $cv.GetValue('InstallDate')
}
}
#$arrSoftware += $software
$hashkey = $cv.GetValue('DisplayName') + "_" + $cv.GetValue('DisplayVersion')
if (!$htSoftware.ContainsKey($hashkey))
{
$htSoftware.Add($hashkey, $software)
}
}
}
}
}
[PSCustomObject[]]$arrSoftware = (1..$htSoftware.Count)
$htSoftware.Values.CopyTo($arrSoftware, 0)
$arrSoftware
}
然后使用一些辅助函数将返回的数组填充到gridview中:
$form_computer_details.UseWaitCursor = $true
[System.Windows.Forms.Application]::DoEvents()
$soft = Get-InstalledSoftware -ComputerName $ComputerName
if ($soft -ne $null)
{
$table = ConvertTo-DataTable -InputObject $soft
Load-DataGridView -DataGridView $datagridview_sw -Item $table
}
else
{
$richtextbox_ComputerInfoMsg.Text = "Konnte keine Daten aus der Registry des Computers $ComputerName lesen."
}
$form_computer_details.UseWaitCursor = $false
经过更长时间的调试会话后,问题出现在我的函数中这两行代码:
[PSCustomObject[]]$arrSoftware = (1..$htSoftware.Count)
$htSoftware.Values.CopyTo($arrSoftware, 0)
在运行它的机器上,调试器在声明和初始化后显示变量$ arrSoftware的以下内容:
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40"
在CopyTo命令之后,数组看起来像这样:
$arrSoftware "@{Name=Microsoft Visual Studio 2010 Shell (Isolated) - ENU; Version=10.0.40219; Publisher=Microsoft Corporation; Installationsort=; Installationsdatum=20151128}", "@{Name=Microsoft SQL Server 2014 RsFx Driver; Version=12.0.2000.8; Publisher=Microsoft Corporation; Installationsort=; Installationsdatum=20151128}", .....
(我截断了输出.....)
在机器上, NOT 工作时,它看起来如下:
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22"
好到目前为止,但现在复制后:
(Empty)
但$arrSoftware.count
在调试器中显示以下结果:
$arrSoftware.count 22
当我查看数组的第一个元素时,我看到以下内容:
$arrSoftware[0] @{Name=7-Zip 9.20 (x64 edition); Version=9.20.00.0; Publisher=Igor Pavlov; Installationsort=; Installationsdatum=20130526}
$arrSoftware[1] @{Name=Altaro Backup FS; Version=2.0.26.0; Publisher=Altaro; Installationsort=; Installationsdatum=20131221}
....
$arrSoftware[20] @{Name=Microsoft Visual C++ 2012 x86 Additional Runtime - 11.0.61030; Version=11.0.61030; Publisher=Microsoft Corporation; Installationsort=; Installationsdatum=20151219}
有趣的是,22的大小的最后一个元素应该是[21],这是EMPTY!
知道这里出了什么问题吗?