Как я могу преобразовать вывод prnmngr в пользовательский объект?

вывод 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


person munish    schedule 08.05.2018    source источник
comment
Почему бы просто не вызвать Get-Printer?   -  person Kory Gill    schedule 08.05.2018
comment
Многие люди в SO считают идеальным то, что установки Windows 7 по всему миру незначительны. Не так — здесь и здесь, например. Командлет get-printer доступен только в Windows 8. Если вы работаете в Windows 7: Get-WmiObject -Class Win32_Printer предоставляет набор объектов способом PowerShell.   -  person kuujinbo    schedule 09.05.2018


Ответы (2)


Кори Гилл услужливо предлагает использовать W8+/W2K12+ Get-Printer cmdlet.

Точно так же kuujinbo предлагает Get-WmiObject -Class Win32_Printer для более ранних версий ОС.

В духе PowerShell обе команды возвращают объекты, к свойствам которых можно получить прямой доступ — нет необходимости в анализе текста.


В случае, если вам все еще нужно проанализировать вывод из cscript prnmngr.vbs -l (если он предоставляет дополнительную информацию, которой нет в приведенных командах), используйте следующий подход — обратите внимание, сколько усилий требуется для анализа текстового вывода. в структурированные объекты:

Учитывая, что вся информация разделена пробелами, а часть свойства name каждой строки состоит из различных количеств токенов, единственный предсказуемый способ анализа текста:

  • поддерживать коллекцию известных свойств названия
  • рассматривайте все, что идет после имени свойства в строке значение.

Решение для 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

С вашим образцом ввода приведенное выше дает двухэлементный массив [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") splits the multiline paragraph back into an array of lines and loops over them.
    • $ohtFields = [ordered] @{} инициализирует пустую упорядоченную хеш-таблицу (где записи отображаются в порядке определения на выходе), которая служит основой для создания пользовательского объекта.
    • Затем внутренний цикл foreach проверяет каждую строку на наличие интересующего свойства и, если это так, добавляет запись в выходную хеш-таблицу с именем выходного свойства и значением свойства, которое следует за хорошо известным именем свойства на линия.
    • Наконец, упорядоченная хеш-таблица выводится как пользовательский объект путем приведения его к [pscustomobject].
person mklement0    schedule 08.05.2018

Вызов vbscript-скрипта из Powershell просто похож на «переписывание его в 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-script.

Удачи, А-

person Adam    schedule 08.05.2018