Получение версии драйвера принтера вместе с именем принтера в PowerShell - PullRequest
0 голосов
/ 04 февраля 2020

Здравствуйте:)

Надеюсь, у вас все хорошо сегодня.

Что ж, меня попросили достать отчет обо всех наших принтерах и версии драйверов, которые они используют (подробнее более 1300 принтеров по всему миру и более 150 хостов).

На этом этапе я могу получить большую часть необходимой мне информации.

Вот код на данный момент:

$ReportFileName = "c:\SAC_IS\printerreport.csv" 
$PrintServersList="C:\SAC_IS\servlist_TEST.txt" 

$servers =  Get-Content -Path $PrintServersList 
$allprinters = @() 
foreach( $server in $servers ){ 
Write-Host "checking $server ..." 
$printers = $null 
$printers = Get-WmiObject -class Win32_Printer -computername $server | select Name,Shared,ShareName,Local, DriverName, PortName, @{n="HostName";e={$server}} ,@{n="Driver Version";e={Get-WmiObject Win32_PrinterDriver -ComputerName $server | select @{n="Version";e={(Get-Item $_.DriverPath).VersionInfo.ProductVersion}}}}, Location,Comment,SpoolEnabled,Published
$allprinters += $printers 
 } 

$allprinters | Export-CSV -Path $ReportFileName -Delimiter ";" -NoTypeInformation -Force -Encoding UTF8 

Моя проблема здесь в том, что я не могу получить версию драйвера, которую использует принтер:

CSV Output

Выполнение скрипта вообще не возвращает ошибок: /

Можно ли подать руку, пожалуйста? : D

Вспомогательный вопрос, почему, черт возьми, это занимает около 5 минут на хоста. Разве это не может быть быстрее?

Большое спасибо всем, кто может помочь:)

Ответы [ 2 ]

1 голос
/ 04 февраля 2020

Вероятно, главное в вашем коде состоит в том, что, хотя вы работаете на удаленных машинах, вы используете local DriverPath для получения версии драйвера, а также не указываете драйвер, на который вы нацелены.

Приведенный ниже код использует небольшую вспомогательную функцию для получения версии драйвера из фактического файла драйвера на сервере, используя путь UN C вместо локального пути. Кроме того, я думаю, что использование здесь функции может сделать код более читабельным.

Чтобы попытаться ускорить процесс, я использую Get-CimInstance вместо Get-WmiObject и собираю объекты без добавления в предопределенные массив:

$ReportFileName   = 'C:\SAC_IS\printerreport.csv' 
$PrintServersList = 'C:\SAC_IS\servlist_TEST.txt' 

function Get-PrinterProductVersion ($server, $printer) {
    $prn = Get-CimInstance -ClassName Win32_PrinterDriver -ComputerName $server | 
           Where-Object { ($_.Name -split ',')[0] -eq $($printer.DriverName) }
    if ($prn) { 
        # transform the local driver path into a UNC path
        $path = Join-Path -Path "\\$server" -ChildPath ($prn.DriverPath -replace ':', '$')
        (Get-Item $path).VersionInfo.ProductVersion 
    }
}

$allprinters = Get-Content -Path $PrintServersList | ForEach-Object {
    # capture the server name in a self-defined variable
    $server = $_
    Write-Host "checking server $server ..." 
    Get-CimInstance -ClassName Win32_Printer -ComputerName $server | 
        Select-Object Name,Shared,ShareName,Local,DriverName,PortName, 
                      @{Name = "HostName"; Expression = { $server }},
                      @{Name = "Driver Version"; Expression = { Get-PrinterProductVersion $server $_ }}, 
                      Location,Comment,SpoolEnabled,Published
 } 

# output on screen
$allprinters

# output to CSV file
$allprinters | Export-CSV -Path $ReportFileName -Delimiter ";" -NoTypeInformation -Force -Encoding UTF8 

PS Лично я не хотел бы заголовок с пробелом в его имени, как "Driver Version", но это зависит от вас


Редактировать

Я не могу проверить это сам, но, возможно, вы можете ускорить это, если вы позволите серверам собирать необходимую информацию о принтере.

Примерно так:

$ReportFileName   = 'C:\SAC_IS\printerreport.csv' 
$PrintServersList = 'C:\SAC_IS\servlist_TEST.txt' 

# create a scriptblock for each server to execute
$scriptBlock = {
    function Get-PrinterProductVersion ($printer) {
        # or try with 'Get-WmiObject -Class Win32_PrinterDriver' if Get-CimInstance not available
        $prn = Get-CimInstance -ClassName Win32_PrinterDriver | 
               Where-Object { ($_.Name -split ',')[0] -eq $($printer.DriverName) }
        if ($prn) { (Get-Item $prn.DriverPath).VersionInfo.ProductVersion }
    }

    # or try with 'Get-WmiObject -Class Win32_Printer' if Get-CimInstance not available
    Get-CimInstance -ClassName Win32_Printer | 
        Select-Object Name,Shared,ShareName,Local,DriverName,PortName, 
                      @{Name = "HostName"; Expression = { $env:COMPUTERNAME }},
                      @{Name = "Driver Version"; Expression = { Get-PrinterProductVersion $_ }}, 
                      Location,Comment,SpoolEnabled,Published


}

# create a list to gather all results from the servers
$allprinters = New-Object System.Collections.Generic.List[object]

Get-Content -Path $PrintServersList | ForEach-Object {
    Write-Host "checking server $_ ..." 
    if (Test-Connection -ComputerName $_ -Count 1 -Quiet) {
        $printers = Invoke-Command -ScriptBlock $scriptBlock -ComputerName $_
        $allprinters.AddRange($printers)
    }
    else {
        Write-Warning "Server $_ cannot be reached"
    }
 } 

# output on screen
$allprinters

# output to CSV file
$allprinters | Export-CSV -Path $ReportFileName -Delimiter ";" -NoTypeInformation -Force -Encoding UTF8 
1 голос
/ 04 февраля 2020

Попробовать так?

$servers | ForEach-Object {
    $CurrentServer = $_
    Write-Host "Checking $CurrentServer_ ..." 
    $Drivers = Get-PrinterDriver -ComputerName $CurrentServer | Select-Object Name, @{n="DriverVersion";e={ $ver = $_.DriverVersion;(3..0 | ForEach-Object { ($ver -shr ($_ * 16)) -band 0xffff }) -join '.'}}

    Get-WmiObject -class Win32_Printer -Computername $CurrentServer | ForEach-Object {
        $ThisPrintDriverName = $_.DriverName
        $ThisDriver = $Drivers | Where-Object { $_.Name -eq $ThisPrintDriverName }

        [pscustomobject]@{Name = $_.Name
                        Shared = $_.Shared
                        ShareName = $_.ShareName
                        Local = $_.Local
                        DriverName = $_.DriverName
                        PortName = $_.PortName
                        HostName = $CurrentServer
                        Location = $_.Location
                        Comment = $_.Comment
                        SpoolEnabled = $_.SpoolEnabled
                        Published = $_.Published
                        Driver = $ThisDriver.Name
                        Version = $ThisDriver.DriverVersion
                        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...