如果使用 wmic 和 powershell 安装了特定程序,则查询远程计算机

Query remote machine if specific program installed using wmic and powershell

我正在编写脚本以使用 wmic 查询和 powershell 检查特定程序是否安装在某些远程计算机上

$Machines = Get-Content .\machines.txt 

foreach( $Machine in $Machines) 
{
    Write-Host " Processing Machine $Machine "
    if(Test-Connection $Machine -Count 2 -Quiet)
    {
    Get-WmiObject -ComputerName $Machine -Class Win32_Product  | 
    Select-Object __SERVER, Name, Vendor, Version, InstallDate | 
    sort-object Name | Where-Object { $_.Name -like "*Kasper*" -or $_.name -like "*Ivanti*" -or $_.name -like "*Traps*" -or $_.name -like "*microsoft*"} -ErrorAction SilentlyContinue |
    Export-Csv -Path .\result.csv -NoTypeInformation -Append
     }
    else
    {
       Write-Warning "Unable to connect to $Machine" 
       [pscustomobject]@{
            __SERVER = $Machine
            Name = 'not found'
        }       | Export-Csv -Path .\result.csv -NoTypeInformation -Append
     } 
}

我希望在一个导出的 CSV 文件中看到我的机器列表的结果,如果它没有像下面这样写 "machine not reachable",则从机器收集结果,如果它在线写程序 detalis

__SERVER    Name    Vendor  Version InstallDate
it01    Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.6161  Microsoft Corporation   9.0.30729.6161  20190626
it01    Microsoft Visual C++ 2008 Redistributable - x86 9.0.30729.6161  Microsoft Corporation   9.0.30729.6161  20190626
it-machine2 Can't reached           
it-machine3 Can't reached           
IT-Machine7 Kasper Endpoint protection  Kasper LAB  10.3.200.2  20190526

如果 ICMP 规则在 windows 防火墙中关闭,服务器仍然可以访问,因此确定服务器不可访问的最佳方法是让 cmdlet Get-WMIobject 失败。 在 powershell 上执行并行操作的最佳方法是使用 powershell 作业。 希望这有帮助。

$Machines = Get-Content .\machines.txt 
$scriptBlock={
    try
    {
        $result = Get-WmiObject -ComputerName $args[0] -Class Win32_Product -ErrorAction Stop  | 
        Select-Object __SERVER, Name, Vendor, Version, InstallDate | 
        sort-object Name | Where-Object { $_.Name -like "*Kasper*" -or $_.name -like "*Ivanti*" -or $_.name -like "*Traps*" -or $_.name -like "*microsoft*"} -ErrorAction Stop 
        return @{"Success"=$true; "result"=$result; "server_name"=$args[0]}
    }
    catch
    {
        return @{"Success"=$false; "server_name"=$args[0]}
    }
}

get-job | Remove-Job

foreach($Machine in $Machines) 
{
    Start-Job -Name "Query programs" -ScriptBlock $scriptBlock -ArgumentList $Machine
}

$processing=$true;
while($processing)
{
    start-sleep 2
    $jobsLeft = Get-Job | Where-Object {$_.Name -eq "Query programs" -and $_.State -eq "Running"} | Measure-Object | Select-Object -ExpandProperty Count
    Write-Host "$jobsLeft servers still processing"
    if(0 -eq $jobsLeft)
    {
        $processing=$false;
    }
}

[array]$results=@();
foreach($job in Get-Job | Where-Object {$_.Name -eq "Query programs" -and $_.State -eq "Completed"})
{
    $jobResult = $job | Receive-Job;
    if($true -eq $jobResult.Success)
    {
        foreach($item in $jobResult.result)
        {
            $obj = New-Object PsObject;
            $obj | Add-Member -NotePropertyName ServerName -NotePropertyValue $jobResult.server_name
            $obj | Add-Member -NotePropertyName Name -NotePropertyValue $item.Name
            $obj | Add-Member -NotePropertyName Vendor -NotePropertyValue $item.Vendor
            $obj | Add-Member -NotePropertyName Version -NotePropertyValue $item.Version
            $obj | Add-Member -NotePropertyName InstallDate -NotePropertyValue $item.InstallDate
            $results += $obj
        }
    }
    else
    {
        $obj = New-Object PsObject;
        $obj | Add-Member -NotePropertyName ServerName -NotePropertyValue $jobResult.server_name
        $obj | Add-Member -NotePropertyName Name -NotePropertyValue "Can't reach"
        $obj | Add-Member -NotePropertyName Vendor -NotePropertyValue $null
        $obj | Add-Member -NotePropertyName Version -NotePropertyValue $null
        $obj | Add-Member -NotePropertyName InstallDate -NotePropertyValue $null
        $results += $obj
    }
} 

$results | Export-Csv -Path .\result.csv