在 Powershell 中拆分 WMI 对象

Split up WMI Objects in Powershell

我是 PowerShell 的新手,我尝试阅读来自客户的一些 monitor/display 信息。

我整理了这个脚本:

param(
[string]$ComputerName
)

$objWMi = get-wmiobject -namespace root\WMI -ComputerName $ComputerName -class WmiMonitorID | select WeekOfManufacture, YearOfManufacture, UserFriendlyName, SerialNumberID, ManufacturerName

$Userfn = ForEach-Object {($objWMi.UserFriendlyName -ne 0 | foreach {[char]$_}) -join"";}
$SerialNum = ForEach-Object {($objWMi.SerialNumberID -ne 0 | foreach {[char]$_}) -join"";}
$ManuName = ForEach-Object {($objWMi.ManufacturerName -ne 0 | foreach {[char]$_}) -join"";}
$Weekom = $objWMi.WeekOfManufacture
$Yearom = $objWMi.YearOfManufacture


Write-Host "1: $Userfn  | $ManuName | $SerialNum | $Weekom | $Yearom" 


Exit 0

.\myscript.ps1 -ComputerName clientdnsname 和 returns 调用它是这样的:

1: P22W-5 ECO | FUS | YE7XXXXX | 46 | 2008

效果很好,正是我所需要的。有一个例外:如果某些客户端有多个监视器附加脚本 returns 是这样的:

1: HP E272qHP E272q | HWPHWP | CNKXXXXCCNKYYYY | 40 40 | 2015 2015

如果有多个监视器和输出,我如何修改输出以拆分结果

1: HP E272q | HWP| CNKXXXX | 40 | 2015 2: HP E272q | HWP| CNKXXXX | 40 | 2015

变量包含所有监视器的信息,我不知道如何避免这种情况或如何将其拆分为每个变量的一个值。 非常感谢任何想法!

编辑:我需要像上面那样在 一行 中返回结果,因为我将其提供给另一个程序。

查看此脚本:http://www.activexperts.com/admin/scripts/wmiscripts/powershell/0073/

它不像您那样处理文本转换,但使用您已有的代码很容易纠正。

此修改应该非常接近您的需要:

function byteArrayToString($byteArray)
{
    if ($byteArray.Count -gt 0){
        return ($byteArray -ne 0 | foreach {[char]$_}) -join""
    }
    return "N/A"
}

$strComputer = "."

$objWMi = get-wmiobject -namespace root\WMI -computername localhost -Query "Select * from WmiMonitorID"

foreach ($obj in $objWmi)
{
    $Userfn = byteArrayToString($obj.UserFriendlyName)
    $SerialNum = byteArrayToString($obj.SerialNumberID)
    $ManuName = byteArrayToString($obj.ManufacturerName)
    $Weekom = $obj.WeekOfManufacture
    $Yearom = $obj.YearOfManufacture
    Write-Host "1: $Userfn  | $ManuName | $SerialNum | $Weekom | $Yearom" 
}

我觉得有必要补充一个答案。请记住 Write-Host 不是正确的选择。正如 Don Jones explains 它杀死了小狗,还有很多更好的方法来实现你想要的。

首先,通过生成 PSCustomObject 你可以做更多的事情。

一些例子:

Function Get-MonitorInfo {
    Param (
        [String]$ComputerName = $env:COMPUTERNAME
    )

    # For ease of reading the code we create a hashtable which we use wit 'Get-WmiObject', this is called 'Splatting'
    $WmiParams = @{
        Namespace    = 'root\WMI'
        ComputerName = $ComputerName
        Class        = 'WmiMonitorID'
    }

    # First we collect all the results in one variabla
    $Objects = Get-WmiObject @WmiParams | Select-Object WeekOfManufacture, YearOfManufacture, 
        UserFriendlyName, SerialNumberID, ManufacturerName

    # Then for each object in the variable '$Objects' we generate one line of output (an object)
    foreach ($Object in $Objects) {

        # The generated object will contain the following
        [PSCustomObject]@{
            FriendlyName      = ($Object.UserFriendlyName | ForEach-Object {[Char]$_}) -join ''
            SN                = ($Object.SerialNumberID | ForEach-Object {[Char]$_}) -join ''
            ManufacturerName  = ($Object.ManufacturerName | ForEach-Object {[char]$_}) -join ''
            ManufacturingWeek = $Object.WeekOfManufacture
            ManufacturingYear = $Object.YearOfManufacture
        }
    }
}

$Result = Get-MonitorInfo

# List all monitors:
$Result

# Only list Monitors with a FriendlyName starting with HP:
$Result | where {$_.FriendlyName -like 'HP*'}

# Only list Monitors with a FriendlyName starting with HP and show me the SN:
$Result | where {$_.FriendlyName -like 'HP*'} | Select-Object SN

# Count how many monitors we have on one machine:
$Result.Count

# Export everything to a file
$Result | Out-File -FilePath "$env:TEMP\Monitors.txt"
Start-Process "$env:TEMP\Monitors.txt"

如您所见,仅使用 Write-Host 时,所有这些事情都会很困难。希望上面的例子让你更清楚为什么你不应该在这种情况下使用 Write-Host

我试图提出以下建议作为对 DarkLite1 答案的修改,但显然有人认为它是 "deliberately destructive" 并拒绝了它。 . .

为了回答你的问题,duenni,以下对 DarkLite1 代码的修改将使你能够以你正在寻找的格式输出数据。

Function byteArrayToString($byteArray)
{
    if ($byteArray.Count -gt 0){
        return ($byteArray -ne 0 | foreach {[char]$_}) -join""
    }
    return "N/A"
}

Function Get-MonitorInfo {
    Param (
        [String]$ComputerName = $env:COMPUTERNAME
    )

    # For ease of reading the code we create a hashtable which we use wit 'Get-WmiObject', this is called 'Splatting'
    $WmiParams = @{
        Namespace    = 'root\WMI'
        ComputerName = $ComputerName
        Class        = 'WmiMonitorID'
    }

    # First we collect all the results in one variabla
    $Objects = Get-WmiObject @WmiParams | Select-Object WeekOfManufacture, YearOfManufacture, 
        UserFriendlyName, SerialNumberID, ManufacturerName

    # Then for each object in the variable '$Objects' we generate one line of output (an object)
    foreach ($Object in $Objects) {

        # The generated object will contain the following
        [PSCustomObject]@{
            FriendlyName      = byteArrayToString($Object.UserFriendlyName)
            SN                = byteArrayToString($Object.SerialNumberID)
            ManufacturerName  = byteArrayToString($Object.ManufacturerName)
            ManufacturingWeek = $Object.WeekOfManufacture
            ManufacturingYear = $Object.YearOfManufacture
        } | Add-Member -MemberType ScriptMethod -Name ToString -Force -Value {
            "1: $($this.FriendlyName) | $($this.ManufacturerName) | $($this.SN) | $($this.ManufacturingWeek) | $($this.ManufacturingYear)"
        } -PassThru
    }
}

$Result = Get-MonitorInfo

# List all monitors:
$Result

# List all monitors as formatted strings
foreach ($monitor in $Result) {$monitor.ToString()}

# Only list Monitors with a FriendlyName starting with HP:
$Result | where {$_.FriendlyName -like 'HP*'}

# Only list Monitors with a FriendlyName starting with HP and show me the SN:
$Result | where {$_.FriendlyName -like 'HP*'} | Select-Object SN

# Count how many monitors we have on one machine:
$Result.Count

# Export everything to a file
$Result | Out-File -FilePath "$env:TEMP\Monitors.txt"
Start-Process "$env:TEMP\Monitors.txt"

新函数调用方式如下:

foreach ($monitor in $Result) {$monitor.ToString()}