【问题标题】:Split up WMI Objects in Powershell在 Powershell 中拆分 WMI 对象
【发布时间】:2016-02-18 13:59:57
【问题描述】:

我是 PowerShell 新手,我尝试从客户端读取一些监视器/显示信息。

我整理了这个脚本:

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 调用它并返回如下内容:

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

就像一个魅力,正是我需要的。有一个例外:如果某些客户端连接了多个监视器,则脚本将返回如下内容:

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

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

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

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

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

【问题讨论】:

    标签: powershell scripting wmi wmi-query


    【解决方案1】:

    查看此脚本: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 放置了一个foreach 循环。这也会输出具有双倍条目的行,但只会执行两次......
    • 我将代码更新为在一行上为您输出。围绕变量赋值的“foreach”循环是导致问题的原因。
    • 是的。我也尝试在变量周围使用foreach 循环,但没有同时删除ForEach-Object。谢谢!
    • 我添加了一个小函数来进行字符串转换。这样,如果你得到一个空值,它不会抛出错误。 DarkLite1 的解决方案更优雅。所以理想情况下,我会将该功能与他的回应结合起来。
    【解决方案2】:

    我觉得有必要添加一个额外的答案。请记住,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

    【讨论】:

    • 谢谢!我不知道这件事。我正在用另一个程序处理这个脚本,该程序正在执行该脚本并期望一个字符串作为结果打印到标准输出(在一行中)。
    • 不客气,希望你学到了一些东西。也可以输出到字符串:$Result | Select @{N='String';E={"$($_.FriendlyName) | $($_.SN) | $($_.ManufacturerName) | $($_.ManufacturingWeek) | $($_.ManufacturingYear)"}} | Out-String,或者如果您的意思是在一行上查看内容,您也可以使用$Result | Format-Table
    • 非常感谢!哈希表似乎不起作用,它总是从本地主机返回信息......还有没有办法只返回这一行?您的第一个示例输出 String ------ P22W-5 ECO | YE7XXXXX | FUS | 46 | 2008 如何避免整个“字符串”行?
    • 有了对象一切皆有可能,请试试这个:Get-MonitorInfo -ComputerName MyPCNameHere | Select @{N='String';E={"$($_.FriendlyName) | $($_.SN) | $($_.ManufacturerName) | $($_.ManufacturingWeek) | $($_.ManufacturingYear)"}} | Select -ExpandProperty String
    【解决方案3】:

    我试图提出以下作为对 DarkLite1 答案的修改,但显然有人认为它是“故意破坏性的”并拒绝了它。 . .

    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()}

    【讨论】:

    • 谢谢!对你起作用吗?如果我用.\myscript.ps1 -ComputerName hostxy 调用它,它总是从本地主机返回信息。我尝试将$Result = Get-MonitorInfo 修改为$Result = Get-MonitorInfo -ComputerName $ComputerName,但这不起作用。
    • 嗯,我想我明白了。必须在 ps1 文件的开头使用另一个 Param-block,例如:param( [string]$HostName )。然后将此参数传递给带有$Result = Get-MonitorInfo($HostName) 的函数。然后我可以像这样调用脚本myscript.ps1 -HostName hostxy
    • 你可以这样做,或者你可以点源化 ps1 文件,然后调用Get-MonitorInfo -ComputerName whatever 了解详情,查看此页面并搜索“点源”:technet.microsoft.com/en-us/library/hh847841.aspx跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-17
    相关资源
    最近更新 更多