none
Сбор данных по сетевым принтерам RRS feed

  • Вопрос

  • Есть задача, опросить сервер печати на параметры расшаренных принтеров и далее проверить сетевые принтера по адресу.

    Ранее я использовал такой фрагмент кода

    <# $PSlists - файл, где лежит перечень серверов $IPList - список принтеров на сервере #> $IPList = Get-Printer -ComputerName $PSlists

    $IPlist.portname


    Но к сожалению подтягиваются все принтеры, не только расшаренные. По этому решил воспользоваться таким запросом

    $IPList = Get-WmiObject -Class Win32_TCPIPPrinterPort -computername $PSlists

    Все отлично, в переменную $IPList.hostaddress заносились все подключенные сетевые принтеры в офисе(их IP). Но при вызове 

    $Ping = Test-NetConnection $IPList.hostaddress

    Посыпались ошибки 

    Test-NetConnection : Не удается обработать преобразование аргументов для параметра "ComputerName". Не удается преобразовать значение в тип System.String.

    Я попытался изменить команду

     $IPList = Get-WmiObject -Class Win32_TCPIPPrinterPort -computername $PSlists | Out-String
     

    И полезла ошибка

    Resolve-DnsName : Не удается проверить аргумент для параметра "Name". Аргумент пустой или имеет значение NULL. Укажите непустой аргумент, не имеющий значение NULL, после чего повторите выполнение команды.

    При использовании такого кода, проблема осталась и текст ошибки не изменился

        $IPList = Get-WmiObject -Class Win32_TCPIPPrinterPort -computername $PSlists
        $IPList = [string] $IPList

    Понимаю что при выполнении 

    $IPList = Get-WmiObject -Class Win32_TCPIPPrinterPort -computername $PSlists

    Возникает проблема  типом данных, но вот как привести их в правильный вид не пойму. 


    4 декабря 2018 г. 14:29

Ответы

  • Мои комментарии начинаются с #?#
    $ReportDir = "\\SERVER\Report"
    $Date = Get-Date -UFormat "%d-%m-%Y"
    
    
    #СПИСОК СЕРВЕРОВ
    #?# Зачем вам CSV если вы не используете его функционал через Import-CSV ?
    $PSList =  @(Get-Content $ReportDir\PS_list.csv)	#список принтеров
    
    #?# Apple - яблоко (единственное число), apples - яблокИ (множественное число).
    #?# $PSlists - PS спискИ (единственное число как бы странно это не звучало)
    Foreach ($PSlists in $PSlist) {
    	#ЗАДАЕМ ПЕРЕМЕННЫЕ
        $IPList = Get-WmiObject -Class Win32_TCPIPPrinterPort -computername $PSlists
        #?# Предположу что $IPList может содержать более одного порта // У меня команда ничего не вернула
    
        #?# Зачем пересоздавать каталог столько раз сколько у вас серверов в списке? Вынесите команду в 3 строку
        New-Item -Path $ReportDir\LanPrinter -ItemType "directory" -ErrorAction SilentlyContinue | Out-Null
        Write-Host -ForegroundColor White -BackgroundColor DarkGreen "Сервер $PSlists"
        
        Foreach ($IPs in $IPList) {
    		#ОПРОС КАЖДОГО ПРИНТЕРА
            #?# Почему тут используете $IPList хотя это массив, а переменная в этом масиве называется $IPs?
    		$Ping = Test-NetConnection $IPList.hostaddress -ErrorAction Continue -WarningAction SilentlyContinue
            #?# Тоже самое тут: $($IPs.Name) но почему то $($IPList.hostaddress)
            $PingOK = "Принтер $($IPs.Name) ($($IPList.hostaddress)) ДОСТУПЕН" 
            #?#  -//-
            $PingFail = "!!! Принтер $($IPs.Name) ($($IPList.hostaddress)) НЕ ДОСТУПЕН"
    
    		if ($ping.PingSucceeded -eq "True") {
               Write-Host "$PingOK" -ForegroundColor Green
               $PingOK >> $ReportDir\LanPrinter\$Date.log
            }
    		else { 
    			Write-Host "$PingFail" -ForegroundColor Red -BackgroundColor Black
                $PingFAIL >> $ReportDir\LanPrinter\$Date.log
                $PingFAIL >> $ReportDir\LanPrinter\$Date_FAIL_$PSlists.log
            }
    	} 
    }
    PS Обратите внимание что преобразование типов я удалил так как оно не нужно

    The opinion expressed by me is not an official position of Microsoft


    4 декабря 2018 г. 21:00
    Модератор

Все ответы

  • Вы массив приводите к типу строка что не верно. Используйте foreach для перебора элементов масива и именно для них (элементов), по одному проверяйте доступность

    The opinion expressed by me is not an official position of Microsoft

    4 декабря 2018 г. 14:41
    Модератор
  • Я привел лишь кусок кода. Foreach я использую. Вот весь код

    $ReportDir = "\\SERVER\Report"
    $Date = Get-Date -UFormat "%d-%m-%Y"
    
    
    #СПИСОК СЕРВЕРОВ
    $PSList =  @(Get-Content $ReportDir\PS_list.csv)	#список принтеров
    
    Foreach ($PSlists in $PSlist) {
    	#ЗАДАЕМ ПЕРЕМЕННЫЕ
        $IPList = Get-WmiObject -Class Win32_TCPIPPrinterPort -computername $PSlists
        $IPList = [string] $IPList
    
        New-Item -Path $ReportDir\LanPrinter -ItemType "directory" -ErrorAction SilentlyContinue | Out-Null
        Write-Host -ForegroundColor White -BackgroundColor DarkGreen "Сервер $PSlists"
        
        Foreach ($IPs in $IPList) {
    		#ОПРОС КАЖДОГО ПРИНТЕРА
    		$Ping = Test-NetConnection $IPList.hostaddress -ErrorAction Continue -WarningAction SilentlyContinue
            $PingOK = "Принтер $($IPs.Name) ($($IPList.hostaddress)) ДОСТУПЕН" 
            $PingFail = "!!! Принтер $($IPs.Name) ($($IPList.hostaddress)) НЕ ДОСТУПЕН"
    
    		if ($ping.PingSucceeded -eq "True") {
               Write-Host "$PingOK" -ForegroundColor Green
               $PingOK >> $ReportDir\LanPrinter\$Date.log
               
            }
    		else { 
    			Write-Host "$PingFail" -ForegroundColor Red -BackgroundColor Black
                $PingFAIL >> $ReportDir\LanPrinter\$Date.log
                $PingFAIL >> $ReportDir\LanPrinter\$Date_FAIL_$PSlists.log
            }
    	} 
    }
           

    Проблема началась когда я захотел использовать 

    $IPList = Get-WmiObject -Class Win32_TCPIPPrinterPort -computername $PSlists

    Вместо

    $IPList = Get-Printer -ComputerName $PSlists

    4 декабря 2018 г. 14:49
  • Мои комментарии начинаются с #?#
    $ReportDir = "\\SERVER\Report"
    $Date = Get-Date -UFormat "%d-%m-%Y"
    
    
    #СПИСОК СЕРВЕРОВ
    #?# Зачем вам CSV если вы не используете его функционал через Import-CSV ?
    $PSList =  @(Get-Content $ReportDir\PS_list.csv)	#список принтеров
    
    #?# Apple - яблоко (единственное число), apples - яблокИ (множественное число).
    #?# $PSlists - PS спискИ (единственное число как бы странно это не звучало)
    Foreach ($PSlists in $PSlist) {
    	#ЗАДАЕМ ПЕРЕМЕННЫЕ
        $IPList = Get-WmiObject -Class Win32_TCPIPPrinterPort -computername $PSlists
        #?# Предположу что $IPList может содержать более одного порта // У меня команда ничего не вернула
    
        #?# Зачем пересоздавать каталог столько раз сколько у вас серверов в списке? Вынесите команду в 3 строку
        New-Item -Path $ReportDir\LanPrinter -ItemType "directory" -ErrorAction SilentlyContinue | Out-Null
        Write-Host -ForegroundColor White -BackgroundColor DarkGreen "Сервер $PSlists"
        
        Foreach ($IPs in $IPList) {
    		#ОПРОС КАЖДОГО ПРИНТЕРА
            #?# Почему тут используете $IPList хотя это массив, а переменная в этом масиве называется $IPs?
    		$Ping = Test-NetConnection $IPList.hostaddress -ErrorAction Continue -WarningAction SilentlyContinue
            #?# Тоже самое тут: $($IPs.Name) но почему то $($IPList.hostaddress)
            $PingOK = "Принтер $($IPs.Name) ($($IPList.hostaddress)) ДОСТУПЕН" 
            #?#  -//-
            $PingFail = "!!! Принтер $($IPs.Name) ($($IPList.hostaddress)) НЕ ДОСТУПЕН"
    
    		if ($ping.PingSucceeded -eq "True") {
               Write-Host "$PingOK" -ForegroundColor Green
               $PingOK >> $ReportDir\LanPrinter\$Date.log
            }
    		else { 
    			Write-Host "$PingFail" -ForegroundColor Red -BackgroundColor Black
                $PingFAIL >> $ReportDir\LanPrinter\$Date.log
                $PingFAIL >> $ReportDir\LanPrinter\$Date_FAIL_$PSlists.log
            }
    	} 
    }
    PS Обратите внимание что преобразование типов я удалил так как оно не нужно

    The opinion expressed by me is not an official position of Microsoft


    4 декабря 2018 г. 21:00
    Модератор
  • Михаил, как ваши успехи?

    The opinion expressed by me is not an official position of Microsoft

    5 декабря 2018 г. 19:05
    Модератор
  • Спасибо за рекомендации сверху. Я пока лишь осваиваю PoSh, по этом часто выбираю  нерациональные решения. На данный момент использую пару скриптов. 

    Первый

    <#
    	Опрашивает принтсерверы на наличие принтеров (имя, порт, драйвер)
        Выгрузка из AD
    
    	Отчет сохраняет в папку \\SERVER\PRINT\Report\
    #>
    
    $ReportDir = "\\SERVER\PRINT\Report"
    $ServerList = "\\SERVER\PRINT\PRINT\PS"
    
    
    #СПИСОК СЕРВЕРОВ
    $PSList =  @(Get-Content $ServerList\PS_list.csv)	#ПРИНТ
    
    
    
    
    Write-Host -ForegroundColor White -BackgroundColor Blue  "СБОР ИНФОРМАЦИИ ПО ПРИНТСЕРВЕРАМ"
    
    	
    
    Foreach ($PS in $PSlist)
    	{
    	#ПАПКА ДЛЯ ЛОГОВ
    	$Date = Get-Date -UFormat "%d-%m-%Y"
    	New-Item -Path $ReportDir\$PS -ItemType "directory" -ErrorAction SilentlyContinue | Out-Null
    	
        #СБОР ВСЕХ РАСШАРЕННЫХ ПРИНТЕРОВ
        Write-Host -ForegroundColor Cyan "`t[$PS]`tЗапрос данных"
    	$PServer = Get-Printer -ComputerName $PS -ErrorAction SilentlyContinue | ? published | Select-Object Name, Portname, DriverName
    	
        #ПИШЕМ ЛОГИ (csv, log)
    	$PServer | Export-Csv $ReportDir\$PS\Printers_$Date.csv
    	$PServer | Format-table > $ReportDir\$PS\Printers_$Date.log
    
    
        $ServerInfo = "		$PS" >> $ReportDir\PortPrinters_$Date.log
        $ServerInfo = "══════════════════════════════════════" >> $ReportDir\PortPrinters_$Date.log
        
        Foreach ($Printer in $PServer) {
    	    $PrinterIP = "$($Printer.portname)" 
            $PrinterName = "$($Printer.Name)"
            $PrinterReport = "$PrinterName`t·······`t$PrinterIP" >> $ReportDir\PortPrinters_$Date.log
    	} 
        $ServerInfo = "`n" >> $ReportDir\PortPrinters_$Date.log
    }
    
    
    Write-Host -ForegroundColor White -BackgroundColor Blue  "ВЫГРУЗКА ПРИНТЕРОВ ИЗ AD"
    
    #ВЫГРУЗКА ВСЕХ ПРИНТЕРОВ ИЗ AD
    Write-Host -ForegroundColor Cyan "[AD] `tВыгрузка всех принтеров`n"
    Get-AdObject -filter {ObjectClass -eq "printQueue"} -SearchScope Subtree > $ReportDir\AD_PRINT_$date.csv
    Write-Host -ForegroundColor Cyan "[AD] `tВыгрузка сервер-принтер`n"
    Get-AdObject -filter "objectCategory -eq 'printqueue'" -Prop *| Select ServerName, @{N='ShareNames';E={$_.printShareName -join ';'}} | Format-Table -Wrap -AutoSize > $ReportDir\PRINTERS_$date.log
    
    
    Write-Host -ForegroundColor Yellow -BackgroundColor DarkBlue "Отчёт по всем серверам:`t$ReportDir	"
    ii $ReportDir

    И есть чуть сложнее, взял кусок чужого готового кода и чуть подправил под свои нужды. Выгрузка происходит в удобную таблицу:

    #СПИСОК СЕРВЕРОВ
    
    $PSList =  @(Get-Content \server\folder\PS_list.csv)
    
    # Create new Excel workbook
    $Excel = New-Object -ComObject Excel.Application
    $Excel.Visible = $True
    $Excel = $Excel.Workbooks.Add()
    $Sheet = $Excel.Worksheets.Item(1)
    $Sheet.Name = "Printer Inventory"
    #======================================================
    $Sheet.Cells.Item(1,1) = "Print Server"
    $Sheet.Cells.Item(1,2) = "Printer Name"
    $Sheet.Cells.Item(1,3) = "IP Address"
    $Sheet.Cells.Item(1,4) = "Driver Name"
    $Sheet.Cells.Item(1,5) = "Driver Version"
    $Sheet.Cells.Item(1,6) = "Driver"
    #=======================================================
    $intRow = 2
    $WorkBook = $Sheet.UsedRange
    $WorkBook.Interior.ColorIndex = 40
    $WorkBook.Font.ColorIndex = 11
    $WorkBook.Font.Bold = $True
    #=======================================================
    
    # Get printer information
    ForEach ($PrintServer in $PSList)
    {   Write-Verbose "$(Get-Date): Working on $PrintServer..."
        $Printers = Get-WmiObject Win32_Printer -ComputerName $PrintServer
        ForEach ($Printer in $Printers)
        {
            If ($Printer.Name -notlike "Microsoft XPS*")
            {   $Sheet.Cells.Item($intRow, 1) = $PrintServer
                $Sheet.Cells.Item($intRow, 2) = $Printer.Name
    
                
                If ($Printer.PortName -notlike "*\*")
                {   $Ports = Get-WmiObject Win32_TcpIpPrinterPort -Filter "name = '$($Printer.Portname)'" -ComputerName $Printserver
                    ForEach ($Port in $Ports)
                    {
                        $Sheet.Cells.Item($intRow, 3) = $Port.HostAddress
                    }
                }
           
                ####################       
                $Drivers = Get-WmiObject Win32_PrinterDriver -Filter "__path like '%$($Printer.DriverName)%'" -ComputerName $Printserver
                ForEach ($Driver in $Drivers)
                {   $Drive = $Driver.DriverPath.Substring(0,1)
                    $Sheet.Cells.Item($intRow, 5) = (Get-ItemProperty ($Driver.DriverPath.Replace("$Drive`:","\\$PrintServer\$Drive`$"))).VersionInfo.ProductVersion
                    $Sheet.Cells.Item($intRow,6) = Split-Path $Driver.DriverPath -Leaf
                }
                ####################      
                $Sheet.Cells.Item($intRow, 4) = $Printer.DriverName
                $intRow ++
            }
        }
        $WorkBook.EntireColumn.AutoFit() | Out-Null
    }
     
    
    


    24 декабря 2018 г. 8:33