【问题标题】:Optimal way of creating object from two objects从两个对象创建对象的最佳方式
【发布时间】:2019-05-27 18:08:46
【问题描述】:

我构建了这个,运行良好,运行和显示大约需要 7-9 秒。 我想知道,是否有更快/最佳的方式来构建这个自定义对象?

如您所见,我想要来自 Win32_PNPsigneddriver 的所有驱动程序信息,但除此之外,我还根据 DeviceID 添加了来自 Win32_PNPentity 的另外两个属性(configmanagererrorcode 和 status)。

这样,最终对象包含所有驱动程序,并显示使用该驱动程序的设备是否存在错误。

$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"

就像我说的,一切正常。不过,我很想知道是否有更快的方法!

【问题讨论】:

    标签: powershell optimization foreach properties


    【解决方案1】:

    从 PowerShell 3.0 开始,Get-WmiObject cmdlet 已被 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
    

    【讨论】:

      【解决方案2】:

      瓶颈是每次使用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"
      

      【讨论】:

      • 里面有很棒的提示,非常感谢!不太习惯分组对象,这教会了我,
      【解决方案3】:

      这就是我的做法,性能差异不大,但更清晰的 IMO: 结果用了一个ArrayList,还把Get-WmiObject上的Where-Object换成了-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"
      

      【讨论】:

        猜你喜欢
        • 2013-01-22
        • 2014-01-17
        • 1970-01-01
        • 1970-01-01
        • 2013-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-19
        相关资源
        最近更新 更多