⬆️ ⬇️

Automatic connection of network multifunction devices with the ability to scan [Part 2]

Kyocera M2035dn, Xerox WorkCentre 3615 and 6505DN



As promised in the first part , for which I successfully received an invite in the sandbox, in this article I will show how to connect the network multifunction devices Kyocera M2035dn, Xerox WorkCentre 3615 and 6505DN, and at the end of the article I will add a small bonus with which any script associated with the network becomes better .







No matter how beautiful the homogeneous infrastructures are, even in the part of printers and MFP, reality often sets its own conditions. While the users themselves were fully connected and successfully scanned from the once problematic HP MFPs, a Japanese guest came to the company - Kyocera M2035dn.

')

Kyocera M2035dn



I arrived, as always, not in my cozy admin's lair, but immediately at the object and, like the mfp from HP, I, frankly, didn’t even see it in my eyes.

First of all, download the driver and watch the contents ... ba, all the familiar people:







There is a note that the network connection is the ID!

Let's try to connect the scanner via devcon, just as we connected the MFP from HP in the first part:

.\devcon.exe /r install C:\Drivers\Scanners\2035dnscan\kmwiadrv.inf "KM_WC_ECOSYS_M2035dn_N_WIA"



The scanner has connected, register the address of the scanner in the registry with the ScannerAddress parameter and start the scan. Scanning application showed scanned sheet, everything works fine. It would seem a victory, but the launch of the second program used by us for scanning diminished the joys - the scanner was not displayed in it.







It turns out that the Kyocera developers for some reason in the driver implemented scanning only through WIA, for TWAIN it is necessary to set a separate costa .. a wrapper that sends the TWAIN interface to WIA and returns the result. This TWAIN driver looks like this:







At the same time, according to WIA, we can connect several Kyocera scanners, while we will always have only one TWAIN interface. Either use WIA, or run our utility each time and switch the scanner. We'll have to accept, but for now let's see how we get around the launch of this utility on the user's machine.

The utility stores settings in ini-files, one KM_TWAIN * .ini file for each network scanner and one resulting file with a description of scanners and their settings files.

Screen of both files for one connected scanner:







Now the installation is seen as follows:

- we connect the scanner through devcon

- if the TWAIN utility is not installed, set it

- add the scanner address to the registry

- we go through the registry in the search for connected Kyocera scanners and, based on the data in the registry, generate ini-files



Expand the scanner connection function from the previous note with the following code, which I tried to comment to the maximum:



 #        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 } } } 


In the script, I used the function of displaying a hash table in the ini-file, here is its code:



 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 and 6505DN



This code worked successfully and there were no problems with it, probably for half a year until the wind again blew in the other direction. Towards Xerox.

A letter with the ip-addresses of two new MFPs, WorkCentre 3615 and WorkCentre 6505DN, fell into the Outlook. The road of thought when meeting the new MFP has already been beaten, open the driver and see the familiar:







And my mood has improved ©



Unpack the driver, run the console, execute:

.\devcon.exe /r install C:\Drivers\Scanners\xx3615\xrszdim.inf "NON_PNP&WorkCentre3615"



The scanner connected and a new run-up appeared on the screen, as they say, only from the Xerox developers:







Another strange utility from the authors of the driver for prescribing IP, and it runs from the driver during installation. So, in order to hide it from the user, we will nail it in the script, in general, it does not matter.



Now I will show on the example of 3615 how to expand the scanner connection function. It practically does not differ from the 6506DN, unless a different name of the driver file and 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    &rg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "EnableEnhancedBW" /t REG_DWORD /d 1 /f &rg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "ISO_B_Series" /t REG_DWORD /d 1 /f &rg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "IP Address" /t REG_SZ /d $ipAddress /f } 




Now we can connect a whole zoo of network mfps and are not afraid at all, it remains to add some magic ... magic snmp!



We are looking for an MFP in the network by snmp



SNMP (Simple Network Management Protocol) is a standard Internet protocol for managing devices on IP networks based on TCP / UDP architectures.

ru.wikipedia.org/wiki/SNMP




To work with powershell snmp, I used the sharpsnmp open library in the script, read more about its use at: vwiki.co.uk/SNMP_and_PowerShell

After the library is connected, obtaining information is reduced to calling the Invoke-SNMPget function indicating Ip and uid, the last of which is easily googled.

Example from code:

Invoke-SNMPget $ip .1.3.6.1.2.1.25.3.2.1.3.1



The result of the search is displayed on the screen, on how to do it in one command just below:







It remains to select the desired printer and click OK, by the way, multiple selection is also possible, in this case all selected printers will be connected.

This handy magic is provided by the Out-GridView cmdlet, which displays any objects passed to it. When calling with the PassThru parameter, after clicking OK, he will pass on the selected objects down the pipeline, we just have to call in turn our driver installation functions with the parameters that came in the object from the pipeline.



In a simplified form, the script will take the form:

 $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 } 




In the process of studying the responses of printers, I came across the fact that printers sometimes give a name that differs from the name written in the driver, to bypass this feature I added a simple switch with regulars to the script that never miss, and as we know Turing is full ;-)



 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" } } 




Full code of the ready script for searching and connecting a network printer
 $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 &rg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 6505\TwainDriver" /v "EnableEnhancedBW" /t REG_DWORD /d 1 /f &rg.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 #    rg,   ,     ® &rg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "EnableEnhancedBW" /t REG_DWORD /d 1 /f &rg.exe add "hklm\SOFTWARE\Xerox\WorkCentre 3615\TwainDriver" /v "ISO_B_Series" /t REG_DWORD /d 1 /f &rg.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 






That's all for today, I hope my notes will help you forget about problems with network printers and free up time to learn PowerShell.

Thank you for your attention to those who read up to this point ;-)

Source: https://habr.com/ru/post/242725/



All Articles