如何将 prnmngr 的输出转换为自定义对象?
How can i convert the output of prnmngr into custom object?
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
表示 属性 在 [=12 的输出上循环的值=]
Kory Gill helpfully suggests using the W8+ / W2K12+ Get-Printer
cmdlet 代替。
同样,kuujinbo 建议 Get-WmiObject -Class Win32_Printer
早期 OS 版本。
本着 PowerShell 的精神,这两个命令 returns objects 您可以直接访问其 properties - 无需 文本解析.
如果您仍然需要解析 cscript prnmngr.vbs -l
的输出(如果它提供了引用的命令没有提供的额外信息),请使用以下方法 - 注意解析需要多少努力文本输出到结构化对象:
鉴于所有信息都是space分隔的,每行的属性 name部分由varying[=组成71=] 个标记,唯一可预测的解析文本的方法是:
- 维护着名的 属性 名字
- 考虑 行上的 属性 名称 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] @{}
初始化一个空的 ordered 哈希表(其中条目反映在输出的定义顺序中)作为创建自定义对象的基础。
- 内部
foreach
循环然后检查每一行是否包含感兴趣的 属性,如果是,则向输出哈希表添加一个条目,输出 属性 名称和属性 值,即行中众所周知的 属性 名称之后的部分。
- 最后,将有序哈希表转换为
[pscustomobject]
。 将其输出为自定义对象
从 Powershell 调用 vbscript-script 感觉就像 "re-write it in Powershell sort of thing"(不要评判)。 @KoryGill 问了一个有趣的问题,"Why not just call 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-
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
表示 属性 在 [=12 的输出上循环的值=]
Kory Gill helpfully suggests using the W8+ / W2K12+ Get-Printer
cmdlet 代替。
同样,kuujinbo 建议 Get-WmiObject -Class Win32_Printer
早期 OS 版本。
本着 PowerShell 的精神,这两个命令 returns objects 您可以直接访问其 properties - 无需 文本解析.
如果您仍然需要解析 cscript prnmngr.vbs -l
的输出(如果它提供了引用的命令没有提供的额外信息),请使用以下方法 - 注意解析需要多少努力文本输出到结构化对象:
鉴于所有信息都是space分隔的,每行的属性 name部分由varying[=组成71=] 个标记,唯一可预测的解析文本的方法是:
- 维护着名的 属性 名字
- 考虑 行上的 属性 名称 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] @{}
初始化一个空的 ordered 哈希表(其中条目反映在输出的定义顺序中)作为创建自定义对象的基础。- 内部
foreach
循环然后检查每一行是否包含感兴趣的 属性,如果是,则向输出哈希表添加一个条目,输出 属性 名称和属性 值,即行中众所周知的 属性 名称之后的部分。 - 最后,将有序哈希表转换为
[pscustomobject]
。 将其输出为自定义对象
从 Powershell 调用 vbscript-script 感觉就像 "re-write it in Powershell sort of thing"(不要评判)。 @KoryGill 问了一个有趣的问题,"Why not just call 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-