Оптимальный способ создания объекта из двух объектов - PullRequest
2 голосов
/ 27 мая 2019

Я построил это, который работает нормально, для запуска и отображения требуется около 7-9 секунд. Мне интересно, есть ли более быстрый / оптимальный способ создания этого пользовательского объекта?

Как видите, я хочу получить всю информацию о драйверах от Win32_PNPsigneddriver, но к этому я добавляю два других свойства из Win32_PNPentity (configmanagererrorcode и status) на основе DeviceID.

Таким образом, конечный объект содержит все драйверы и показывает, есть ли ошибка для устройства, использующего этот драйвер.

$poste = "COMPUTER1234"

$DriversUp = Get-WmiObject -computername $poste Win32_PNPsigneddriver |
             Where-Object {$_.DeviceName -ne $null} 
$Devices = Get-WmiObject -computername $poste Win32_PNPentity

$DriversDevices = foreach ($driver in $DriversUp) {
    $driver |
        Select-Object DeviceClass, Manufacturer, DeviceName,
            FriendlyName, DriverName, InfName,
            @{name='Status';expression={$Devices | Where-Object {$_.DeviceID -eq "$($driver.DeviceID)"} | Select-Object -ExpandProperty status}},
            @{name='ConfigManagerErrorCode';expression={$Devices | Where-Object {$_.DeviceID -eq "$($driver.DeviceID)"} | Select-Object -ExpandProperty ConfigManagerErrorCode}},
            @{name='DriverDate';expression={[DateTime]::ParseExact(($_.DriverDate).Split('.')[0], "yyyyMMddHHmmss", [System.Globalization.CultureInfo]::InvariantCulture)}},
            DriverVersion
}

$DriversDevices |
    Sort-Object DeviceClass |
    Out-GridView -Title "$poste - Drivers utilisés"

Как я и сказал, все уже отлично работает. Однако мне любопытно узнать, есть ли более быстрый способ!

Ответы [ 3 ]

1 голос
/ 27 мая 2019

Узкое место ищет устройство каждый раз, используя Where-Object.В следующем коде для решения проблемы используется Group-Object.

$poste = "COMPUTER1234"

$DriversUp = Get-WmiObject -ComputerName $poste Win32_PnPSignedDriver -Filter "DeviceName != NULL"
$Devices = Get-WmiObject -ComputerName $poste Win32_PnPEntity -Property DeviceID,Status,ConfigManagerErrorCode

@($DriversUp; $Devices) | Group-Object DeviceID | Where-Object Count -eq 2 | ForEach-Object {
    $driver, $device = $_.Group
    [pscustomobject]@{
        DeviceClass = $driver.DeviceClass
        Manufacturer = $driver.Manufacturer
        DeviceName = $driver.DeviceName
        FriendlyName = $driver.FriendlyName
        DriverName = $driver.DriverName
        InfName = $driver.InfName
        Status = $device.Status
        ConfigManagerErrorCode = $device.ConfigManagerErrorCode
        DriverDate = [datetime]::ParseExact($driver.DriverDate.Substring(0, 14), "yyyyMMddHHmmss", $null)
        DriverVersion = $driver.DriverVersion
    } 
} | Sort-Object DeviceClass | Out-GridView -Title "$poste - Drivers utilisés"
1 голос
/ 28 мая 2019

Начиная с PowerShell 3.0, командлет Get-WmiObject был заменен на Get-CimInstance.

$poste = "COMPUTER1234"
$cimses = New-CimSession -ComputerName $poste
$p = & {$args} DeviceClass Manufacturer DeviceName FriendlyName DriverName `
               InfName DriverVersion DeviceID DriverDate
Get-CimInstance -CimSession $cimses -ClassName Win32_PnPSignedDriver `
                -Property $p -Filter 'DeviceName != NULL' |
  ForEach-Object {
    $dev = Get-CimInstance -CimSession $cimses -ClassName Win32_PnPEntity `
                           -Property Status, ConfigManagerErrorCode `
                           -Filter "PNPDeviceID='$($_.DeviceID.Replace('\', '\\'))'"
    [pscustomobject]@{
      DeviceClass = $_.DeviceClass
      Manufacturer = $_.Manufacturer
      DeviceName = $_.DeviceName
      FriendlyName = $_.FriendlyName
      DriverName = $_.DriverName
      InfName = $_.InfName
      Status = $dev.Status
      ConfigManagerErrorCode = $dev.ConfigManagerErrorCode
      DriverDate = '{0:yyyyMMddHHmmss}' -f $_.DriverDate
      DriverVersion = $_.DriverVersion
    }
  } | Sort-Object DeviceClass | Out-GridView -Title "$poste - Drivers utilisés"
Remove-CimSession -CimSession $cimses

На моей машине типWin32_PnPSignedDriver.DriverDate член DateTime.

Get-CimClass -ClassName Win32_PnPSignedDriver |
  Select-Object -ExpandProperty CimClassProperties |
  Where-Object Name -eq 'DriverDate' |
  Select-Object CimType | Format-Table -AutoSize

 CimType
 -------
DateTime
0 голосов
/ 27 мая 2019

Вот как бы я это сделал, не большая разница в производительности, но более понятная IMO: Использовал ArrayList для результатов, также заменил Where-Object на Get-WmiObject на -Filter, это немного быстрее ...

$poste = "COMPUTER1234"    
$DriversUp = Get-WmiObject -computername $poste Win32_PNPsigneddriver -Filter "DeviceName != NULL" 
$Devices = Get-WmiObject -computername $poste Win32_PNPentity

$DriversDevices = New-Object System.Collections.ArrayList

    foreach ($driver in $DriversUp) {

    $row = "" | Select DeviceClass,Manufacturer,DeviceName,FriendlyName,DriverName,
    InfName,Status,ConfigManagerErrorCode,DriverDate,DriverVersion

    $row.DeviceClass = $driver.DeviceClass
    $row.Manufacturer = $driver.Manufacturer
    $row.DeviceName = $driver.DeviceName
    $row.DriverName = $driver.DriverName
    $row.InfName = $driver.InfName
    $row.Status = ($Devices | ? {$_.DeviceID -eq $driver.DeviceID}).Status
    $row.ConfigManagerErrorCode = ($Devices | ? {$_.DeviceID -eq $driver.DeviceID}).ConfigManagerErrorCode
    $row.DriverDate = [datetime]::ParseExact(($driver.DriverDate.Split('.')[0]),"yyyyMMddHHmmss",$null)
    $row.DriverVersion = $driver.DriverVersion
    [void]$DriversDevices.Add($row)
    }

    $DriversDevices | Sort-Object DeviceClass | Out-GridView -Title "$poste - Drivers utilisés"
...