PowerShell
10 November 2014

Автоматическое подключение сетевых МФУ с возможностью сканирования [Часть 2]

Kyocera M2035dn, Xerox WorkCentre 3615 и 6505DN


Как и обещал в первой части, за которую я успешно получил инвайт в песочнице, в этой заметке я покажу как подключить сетевые МФУ Kyocera M2035dn, Xerox WorkCentre 3615 и 6505DN, а в конце статьи добавлю небольшой бонус с которым любой скрипт связанный с сетью становится лучше.



Как бы небыли прекрасны гомогенные инфраструктуры, пусть даже в части принтеров и мфу, реальность зачастую ставит свои условия. В то время как пользователи сами в полный рост подключали и успешно сканировали с некогда проблемных МФУ HP, в компанию приехал японский гость — Kyocera M2035dn.

Kyocera M2035dn


Приехал как всегда не в мое уютное админское логово, а сразу на объект и как и мфу от HP, в глаза его я, если честно, даже не видел.
Первым делом качаем драйвер и смотрим содержимое… ба, знакомые все люди:



Есть пометка о том, что подключение сетевое (network) и есть ID!
Попробуем подключить сканер через devcon, подобно тому как мы подключали МФУ от HP в первой части:
.\devcon.exe /r install C:\Drivers\Scanners\2035dnscan\kmwiadrv.inf "KM_WC_ECOSYS_M2035dn_N_WIA"

Сканер подключился, прописываем в реестр адрес сканера параметром ScannerAddress и запускаем сканирование. Приложение сканирования показало отсканированный лист, все работает отлично. Казалось бы победа, но запуск второй, используемой у нас программы для сканирования, поубавил радости — сканер в ней не отображался.



Оказывается разработчики Kyocera почему-то в драйвере реализовали сканирование только через WIA, для TWAIN надо ставить отдельный косты.. враппер, который пробрасывает TWAIN интерфейс в WIA и возвращает обратно результат. Выглядит гуй этого TWAIN драйвера следующим образом:



При этом, по WIA мы можем подключить несколько сканеров Kyocera, в то время как TWAIN интерфейс у нас будет всегда только один. Либо пользуйтесь WIA, либо каждый раз запускайте нашу утилиту и переключайте сканер. Придется смириться, а пока посмотрим как нам обойти запуск этой утилиты на машине пользователя.
Утилита хранит настройки в ini-файлах, по одному файлу KM_TWAIN*.ini на каждый сетевой сканер и один результирующий файл с описанием сканеров и файлов их настроек.
Скрин обоих файлов, для одного подключенного сканера:



Теперь установка видится следующей:
— подключаем сканер через devcon
— если утилита TWAIN не установлена, ставим её
— добавляем адрес сканера в реестр
— проходимся по реестру в поиске подключенных сканеров Kyocera и на основе данных в реестре генерируем ini-файлы

Расширим функцию подключения сканера из предыдущей заметки следующим кодом, который я постарался по-максимуму прокомментировать:

# знакомый нам участок кода с подключением через devcon
"M2035dn" {
    Push-Location 'C:\Drivers\Scanners\ip\2035dnscan\'
    if ($(Get-Platform) -eq "Windows x64") {
        .\devconx64.exe /r install $dest\kmwiadrv.inf "KM_WC_ECOSYS_M2035dn_N_WIA"
    } else {
        .\devcon.exe /r install $dest\kmwiadrv.inf "KM_WC_ECOSYS_M2035dn_N_WIA"
    }
    Pop-Location

    # проверяем стоит ли костыль kyocera, если нет ставим в тихом режиме
    $twain = Get-WMIObject -Class Win32_Product -Filter 'Name = "Kyocera TWAIN Driver"'
    if (!($twain)) {
        Push-Location 'C:\Drivers\Scanners\2035dnscan\TWAIN'
        .\setup.exe /S /v /qn
        Pop-Location
    }

    # получаем содержимое ветки реестра в которой хранятся настройки сканеров и камер
    $scanclass = 'HKLM:\SYSTEM\CurrentControlSet\Control\Class\{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}'

    # так как мы только что поставили новый сканер, то его номер будет последним среди сканеров
    $item = (Get-ChildItem $scanclass | Where-Object Name -match "\d{4}$" | Select -Last 1).PSChildName

    # добавляем адрес сканера
    New-ItemProperty "$scanclass\$item\DeviceData" -Name "ScannerAddress" -Value $ipaddress | Out-Null

    # тут применил расширенный синтаксис Foreach-Object, состоящий из трех частей
    # первая и последняя выполняются по одному разу, при запуске цикла и его окончании соответственно;
    # код в секции process выполняется для каждого элемента цикла
    Get-ChildItem  $scanclass | Foreach-Object -Begin {
        $count = 0
        Add-Type -As System.Web
        # стандартный пароль, который задает утилита
        $pass = '43srWkUjR/8='
        $scanitem = @{}
        $filelist = @()
    } -Process {
        $path = $_.Name -replace 'HKEY_LOCAL_MACHINE', 'HKLM:'
        $prop = Get-ItemProperty $path
        if ($prop.Vendor -eq 'Kyocera') {
            $count ++
            $twfilename = "KM_TWAIN$count`.INI"
            $devicedata = Get-ItemProperty "$path\DeviceData"
            $cont = @{'Unit'='0';'ScannerAddress'=$devicedata.ScannerAddress; 'SSL'='0'}
            $auth = @{'Auth'='0';'UserName'=''; 'Account'='0'; 'ID'='';'Password'=$pass}
            $twcont = @{'Contents'=$cont; 'Authentication'=$auth}
            Out-IniFile -inputobject $twcont -FilePath "$env:temp\$twfilename"
            $filelist += , "$env:temp\$twfilename"

            $devicename = $devicedata.'Model Name' + " #$count"
            $modelname = $devicedata.'Model Name'
            $scanreg = @{'Name'=$devicename;'Model'=$modelname;'DefFile'=$twfilename;'LastScan'='';'ScanList'='';'Pos'=($count-1)}
            $scanitem.Add("Scanner$count", $scanreg)
        }
    } -End {
        $regfilename = 'RegList.ini'
        $settings = @{'Type'='4'; 'DefaultUse'=$count;'RegNum'=$count;}
        $reglist = @{'Setting'=$settings}
        $reglist += $scanitem
        Out-IniFile -inputobject $reglist -FilePath "$env:temp\$regfilename"
        $filelist += , "$env:temp\$regfilename"
    }

    # удаляем предыдущие ini-файлы и подкладываем сгенерированные выше с новым сканером
    Get-ChildItem $env:systemdrive\users -Directory -Recurse -Include 'appdata' -Force | ForEach-Object {
        $kyodir = $_.FullName + "\Roaming\Kyocera\KM_TWAIN"
        If (!(Test-Path $kyodir)) {
            New-Item -Type Directory -Path $kyodir
        } else {
            Remove-Item "$kyodir\*" -Recurse
        }
        $filelist | ForEach-Object {
            Copy-Item $_ $kyodir -Force | Out-Null
        }
    }
}

В скрипте я использовал функцию вывода хэш-таблицы в ini-файл, вот её код:

function Out-IniFile($inputobject, $filepath) {
    # .Example
    # $Category1 = @{'Key1'='Value1';'Key2'='Value2'}
    # $Category2 = @{'Key1'='Value1';'Key2'='Value2'}
    # $NewINIContent = @{'Category1'=$Category1;'Category2'=$Category2}
    # Out-IniFile -inputobject $NewINIContent -FilePath 'C:\MyNewFile.INI'

    $outfile = New-Item -ItemType File -Path $filepath -Force
    foreach ($i in $inputobject.keys) {
        Add-Content -Path $outfile -Value "[$i]"
        Foreach ($j in ($inputobject[$i].keys | Sort-Object)) {
            Add-Content -Path $outfile -Value "$j=$($inputobject[$i][$j])"
        }
        Add-Content -Path $outfile -Value ''
    }
}


Xerox WorkCentre 3615 и 6505DN


Код этот успешно работал и проблем с ним не возникало, наверное, на протяжении полугода пока ветер опять не подул в другую сторону. В сторону Xerox.
В аутлук упало письмо с ip-адресами двух новых мфу, WorkCentre 3615 и WorkCentre 6505DN. Дорога хода мыслей при знакомстве с новым мфу уже проторена, открываем драйвер и видим знакомое:



И настроение мое улучшилось©

Распаковываем драйвер, запускаем консоль, выполняем:
.\devcon.exe /r install C:\Drivers\Scanners\xx3615\xrszdim.inf "NON_PNP&WorkCentre3615"

Сканер подключился и на экран выскочил новый, как это принято говорить, воркэраунд, только уже от разработчиков Xerox:



Очередная странная утилита от авторов драйвера для прописывания IP, причем запускается она из драйвера при установке. Значит, для того что бы спрятать ее от пользователя, будем прибивать ее в скрипте, в общем-то не беда.

Сейчас покажу на примере 3615, как расширить функцию подключения сканера. От 6506DN она практически не отличается, разве что другое имя файла драйвера и ID:

"3615" {
    Push-Location 'C:\Drivers\Scanners\xx3615\'
    if ($(Get-Platform) -eq "Windows x64") {
        .\devconx64.exe /r install C:\Drivers\Scanners\xx3615\xrszdim.inf "NON_PNP&WorkCentre3615"
    } else {
        .\devcon.exe /r install C:\Drivers\Scanners\xx3615\xrszdim.inf "NON_PNP&WorkCentre3615"
    }
    Pop-Location
    
    Get-Process "AIOScanSettings" | Stop-Process -Force

    # не могу вразумительно ответить почему я тут применил reg add,
    # спишем на ностальгию по cmd, а замену на New-ItemProperty оставим домашкою читателю
    &rеg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "EnableEnhancedBW" /t REG_DWORD /d 1 /f
    &rеg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "ISO_B_Series" /t REG_DWORD /d 1 /f
    &rеg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "IP Address" /t REG_SZ /d $ipAddress /f
 
}


Теперь мы умеем подключать целый зоопарк сетевых мфу и совершенно ничего не боимся, осталось добавить какой-нибудь магии… магии snmp!

Ищем МФУ в сети по snmp


SNMP (англ. Simple Network Management Protocol — простой протокол сетевого управления) — стандартный интернет-протокол для управления устройствами в IP-сетях на основе архитектур TCP/UDP.
ru.wikipedia.org/wiki/SNMP


Для работы с snmp из powershell я в скрипте использовал открытую библиотеку sharpsnmp, подробнее о ее использовании можно почитать по адресу: vwiki.co.uk/SNMP_and_PowerShell
После подключения библиотеки получение информации сводится к вызову функции Invoke-SNMPget с указанием Ip и uid, последний из которых легко гуглится.
Пример из кода:
Invoke-SNMPget $ip .1.3.6.1.2.1.25.3.2.1.3.1

Результат работы поиска выводим на экран, о том как это сделать в одну комманду чуть ниже:



Остается выделить нужный принтер и нажать OK, кстати множественное выделение так же возможно, в этом случае подключатся все выделенные принтеры.
Эту удобную гуёвую магию обеспечивает командлет Out-GridView, отображающий любые переданные в него объекты. При вызове с параметром PassThru, после нажатия OK он передаст дальше по конвейеру выбранные объекты, нам остается только по очереди вызвать наши функции установки драйверов с параметрами пришедшими в объекте из конвейера.

В упрощенном виде скрипт примет вид:
$hosts | Out-GridView -Title "Выберите принтеры для установки" -PassThru | Foreach-Object {
        $printername = $_.Name
        $printersource = $_.Source

        switch -regex ($printername) {
            "xerox.+3615" {
                $modelname = "Xerox WorkCentre 6505DN PCL 6"
                $driverpath = 'C:\Drivers\Scanners\xx6505\xrxmozi.inf'
            }
        }

        Write-Host "Добавляется порт IP принтера $printerName"
        Add-PrinterPort $modelname $printersource

        Write-Host "Добавляется драйвер принтера $printername"
        Add-PrinterDriver $modelname $driverpath

        Write-Host "Добавляется сканер принтера $printername"
        Add-Scanner $printersource $modelname 
    }


В процессе изучения откликов принтеров, столкнулся с тем, что принтеры отдают порой имя отличающееся от имени прописанного в драйвере, для обхода этой особенности добавил в скрипт простой свитч с регулярками, которые никогда не промахиваются и как мы знаем полны по Тьюрингу ;-)

switch -regex ($printername) {
    "hp.+305\d" {
        $modelName = "HP LaserJet 3050 Series PCL 6"
    }
    "hp.+3390" {
        $modelName = "HP LaserJet 3390 Series PCL 6"
    }
    "xerox.+3615" {
        $modelName = "Xerox WorkCentre 3615 PCL6"
    }
    "xerox.+650[0,5]DN" {
        $modelName = "Xerox WorkCentre 6505DN PCL 6"
    }
}


Полный код готового скрипта поиска и подключения сетевого принтера
$ErrorActionPreference = "silentlycontinue"

function Main {

	# путь к драйверам
	$driversdistrib = 'C:\Drivers\'

	# загружаем snmp либу
	$snmplibpath = Join-Path (Get-Location).path "\SharpSnmpLib.dll"
	if (Test-Path $snmplibpath) {
		[reflection.assembly]::LoadFrom((Resolve-Path $snmplibpath))
	} else {
		Write-Host "Не удалось найти SharpSnmpLib"
		Exit
	}

	# вычисляем подсеть, без хитрой математики, в лоб и только /24
	$network = (Get-IPaddress).ToString() -replace "\.[0-9]{1,3}$"

	# в диапазоне закрепленном за принтерами ищем устройства
	$hosts = 10..40 | ForEach-Object {
		$ip = "$network.$_"
		$snmpanswer= $null
		$snmpanswer = Invoke-SNMPget $ip .1.3.6.1.2.1.25.3.2.1.3.1
		if ($snmpanswer) {
			# формируем объект с двумя свойствами который улетит в переменную $hosts
			[pscustomobject]@{
				Name = $snmpanswer.Data;
				Source = $ip;
			}
		}
	}

	# выводим объекты в гуй с параметром PassThru, который передаст выбранные дальше по конвейеру
	$hosts | Out-GridView -Title "Выберите принтеры для установки" -PassThru | Foreach-Object {
		$printername = $_.Name
		$printersource = $_.Source

		switch -regex ($printername) {
			"hp.+305\d" {
				$printername = "HP LaserJet 3050 Series PCL 6"
				$driverpath = Join-Path $driversdistrib 'Printers\3050\hppcp601.inf'
			}
			"hp.+3390" {
				$printername = "HP LaserJet 3390 Series PCL 6"
				$driverpath = Join-Path $driversdistrib 'Printers\3050\hppcp601.inf'
			}
			"hp.+153[0,6]" {
				$printername = "HP LaserJet M1530 MFP Series PCL 6"
				$driverpath = Join-Path $driversdistrib 'Printers\1530\hpc1530c.inf'
			}
			"hp.+1522" {
				$printername = "HP LaserJet M1522 MFP Series PCL 6"
				$driverpath = Join-Path $driversdistrib 'Printers\1522\hppcp608.inf'
			}
			"M2035dn" {
				$printername = "Kyocera ECOSYS M2035dn KX"
				$driverpath = Join-Path $driversdistrib 'Printers\2035dn\OEMSETUP.INF'
			}			
			"xerox.+3615" {
				$printername = "Xerox WorkCentre 3615 PCL6"
				$driverpath = Join-Path $driversdistrib 'Scanners\xx3615\x2GPROX.inf'
			}
			"xerox.+650[0,5]DN" {
				$printername = "Xerox WorkCentre 6505DN PCL 6"
				$driverpath = Join-Path $driversdistrib 'Scanners\xx6505\xrxmozi.inf'
			}
		}

		Write-Host "Добавляется порт IP принтера $printerName"
		Add-PrinterPort $printername $printersource

		Write-Host "Добавляется драйвер принтера $printername"
		Add-PrinterDriver $printername  $driverpath

		Write-Host "Добавляется сканер принтера $printername"
		Add-Scanner $printersource $printername
	}
}
function Add-PrinterPort ($printersource) {
	&cscript C:\Windows\System32\Printing_Admin_Scripts\ru-RU\prnport.vbs `
	-a -r $printersource -h $printersource -o RAW -n 9100 | Out-Null
}
function Add-PrinterDriver ($printerName, $driverpath) {
	$folder = Split-Path $driverpath
	cscript C:\Windows\System32\Printing_Admin_Scripts\ru-RU\prndrvr.vbs `
	-a -m $printerName -e Get-Platform -h $folder -i $driverpath
}
function Add-Scanner ($ipaddress, $printername) {
	switch -regex ($printername) {
		"1530" {
			Push-Location (Join-Path $driversdistrib 'Scanners\1536scan\')
			if ($(Get-Platform) -eq "Windows x64") {
				.\hppniscan64.exe -f "hppasc16.inf" -m "vid_03f0&pid_012a&IP_SCAN" -a $ipAddress -n 1
			} else {
				.\hppniscan01.exe -f "hppasc16.inf" -m "vid_03f0&pid_012a&IP_SCAN" -a $ipAddress -n 1
			}
			Pop-Location
		}
		"(305\d)|(3390)" {
			Push-Location (Join-Path $driversdistrib 'Scanners\3055scan\')
			switch -regex ($printername) {
				"3050" {
					.\hppniscan01.exe -f "hppasc01.inf" -m "vid_03f0&pid_3217&IP_SCAN" -a $ipAddress -n 1
				}
				"3052" {
					.\hppniscan01.exe -f "hppasc01.inf" -m "vid_03f0&pid_3317&IP_SCAN" -a $ipAddress -n 1
				}
				"3055" {
					.\hppniscan01.exe -f "hppasc01.inf" -m "vid_03f0&pid_3417&IP_SCAN" -a $ipAddress -n 1
				}
				"3390" {
					.\hppniscan01.exe -f "hppasc01.inf" -m "vid_03f0&pid_3517&IP_SCAN" -a $ipAddress -n 1
				}
			}
			Pop-Location
		}
		"1522" {
			Push-Location (Join-Path $driversdistrib 'Scanners\1522scan\')
			if ($(Get-Platform) -eq "Windows x64") {
				.\hppniscan64.exe -f "hppasc08.inf" -m "vid_03f0&pid_4517&IP_SCAN" -a $ipAddress -n 1
			} else {
				.\hppniscan01.exe -f "hppasc08.inf" -m "vid_03f0&pid_4517&IP_SCAN" -a $ipAddress -n 1
			}
			Pop-Location
		}
		"M2035dn" {
			Push-Location (Join-Path $driversdistrib 'Scanners\2035dnscan\')
			if ($(Get-Platform) -eq "Windows x64") {
				.\devconx64.exe /r install $dest\kmwiadrv.inf "KM_WC_ECOSYS_M2035dn_N_WIA"
			} else {
				.\devcon.exe /r install $dest\kmwiadrv.inf "KM_WC_ECOSYS_M2035dn_N_WIA"
			}
			Pop-Location

			$twain = Get-WMIObject -Class Win32_Product -Filter 'Name = "Kyocera TWAIN Driver"'
			if (!($twain)) {
				Push-Location (Join-Path $driversdistrib 'Scanners\2035dnscan\TWAIN')
				.\setup.exe /S /v /qn
				Pop-Location
			}

			$scanclass = 'HKLM:\SYSTEM\CurrentControlSet\Control\Class\{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}'
			$item = (Get-ChildItem $scanclass | Where-Object Name -match "\d{4}$" | Select -Last 1).PSChildName
			New-ItemProperty "$scanclass\$item\DeviceData" -Name "ScannerAddress" -Value $ipAddress | Out-Null
			Get-ChildItem  $scanclass | ForEach-Object -Begin {
				$count = 0
				Add-Type -As System.Web
				$pass = [System.Web.Security.Membership]::GeneratePassword(12,2)
				$scanitem = @{}
				$filelist = @()
			} -Process {
				$path = $_.Name -replace 'HKEY_LOCAL_MACHINE', 'HKLM:'
				$prop = Get-ItemProperty $path
				if ($prop.Vendor -eq 'Kyocera') {
					$count ++
					$twfilename = "KM_TWAIN$count`.INI"
					$devicedata = Get-ItemProperty "$path\DeviceData"
					$cont = @{'Unit'='0';'ScannerAddress'=$devicedata.ScannerAddress; 'SSL'='0'}
					$auth = @{'Auth'='0';'UserName'=''; 'Account'='0'; 'ID'='';'Password'=$pass}
					$twcont = @{'Contents'=$cont; 'Authentication'=$auth}
					Out-IniFile -inputobject $twcont -FilePath "$env:temp\$twfilename"
					$filelist += , "$env:temp\$twfilename"

					$devicename = $devicedata.'Model Name' + " #$count"
					$modelname = $devicedata.'Model Name'
					$scanreg = @{'Name'=$devicename;'Model'=$modelname;'DefFile'=$twfilename;'LastScan'='';'ScanList'='';'Pos'=($count-1)}
					$scanitem.Add("Scanner$count", $scanreg)
				}
			} -End {
				$regfilename = 'RegList.ini'
				$settings = @{'Type'='4'; 'DefaultUse'=$count;'RegNum'=$count;}
				$reglist = @{'Setting'=$settings}
				$reglist += $scanitem
				Out-IniFile -inputobject $reglist -FilePath "$env:temp\$regfilename"
				$filelist += , "$env:temp\$regfilename"
			}
			Get-ChildItem $env:systemdrive\users -Directory -Recurse -Include 'appdata' -Force | ForEach-Object {
				$kyodir = $_.FullName + "\Roaming\Kyocera\KM_TWAIN"
				If (!(Test-Path $kyodir)) {
					New-Item -Type Directory -Path $kyodir
				} else {
					Remove-Item "$kyodir\*" -Recurse
				}
				$filelist | ForEach-Object {
					Copy-Item $_ $kyodir -Force | Out-Null
				}
			}
		}
		"6505" {
			Push-Location (Join-Path $driversdistrib 'Scanners\xx6505\')
			if ($(Get-Platform) -eq "Windows x64") {
				.\devconx64.exe /r install $dest\xrsmoim.inf "NON_PNP&WorkCentre6505"
			} else {
				.\devcon.exe /r install $dest\xrsmoim.inf "NON_PNP&WorkCentre6505"
			}
			Pop-Location

			Get-Process "AIOScanSettings" | Stop-Process -Force

			&rеg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 6505\TwainDriver" /v "EnableEnhancedBW" /t REG_DWORD /d 1 /f
			&rеg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 6505\TwainDriver" /v "IP Address" /t REG_SZ /d $ipAddress /f
		}
		"3615" {
			Push-Location (Join-Path $driversdistrib 'Scanners\xx3615\')
			if ($(Get-Platform) -eq "Windows x64") {
				.\devconx64.exe /r install $dest\xrszdim.inf "NON_PNP&WorkCentre3615"
			} else {
				.\devcon.exe /r install $dest\xrszdim.inf "NON_PNP&WorkCentre3615"
			}
			Pop-Location

			Get-Process "AIOScanSettings" | Stop-Process -Force
            # тут в слове rеg, средняя буква русская, дабы не превращался в &reg
			&rеg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "EnableEnhancedBW" /t REG_DWORD /d 1 /f
			&rеg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "ISO_B_Series" /t REG_DWORD /d 1 /f
			&rеg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "IP Address" /t REG_SZ /d $ipAddress /f
		}
	}
}
function Get-IPaddress {
	$ipWmiObject = Get-WmiObject Win32_NetworkAdapterConfiguration -filter "IPEnabled = 'True'"
	$ipWmiObject.IPAddress -match "^192\.([0-9]{1,3}\.){2}[0-9]{1,3}$"
}
function Get-Platform {
	if ([System.Environment]::Is64BitOperatingSystem) {
		"Windows x64"
	} else {
		"Windows NT x86"
	}
}
function Out-IniFile($inputobject, $filepath) {
	# .Example
	# $Category1 = @{'Key1'='Value1';'Key2'='Value2'}
	# $Category2 = @{'Key1'='Value1';'Key2'='Value2'}
	# $NewINIContent = @{'Category1'=$Category1;'Category2'=$Category2}
	# Out-IniFile -inputobject $NewINIContent -FilePath 'C:\MyNewFile.INI'

	$outfile = New-Item -ItemType File -Path $filepath -Force
	foreach ($i in $inputobject.keys) {
		Add-Content -Path $outfile -Value "[$i]"
		Foreach ($j in ($inputobject[$i].keys | Sort-Object)) {
			Add-Content -Path $outfile -Value "$j=$($inputobject[$i][$j])"
		}
		Add-Content -Path $outfile -Value ''
	}
}
function Invoke-SNMPget {
	param (
		[string]$sIP,
		$sOIDs,
		[string]$Community = "public",
		[int]$UDPport = 161,
		[int]$TimeOut=30
		)
	$vList = New-Object 'System.Collections.Generic.List[Lextm.SharpSnmpLib.Variable]'
	foreach ($sOID in $sOIDs) {
		$oid = New-Object Lextm.SharpSnmpLib.ObjectIdentifier ($sOID)
		$vList.Add($oid)
	}
	$ip = [System.Net.IPAddress]::Parse($sIP)
	$svr = New-Object System.Net.IpEndPoint ($ip, 161)
	$ver = [Lextm.SharpSnmpLib.VersionCode]::V1

	try {
		$msg = [Lextm.SharpSnmpLib.Messaging.Messenger]::Get($ver, $svr, $Community, $vList, $TimeOut)
	} catch {
		return $null
	}

	$res = @()
	foreach ($var in $msg) {
		$line = "" | Select OID, Data
		$line.OID = $var.Id.ToString()
		$line.Data = $var.Data.ToString()
		$res += $line
	}
	$res
}

. Main



На этом на сегодня всё, надеюсь мои заметки помогут вам забыть о проблемах с сетевыми принтерами и освободят время для изучения PowerShell.
Спасибо за внимание тем, кто дочитал до этого момента ;-)

+21
82.6k 339
Comments 10