0

的输出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

4

2 回答 2

1

Kory Gill建议改用 W8+ / W2K12+ Get-Printercmdlet

同样,kuujinbo建议Get-WmiObject -Class Win32_Printer使用较早的操作系统版本。

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


如果您仍然需要解析输出(如果它提供了引用的命令没有的额外信息),请使用以下方法 - 请注意将文本输出解析为结构化对象cscript prnmngr.vbs -l需要付出多少努力:

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

  • 维护一个知名属性名称的集合
  • 考虑value行上的属性名称之后的任何内容。

PSv3+ 解决方案:

# 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

使用您的示例输入,上面会产生一个 2 元素[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循环检查每一行是否包含感兴趣的属性,如果是,则向输出哈希表添加一个条目,其中包含输出属性名称和属性值,这是在线。
    • 最后,通过将有序哈希表转换为[pscustomobject].
于 2018-05-08T21:01:35.840 回答
1

从 Powershell 调用 vbscript-script 感觉就像“在 Powershell 中重写它之类的东西”(不要判断)。@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-

于 2018-05-08T21:07:16.720 回答