在Powershell中拆分WMI对象

在Powershell中拆分WMI对象,powershell,scripting,wmi,wmi-query,Powershell,Scripting,Wmi,Wmi Query,我是PowerShell的新手,我尝试从客户端读取一些监视器/显示信息 我编写了以下脚本: param( [string]$ComputerName ) $objWMi = get-wmiobject -namespace root\WMI -ComputerName $ComputerName -class WmiMonitorID | select WeekOfManufacture, YearOfManufacture, UserFriendlyName, SerialNumberID,

我是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 | CNKXXCCNKYYYY | 40 40 | 2015

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

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

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

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

检查此脚本:

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

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

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" 
}
查看此脚本:

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

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

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

我觉得有必要增加一个额外的答案。请记住,
写主机
不是一条好路。就像唐·琼斯那样,它会杀死小狗,有很多更好的方法来实现你想要的

首先,通过生成
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

我觉得有必要添加一个额外的答案。请记住,
写主机
不是一条好路。就像唐·琼斯那样,它会杀死小狗,有很多更好的方法来实现你想要的

首先,通过生成
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"

正如您所看到的,当仅使用
编写主机时,所有这些事情都会很困难。希望上面的例子能更清楚地说明为什么在这种情况下不应该使用
写主机

我试图提出以下内容作为对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($Result中的monitor){$monitor.ToString()}
我试图提出以下内容作为对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($Result中的monitor){$monitor.ToString()}

谢谢。我以前看过这个剧本。不幸的是,我需要在一行中返回结果,因为我在另一个程序中处理结果…编辑我的帖子以澄清问题。我还在脚本中放置了一个
foreach
循环
write host
。这也会输出包含两个条目的行,但只输出两次……我更新了代码,以便在一行中输出。围绕变量赋值的“foreach”循环是造成问题的原因。耶。我也尝试过在变量周围使用
foreach
循环,但没有同时删除
foreach对象。谢谢我添加了一个小函数来进行字符串转换。这样,如果得到一个空值,它就不会抛出错误。不过,DarkLite1的解决方案更为优雅。所以理想情况下,我会把这个功能和他的回答结合起来。谢谢。我以前看过这个剧本。不幸的是,我需要在一行中返回结果,因为我在另一个程序中处理结果…编辑我的帖子以澄清问题。我还在脚本中放置了一个
foreach
循环
write host
。这也会输出包含两个条目的行,但只输出两次……我更新了代码,以便在一行中输出。围绕变量赋值的“foreach”循环是造成问题的原因。耶。我也尝试过在变量周围使用
foreach
循环,但没有同时删除
foreach对象。谢谢我添加了一个小函数来进行字符串转换。这样,如果得到一个空值,它就不会抛出错误。不过,DarkLite1的解决方案更为优雅。因此,理想情况下,我会将该功能与他的回答结合起来。谢谢!我不知道这件事。我正在用另一个程序来处理这个脚本,这个程序正在执行这个脚本,并且希望结果是一个字符串打印到标准输出(在一行中)。不客气,希望您学到了一些东西。也可以输出到字符串:
$Result |选择${N='string';E={“$($.FriendlyName)$($.SN)|$($.ManufacturerName)|$($.ManufacturingWeek)|$($.ManufacturingYear)}}}输出字符串
,或者如果您的意思是在一行上查看内容,也可以执行
$Result>格式表
。谢谢!哈希表似乎不起作用,它总是从localhost返回信息……还有没有办法只返回这一行?第一个示例输出
字符串