如何将prnmngr的输出转换为自定义对象?

时间:2018-05-08 19:45:04

标签: powershell text-parsing pscustomobject

cscript prnmngr.vbs -l

的输出
Server name abcd 
Printer name \\abcd.com\mailroom
Share name mailroom
Driver name Canon iR-ADV 4225/4235 UFR II
Port name mailroom.com
Comment
Location
Print processor winprint
Data type RAW
Parameters
Attributes 536
Priority 1
Default priority 0
Average pages per minute 0
Printer status Idle
Extended printer status Unknown
Detected error state Unknown
Extended detected error state Unknown

Server name cdef 
Printer name \\cdfet.com\mailroom3
Share name mailroom3
Driver name Canon iR-ADV 4225/4235 UFR II
Port name mailroomxxx.com
Comment
Location
Print processor winprint
Data type RAW
Parameters
Attributes 536
Priority 1
Default priority 0
Average pages per minute 0
Printer status Idle
Extended printer status Unknown
Detected error state Unknown
Extended detected error state Unknown

之类的(注意修改后的输出属性名称):

$CustomPrinterobjects = New-Object –TypeName PSObject
$CustomPrinterobjects | Add-Member –MemberType NoteProperty –Name ComputerName –Value "$a" 
$CustomPrinterobjects | Add-Member –MemberType NoteProperty –Name Name –Value "$b" 
$CustomPrinterobjects | Add-Member –MemberType NoteProperty –Name ShareName –Value "$c" 
$CustomPrinterobjects | Add-Member –MemberType NoteProperty –Name DriverName –Value "$d"
$CustomPrinterobjects | Add-Member –MemberType NoteProperty –Name PortName –Value "$e"

其中$a$b$c$d$e表示在cscript prnmngr.vbs -l的输出上循环的属性值

2 个答案:

答案 0 :(得分:1)

Kory Gill有助于建议使用W8 + / W2K12 + Get-Printer cmdlet

同样,kuujinbo建议String[] movieList = fileScanner.nextLine().split("//"); 用于早期操作系统版本。

根据PowerShell的精神,这两个命令都会返回对象,您可以直接访问属性 - 无需文本解析

如果您仍然需要解析Get-WmiObject -Class Win32_Printer的输出(如果它提供了所引用命令没有提供的额外信息),请使用以下方法 - 注意解析 textual 输出到结构化对象

鉴于所有信息都是以空格分隔的,并且每行的属性 name 部分由不同的数量的标记组成,解析文本的唯一可预测方法是到:

  • 维护众所周知的属性名称
  • 的集合
  • 的行之后 之后

PSv3 +解决方案:

cscript prnmngr.vbs -l

使用您的示例输入,上面会产生一个2元素的# Map the input property names of interest to output property names, # using a hashtable. $propNameMap = @{ 'Server name ' = 'ComputerName' 'Printer name ' = 'Name' 'Share name ' = 'ShareName' 'Driver name ' = 'DriverName' 'Port name ' = 'PortName' } # Split the output of `cscript prnmngr.vbs -l` into paragraphs and # parse each paragaph into a custom object with only the properties of interest. $customPrinterObjs = (cscript prnmngr.vbs -l) -join "`n" -split "`n`n" | ForEach-Object { $ohtFields = [ordered] @{} foreach ($line in $_ -split "`n") { foreach ($propNamePair in $propNameMap.GetEnumerator()) { if ($line -like ($propNamePair.Key + '*')) { $ohtFields[$propNamePair.Value] = $line.Substring($propNamePair.Key.length) } } } [pscustomobject] $ohtFields } # Output the resulting custom objects. $customPrinterObjs 数组:

[pscustomobject]
  • ComputerName : abcd Name : \\abcd.com\mailroom ShareName : mailroom DriverName : Canon iR-ADV 4225/4235 UFR II PortName : mailroom.com ComputerName : cdef Name : \\cdfet.com\mailroom3 ShareName : mailroom3 DriverName : Canon iR-ADV 4225/4235 UFR II PortName : mailroomxxx.com 从数组中收集(cscript prnmngr.vbs -l) -join "`n"的输出行,然后将它们连接起来形成一个多行字符串。

  • cscript prnmngr.vbs -l将生成的多行字符串拆分为段落,每个字符串代表一个打印机的属性。

  • -split "`n`n"脚本块然后处理每个打印机的属性段落:

    • ForEach-Object将多行段落拆分为一系列行并循环遍历它们。
    • foreach($line in $_ -split "`n")初始化一个空的有序哈希表(其中条目按输出的定义顺序反映),作为创建自定义对象的基础。
    • 然后内部$ohtFields = [ordered] @{}循环检查每一行是否包含感兴趣的属性,如果是,则使用输出属性名称和属性值向输出散列表添加一个条目,该属性值是后面的部分这条着名的物业名称就行了。
    • 最后,将有序哈希表作为自定义对象输出,方法是将其转换为foreach

答案 1 :(得分:1)

从Powershell调用一个vbscript脚本只是感觉就像在Powershell中重写一样#34; (不要迟钝)。 @KoryGill提出了一个有趣的问题,"为什么不直接调用Get-Printer"?

但是,对于你的问题,你可以把它完全变成一个对象,但是你必须做一些文本操作:

$printer_stuff = $(cscript prnmngr.vbs -l)

这将创建一个名为$printer_stuff的字符串数组,其中每个元素都有一个单独的输出行。您将要为每个打印机属性创建一个令牌列表,例如服务器名称,打印机名称等。您将迭代输出(在字符串数组中)将属性复制到PSObject。这是一个便宜的例子来证明这一点:

## Make a list of tokens
$tokens = @('Server name', 'Printer name', 'Share name')

## This will be your printer object
$printer = New-Object -TypeName PSObject

## Parsing the string array and stuffing the good bits into your printer object
foreach ($thing in $printer_stuff[0..17]) {
    foreach ($token in $tokens) {
        if ($thing -match $token) {
            Add-Member -InputObject $printer -MemberType NoteProperty -Name $token -Value $thing.Replace($token, '')
        }
    }
}

## Here is your object...
$printer

如果prnmgr.vbs脚本将返回一堆打印机的信息,您可以将$printer对象填充到一个数组中:

$printers = @()
....
$printers += $printer

您可以使用类似......

之类的内容从字符串数组中提取每个打印机的数据
$min = 0
$max = $size
while ($min -lt $printer_stuff.length) {
    $printer_stuff[$min..$max]
    $min = $max + 1
    $max += $size
}

正如你所看到的,这对屁股来说是个巨大的痛苦,这就是为什么我建议只是在Powershell中重写这个东西。如果您足够灵活地执行此操作,那么您可以轻松移植vbscript脚本。

祝你好运, A -