Pull to refresh

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

PowerShell
Sandbox

HP LaserJet 1522, 1536, 3052/3055, 300/400 Color...


Я думаю, многим системным администраторам известны описанные в заголовке мфу, отличаются они, в первую очередь, не очень удобной установкой и от этого имеют дурную славу. Однажды, копируя на очередной компьютер сквозь узкий канал пакет fullsolution для мфу весом около 300 мегабайт, идея разобрать этот инсталлятор и автоматизировать установку вылезла попапом на глаза — работу пришлось приостановить.



Разбором драйвера я занимался уже около полутора лет назад, в то время интернет на эту тему был совершенно пуст. Сейчас быстро погуглил по теперь уже известным мне ключевым словам утилит и нашел немного разрозненной информации. Несмотря на это, я решил. что собранная в одно место информация все равно не помешает, при том, что в этом посте она более полная.

Настроим печать


Первым на запрос по snmp показался мфу HP LaserJet 1536, с него и решил начать. Для начала нужно понять. как его подключать как принтер под Windows 7; пожилую XP отбросил сразу, свежую Windows 8 в домене, есть мнение, мне не увидеть никогда. Вот и повод познакомиться с новым для себя PowerShell, подумал я, который в итоге был чуть ли не основной мотивацией в разборе драйвера. Подключение ip-принтера в Windows 7 состоит из трех этапов (в Windows 8 всё сильно упрощается встроенными командлетами, но про нее я уже говорил — не судьба), сначала создаем ip-порт, потом добавляем драйвер и подключаем, собственно, принтер. Для всех этих этапов в Windows есть уже готовые VBS скрипты, многим, я думаю, знакомые, в Windows 7 путь к ним: С:\Windows\System32\Printing_Admin_Scripts\

Начну с создания порта, этот этап самый простой, имя присвоим такое же как ip:
cscript C:\Windows\System32\Printing_Admin_Scripts\ru-RU\prnport.vbs -a -r "192.168.0.30" -h "192.168.0.30" -o RAW -n 9100


Добавление драйвера:
cscript C:\Windows\System32\Printing_Admin_Scripts\ru-RU\prndrvr.vbs -a -m "HP LaserJet M1530 MFP Series PCL 6" -e "Windows NT x86" -h "C:\drivers\1536\"-i "C:\drivers\1536\hpc1530c.inf"



Тут стоит отметить одну важную особенность: имя принтера должно указываться точно так же как оно прописано в inf файле драйвера, ради примера уберите часть имени, скрипт выдаст ошибку: «Не удалось добавить драйвер принтера HP LaserJet Код ошибки Win32 87».

Отрывок файла драйвера с полным именем принтера:



Теперь осталось подключить принтер, для этого я остановился на замечательной программе printui, советую посмотреть на нее поближе, у нее есть интересные ключи.
&rundll32 printui.dll,PrintUIEntry /if /b "HP LaserJet M1530 MFP Series PCL 6" /r "192.168.0.30" /m "HP LaserJet M1530 MFP Series PCL 6" /u /K /q /Gw

Пришло время оформить все это в примерно следующего вида скрипт на PowerShell:

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 Get-Platform {
	if ([System.Environment]::Is64BitOperatingSystem) {
		"Windows x64"
	} else {
		"Windows NT x86"
	}
}

Add-Type -As Microsoft.VisualBasic
$printerSource = [Microsoft.VisualBasic.Interaction]::InputBox("Укажите IP адрес принтера.")

if ($printerSource -match "^192\.168\.0\.[0-9]{1,3}$") {
	$printername = "HP LaserJet M1530 MFP Series PCL 6"
	$driverpath = "C:\drivers\1536\hpc1530c.inf"

	Add-PrinterPort $printersource
	Add-PrinterDriver $printername $driverpath

	# знак & перед командой переключит режим и паремтры не сломаются
	&rundll32 printui.dll,PrintUIEntry /if /b $printername /r $printersource /m $printername /u /K /q /Gw
	Start-Sleep -Seconds 10
}




Сканирование


Копаясь в inf файлах драйвера, для поиска правильного имени принтера и попутно вообще разбираясь в структуре драйвера HP, глаз зацепился за следующие строки (выделил жирным):

;Windows Vista
[HP.NT.6.0]
«HP LJ M1530 MFP Series Scan»= WIA_1530_Inst.NT.6.0, USB\vid_03f0&pid_012a&mi_00
«HP LJ M1530 MFP Series Scan»= WIA_1530_NW.NT.6.0,vid_03f0&pid_012a&IP_SCAN

;Windows Vista 64
[HP.NTAMD64.6.0]
«HP LJ M1530 MFP Series Scan»= WIA_1530_Inst_Vista64, USB\vid_03f0&pid_012a&mi_00
«HP LJ M1530 MFP Series Scan»= WIA_1530_NW_Vista64,vid_03f0&pid_012a&IP_SCAN


Тут бы хотелось лирики (казалось бы, при чем тут 1С? если вы понимаете о чём я), но опущусь до сухой констатации: попробуем devcon.exe.

DevCon — это программа с интерфейсом командной строки, которая используется в качестве альтернативы диспетчеру устройств С ее помощью можно включать, выключать, перезапускать, обновлять, удалять и опрашивать отдельные устройства или группы устройств. Программа DevCon также предоставляет необходимые разработчику драйвера сведения, которые недоступны с помощью диспетчера устройств.

support.microsoft.com/kb/311272/ru

Добавляем устройство по ID указав драйвер:

.\devcon.exe /r install C:\drivers\1536scan\hppasc16.inf "vid_03f0&pid_012a&IP_SCAN"

Добавляем в реестр необходимые параметры, запускаем сканирование и… Бинго!
Сканер отлично работает, осталось все это оформить.

Настройки сканера в реестре хранятся по следующим путям:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\IMAGE

Опытным путём определяем необходимые нам ключи реестра:





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

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}\_ITEM_\DeviceData]
«NetworkDeviceID»="\\hostname:_NETWORK_NAME_.domain.local\\ipaddr:_IP_ADDRESS_\\guid:\\macaddr:_MAC_ADDRESS_\\port:1"
«PortID»="_IP_ADDRESS_"
«NetworkHostName»="_NETWORK_NAME_.domain.local"
«TulipIOType»=dword:00000005

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\IMAGE\_ITEM_\Device Parameters]
«NetworkDeviceID»="\\hostname:_NETWORK_NAME_.domain.local\\ipaddr:_IP_ADDRESS_\\guid:\\macaddr:_MAC_ADDRESS_\\port:1"
«PortID»="_IP_ADDRESS_"
«NetworkHostName»="_NETWORK_NAME_.domain.local"
«MAC»="_MAC_ADDRESS_"
«PortNumber»=«1»
«Index»="_ITEM_"


Готовый скрипт установки сканера примет следующий вид:

$IP_ADDRESS = "192.168.0.30"
$MAC_ADDRESS = "001b00b2cc00"
$NETWORK_NAME = "NPI3CPOF7"

$source = "C:\drivers\1536scan"
$dest = Join-Path (Get-Location).path "\temporary"

Copy-Item $source $dest -Recurse -Force
$dest = Join-Path $dest "\hppasc16.inf"

# devcon лежит в одной директории со скриптом
& .\devcon.exe /r install $dest "vid_03f0&pid_012a&IP_SCAN"

$item = Get-ChildItem HKLM:\SYSTEM\CurrentControlSet\Control\Class\"{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}" |
	Select-Object -Last 1
$item = $item.Substring($item.Length-4, 4)

$pattern = ".\temporary\1536.reg"
$result = ".\temporary\res.reg"
Get-Content $pattern | ForEach-Object {
    $_ 	-replace "_IP_ADDRESS_", $IP_ADDRESS `
    	-replace "_MAC_ADDRESS_", $MAC_ADDRESS `
    	-replace "_NETWORK_NAME_", $NETWORK_NAME `
    	-replace "_ITEM_", $item
} | Set-Content $result

& regedit /s .\temporary\res.reg


Потираем руки, проверяем — работает, модифицируем под 1522 — работает, победно правим под 3055 — облом…
Сканер не дает выбрать планшет, в меню сканирования доступен только податчик, да и тот отказывается сканировать.



Серьезный разговор с 3055 или, Чувак ты поднял на гору не тот камень





Вот он, LaserJet 3055/3052 — самый вредный парень, на удивление вижу я его чаще всех. На самом деле — скажу по секрету — я начал заниматься им первым — пошел через дебри фильтрации вывода procmon при установке драйвера для поиска чего-нибудь интересного и утонул где-то посередине. Когда очередной раз procmon упал из-за нехватки памяти, я решил отложить эту затею до более дружелюбного и спокойного состояния.

Второй набег на разбор установщика МФУ дал результат: спустя часа полтора разбора логов в недрах вывода установщика была найдена жемчужина — hppniscan01.exe
Запуск с необходимыми параметрами моментально установил сканер в устройства и прописал необходимые ветки реестра:
hppniscan01.exe -f "hppasc16.inf" -m "vid_03f0&pid_012a&IP_SCAN" -a "192.168.0.30" -n 1




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

Драйвера сканера я решил выдернуть из общей папки драйверов и сложить отдельно, необходимые файлы легко читаются из inf-файла драйвера. Дерево получилось следующего вида:

C:\Drivers\Scanners\ip\3055scan\hpgtpusd.dll
C:\Drivers\Scanners\ip\3055scan\hppasc01.cat
C:\Drivers\Scanners\ip\3055scan\hppasc01.dll
C:\Drivers\Scanners\ip\3055scan\hppasc01.inf
C:\Drivers\Scanners\ip\3055scan\hppniscan01.exe
C:\Drivers\Scanners\ip\3055scan\hpptpml3.dll
C:\Drivers\Scanners\ip\3055scan\hpxp3390.dll
C:\Drivers\Scanners\ip\3055scan\Drivers\dot4
C:\Drivers\Scanners\ip\3055scan\Drivers\dot4\Win2000\hpzidr12.dll
C:\Drivers\Scanners\ip\3055scan\Drivers\dot4\Win2000\hpzipm12.dll
C:\Drivers\Scanners\ip\3055scan\Drivers\dot4\Win2000\hpzipr12.dll
C:\Drivers\Scanners\ip\3055scan\Drivers\dot4\Win2000\hpzipr12.sys


Функция установки сканера теперь стала совсем простой, хоть и с зависимостью от внешней компоненты.
Итоговый вид скрипта, с некоторыми захардкоженными упрощениями, примет следующий вид:

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 Get-Platform {
    if ([System.Environment]::Is64BitOperatingSystem) {
        "Windows x64"
    } else {
        "Windows NT x86"
    }
}

function Add-Scanner ($ipaddress, $printername) {
    switch -regex ($printername) {
        # добавить других мфу по вкусу
        "1530" {
            Push-Location 'C:\Drivers\Scanners\ip\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 'C:\Drivers\Scanners\ip\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
        }
    }
}

Add-Type -As Microsoft.VisualBasic
$printerSource = [Microsoft.VisualBasic.Interaction]::InputBox("Укажите IP адрес принтера.")

if ($printersource -match "^192\.168\.0\.[0-9]{1,3}$") {
    $printername = "HP LaserJet M1530 MFP Series PCL 6"
    $driverpath = "C:\drivers\1536\hpc1530c.inf"

    Add-PrinterPort $printersource
    Add-PrinterDriver $printername $driverPath
    # знак & перед коммандой переключит режим и параметры не сломаются
    &rundll32 printui.dll,PrintUIEntry /if /b $printername /r $printersource /m $printername /u /K /q /Gw
    Start-Sleep -Seconds 10

    Add-Scanner $printersource $printername
}


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

Список файлов драйвера можно посмотреть в разделах inf-файла с именами [SourceDisksFiles], [RegisterDlls], [WIA_CopyFiles] и далее по файлу. Скриншот по драйверам 3055 и 1536, для наглядности:



Из описанных в этой заметке отрывков кода можно собрать полноценный скрипт автоматической установки МФУ, а если добавить в него немного гуя и snmp, то можно вообще навсегда закрыть для себя тему установки МФУ на новые машины.

На этом на сегодня всё, спасибо за внимание. Если в комментариях подскажут чего не хватает МФУ 3055 для работы при установке первым способом посредством devcon, буду сильно благодарен. Может быть кто-то проделал ту же работу, что и я, но добился больших успехов.

В следующей части, если кто-то кинет таки инвайт в песочницу, покажу как расширить наш сценарий для работы с МФУ Xerox и Kyocera.
Tags:hplaserjetpowershellмфусканирование
Hubs: PowerShell
Total votes 31: ↑30 and ↓1 +29
Views152.8K

Popular right now

DevOps specialist
from 100,000 ₽deeplayНовосибирскRemote job
Разработчик Python/Django
from 80,000 to 120,000 ₽PrintumRemote job
Системный инженер [SI2021Q2]
from 80,000 to 150,000 ₽ITA LabsRemote job
DevOps инженер
from 80,000 ₽Smart WorldТомск