kelp7
(Starting to like KiXtart)
2015-12-07 12:29 PM
SNMP with Printers

Hi,

Just a quick query (with probably not a quick answer, I'm sure) but can you issue SNMP 'get' queries from Kixtart? Are there any Kix scripts already written to retrieve some information from networked printers via SNMP (ideally I'd like to get toner level and printer model).

Thanks!


Glenn BarnasAdministrator
(KiX Supporter)
2015-12-07 12:49 PM
Re: SNMP with Printers

If you can use a command-line utility, then WshPipe() can be used to execute the command and return the results in a string. See www.net-snmp.org/ for a free, command-line tool for Windows. (There are others, this was the top/free tool returned by Google.)

If you use the version of WshPipe() from my web site, it returns an array of arrays - the inner array is an array of lines of STDOUT, and the outer array is an array of the lines of STDERR. The version published here on KORG returns a single string of all the lines of STDOUT and STDERR, which I find a bit harder to parse.

Once you have the result from either version of WshPipe(), it's a fairly straightforward task to enumerate the list of output and find/interpret the results.

Post what you build - we can help tweak it and I for one would be interested in seeing something like this!

Glenn


kelp7
(Starting to like KiXtart)
2015-12-07 01:50 PM
Re: SNMP with Printers

Thanks Glenn, as ever, always appreciate your quick answers.

Firstly, I've got to get to grips with SNMP really :-) Just now trying to find some OIDs or MIB files for the printer types (Xerox) that we are using...


kelp7
(Starting to like KiXtart)
2015-12-07 04:25 PM
Re: SNMP with Printers

Incidentally, just found this nice utility if you don't know what SNMP queries your device is capable of:

http://www.snmpsoft.com/freetools/snmpwalk.html


kelp7
(Starting to like KiXtart)
2015-12-07 07:22 PM
Re: SNMP with Printers

Spent a little while this afternoon looking up OIDs via the SNMPWalk program and it does look like this will be possible. Annoyingly the OIDs for toner and make/model aren't always the same value between different models of the same manufacturer (Xerox in my case). Nothing that can't be dealt with in the script though.

The way I see it the script will need to:

Query current printer for Make\Model
Depending on Make\Model choose the correct list of OIDs
Query the printer again for the current OIDs for toner
Make a note if they're below a threshold
Cycle through all printers with the above script
Finish (in my case) by sending an email to the service desk logging system with the list of toners below the threshold.

It would be nice to also query the location of the printer (we configure the location on all our printers) so hopefully I can get that info as well from SNMP.

Not sure how I'll get a list from the print server of all the printers' IPs and would rather avoid having to store a static list of IP addresses in an array in the script, something else to look into I guess.


Glenn BarnasAdministrator
(KiX Supporter)
2015-12-07 08:54 PM
Re: SNMP with Printers

Sounds like you need a lookup table! \:\)

An INI file could map a printer brand/model to specific OIDs for generic information like TonerLevel, Location, etc..

[Xerox 272]
Toner=OID...
Location=OID...

Doing so would allow you to get the printer model, then lookup the OIDs for the values. The code then becomes generic and only the config file needs to be customized for different printer models.

As for a list of printers, don't you publish your printers in AD? You can do an LDAP query if you do.

Glenn


kelp7
(Starting to like KiXtart)
2015-12-08 02:32 PM
Re: SNMP with Printers

Thanks, yes a lookup table would certainly be first on my list!
We don't publish our printers in AD, we used to but then users were ending up with 20 / 30 printers they'd installed themselves on their profiles and used once. Annoying for our engineers when rebuilding a profile or a whole machine. We push them out with GPO to those who need it. It's possible we might start publishing them again though (something I recently considered proposing myself) as in the long run it does seem easier for users. (We have 170+ printers in our organisation)

Wow, it's taken me a while to go through the SNMP OIDs on each of the 7 different models of printer we have. For a while I couldn't suss out getting the toner levels, no integers in the SNMPWalk results seemed to match up or if they did then they'd give the same result each time for different printers. Clearly they weren't right. I then found that there's a standard OID for toner levels (and Xerox follows the standard luckily) and really weirdly you don't just get a single integer for the toner level, you actually have to look for the maximum value and the current value. Then you get your percentage of toner left by doing the usual divide current by max and * 100

Will be fun to get this working!


kelp7
(Starting to like KiXtart)
2015-12-08 04:50 PM
Re: SNMP with Printers

Got an .ini file ready now \:\)

It's structured like this (this is not the complete file, no point posting that up here):

 Code:
[Xerox 5955]
Location=.1.3.6.1.2.1.1.5.0
Black=.1.3.6.1.2.1.43.11.1.1.9.1.1
ENDPRINTER

[Xerox 6600]
Location=.1.3.6.1.2.1.1.6.0
Cyan=.1.3.6.1.2.1.43.11.1.1.9.1.1
Magenta=.1.3.6.1.2.1.43.11.1.1.9.1.2
Yellow=.1.3.6.1.2.1.43.11.1.1.9.1.3
Black=.1.3.6.1.2.1.43.11.1.1.9.1.4
ENDPRINTER


and have also carried out a very quick test of WshPipe(), just a one liner that collects the model name using an SNMPGet program and it successfully printed the model name on the screen so all looking good so far. Now onto the meat of the exercise !!


AllenAdministrator
(KiX Supporter)
2015-12-08 05:05 PM
Re: SNMP with Printers

What is ENDPRINTER?

If its a comment it should start with # or ;.


kelp7
(Starting to like KiXtart)
2015-12-08 06:11 PM
Re: SNMP with Printers

No, I don't need comments in my .ini file. Everything there has a purpose. ENDPRINTER will just be checked in my script to determine how many criteria each printer has.

AllenAdministrator
(KiX Supporter)
2015-12-08 08:36 PM
Re: SNMP with Printers

Not sure if you are aware of the inbuilt INI support... but here's an example...
 Code:
$Values=split(Readprofilestring($ini,"[Xerox 5955]",""),chr(10))
? "Items:  " + (ubound($values)+1)
for each $Value in $Values
  if $value
    ? readprofilestring($ini,"[Xerox 5955]",$value)
  endif
next


You can get all the sections similarly by readprofilestring($ini,"","")

Also be sure to look for Glenn's INI functions on his website as they turn the INIs into arrays and work great.


Glenn BarnasAdministrator
(KiX Supporter)
2015-12-09 03:34 AM
Re: SNMP with Printers

Kelp,

So - as Allen pointed out, the built-in ReadProfileString has some pretty useful capabilities.
 Code:
$List = ReadProfileString('inifile.ini', 'Xerox 6600')
will load all of the values into a list, delimited with @CRLF. Performing a
 Code:
$aList = Split($List, @CRLF)
will convert this to an array. The UDF EnumIni() will do this for you, btw.

So - to find out how many parameters you have:
 Code:
$Params = UBound($aList)
You can also enumerate this with "for each $V in $Array". Note that this returns the VALUES that exist in the section, and enumerating them will return "Black", "Cyan", "Magenta", and "Yellow". Here's the bigger picture:
 Code:
$PModel = 'Xerox 6600'
; Get the supported toner colors
$aColors = Split(ReadProfileString('PrinterData.ini', $PModel), @CRLF)
For Each $Color in $aColors
  ; message for debugging
  'Processing toner color: ' $Color @CRLF
  $Oid = ReadProfileString('PrinterData.ini', $PModel, $Color)
  $Cmd = 'snmpget.exe ' + $PrinterIP + ' ' + $Oid
  $CmdResult = WshPipe($Cmd)
  ; do the magic with the returned data here..
  ;
  ; then process the next toner color (if any)
Next
Look at EnumIni() as well to simplify repeated execution of INI queries. The other function that Allen referenced is IniArray, which loads an entire INI file into an array and allows manipulation with functions similar to Read/WriteProfileString. If you find yourself doing lots of INI reads, this can improve performance, but I'd start with the basic Read and Write ProfileString commands.

Glenn

Hey Allen - when the hell did "built-in" become "inbuilt"? \:D


AllenAdministrator
(KiX Supporter)
2015-12-09 04:03 AM
Re: SNMP with Printers

Basta! ;\)

NTDOCAdministrator
(KiX Master)
2015-12-10 03:26 AM
Re: SNMP with Printers

LOL... scripting for over a decade causes spots of memory starvation so be kind Glenn :-)

Glenn BarnasAdministrator
(KiX Supporter)
2015-12-11 01:23 PM
Re: SNMP with Printers

Woah, Ron! I'm just being protective!! Allen was right on the edge of that slippery slope of saying "I must revert back to him"! \:D (I like me just the way I am and have no plans to revert to anyone else!)

Glenn


kelp7
(Starting to like KiXtart)
2015-12-14 09:47 AM
Re: SNMP with Printers

Hi guys, sorry I haven't done any more on this yet. Thanks very much for all the advice though, and I didn't realise INI files had already been catered for \:\) Apologies for the delay though, struck down by an extremely hostile throat infection last week (nearly rid of it now) which took me off work Weds - Fri and also ruined my weekend. Nice.

kelp7
(Starting to like KiXtart)
2015-12-14 11:27 AM
Re: SNMP with Printers

Interestingly when I execute:

 Code:
$aColors = Split(ReadProfileString('PrinterData.ini', $PModel), @CRLF)


I get a message from Kix saying "ERROR : invalid method/function call: missing required parameter 3!"

It only seems to allow the line to execute if it's specified like this:

 Code:
$aColors = Split(ReadProfileString('PrinterData.ini', $PModel, ''), @CRLF)


but then the array is empty!

I'm guessing I've missed something else somewhere so am taking a look through the code now (although I've now cut the script right down to simply printing the contents of the array on the screen, unfortunately empty at the moment). I've tried specifying the complete path to the .ini file as well, just in case that was it. But still the same.


kelp7
(Starting to like KiXtart)
2015-12-14 11:41 AM
Re: SNMP with Printers

Also just tried a simple:

 Code:
$aColors = ReadProfileString('PrinterData.ini', $PModel, '')


and printing the variable on the screen but it is also empty. (And also tried substituting $PModel for the actual model number).


Mart
(KiX Supporter)
2015-12-14 12:20 PM
Re: SNMP with Printers

 Originally Posted By: kelp7
Interestingly when I execute:

 Code:
$aColors = Split(ReadProfileString('PrinterData.ini', $PModel), @CRLF)


I get a message from Kix saying "ERROR : invalid method/function call: missing required parameter 3!"

....


ReadProfileString requires three parameters. First the file, second the section and third the value. So something like $aColors = Split(ReadProfileString('PrinterData.ini', $PModel, value), @CRLF) should do the trick. Off course the name of the value needs to be modified to fit your ini file.


kelp7
(Starting to like KiXtart)
2015-12-14 12:29 PM
Re: SNMP with Printers

OK But in the manual it suggests that if the parameter is empty then it'll return all the keys. Anyway, I've worked it out now, the script simply wasn't finding the file! I'm working on a new 2012 server and had forgotten to show all file extensions. So only now do I find out that my .ini file is actually called PrinterData.ini.txt (simple mistake but what a doofus). Right, on with the scripting!!

kelp7
(Starting to like KiXtart)
2015-12-14 12:43 PM
Re: SNMP with Printers

Main issue now seems to be that Split is not putting all the different keys into separate array elements. $aColors[0] contains all of the keys one after another delimited by CRLF

Glenn BarnasAdministrator
(KiX Supporter)
2015-12-14 12:46 PM
Re: SNMP with Printers

Hey - don't be hangin' around spreading those germy bits 'n bytes!

Feel better!


kelp7
(Starting to like KiXtart)
2015-12-14 12:51 PM
Re: SNMP with Printers

\:\) Thanks!

I'm back at work today but still not shaken it all off.

Just trying to work out what's happening with ReadProfileString actually, I wonder whether the results it returns (when it returns all keys in the variable) are actually delimited by CRLF or by something else...


Glenn BarnasAdministrator
(KiX Supporter)
2015-12-14 12:57 PM
Re: SNMP with Printers

Look at the EnumIni UDF - either for ideas or use it as-is.. it does all the heavy lifting of reading the INI (just like you are) and assembling the array.

It is also forgiving about the vars you pass, in fact - it doesn't want them!
 Code:
$aSections = EnumIni($IniFile)  ; return an array of sections in the INI file

$aValues = EnumIni($IniFile, $Section) ; return an array of values within a section
Often, you'll use the first form and enumerate the list of sections, sometimes excluding certain sections such as "COMMON" or "SETTINGS" which contain app settings. The remaining sections might need to be enumerated to gather specific information, such as a file containing a collection of tasks to perform.

The second form returns the list of VALUES, but not any data. This generally is enumerated to perform the specific ReadProfileString($IniFile, $Section, $Value) to get the actual data.

Looking at the EnumIni code, it seems that the delimiter is newline ( Chr(10) ) and not @CRLF. Sorry about that!

FYI - the latest version of any of my UDFs is available from my web site - I have a Kix service that runs to sync my UDF lib with the web site, running PostPrep in the process. It also creates a Zip file of all the UDFs for quick access to everything.

Glenn


kelp7
(Starting to like KiXtart)
2015-12-14 01:06 PM
Re: SNMP with Printers

Thanks Glenn, I always make sure to get any UDFs direct from your website to ensure I get the right versions. Interesting about the Newline character, I'll see if that works. I will check out the Enumini UDF though!

kelp7
(Starting to like KiXtart)
2015-12-14 01:17 PM
Re: SNMP with Printers

Yeah that works now.

I had to put an IF $Color ENDIF section as it seemed to try to work on an empty array element at some point (at the end of the loop I think). But otherwise, all working fine so far, output as follows:

 Code:
C:\Scripts>kix32 printerquery.kix
Processing INI value: Model
Xerox Phaser 6600DN
Processing INI value: Location
SSD Dispatch
Processing INI value: Cyan
1600
Processing INI value: Magenta
1200
Processing INI value: Yellow
1200
Processing INI value: Black
1800


This is just for a specific printer so far, that'll be the next task (looping through a list of printers). Well, actually, the next task is taking those color values returned by the snmpget and dividing them appropriately by the maximum values to get the percentage left. Fun!


Mart
(KiX Supporter)
2015-12-14 02:22 PM
Re: SNMP with Printers

 Originally Posted By: kelp7
OK But in the manual it suggests that if the parameter is empty then it'll return all the keys. Anyway, I've worked it out now, the script simply wasn't finding the file! I'm working on a new 2012 server and had forgotten to show all file extensions. So only now do I find out that my .ini file is actually called PrinterData.ini.txt (simple mistake but what a doofus). Right, on with the scripting!!


Sorry! I should read better. I have some difficulties "starting up" after just 4 hours of sleep and a very busy and sort off messed up weekend.

LOL those pesky .ini.txt files have bitten me also some time ago. A simple mistake but so easy to overlook.


kelp7
(Starting to like KiXtart)
2015-12-14 03:44 PM
Re: SNMP with Printers

 Originally Posted By: Mart
Sorry! I should read better. I have some difficulties "starting up" after just 4 hours of sleep and a very busy and sort off messed up weekend.

LOL those pesky .ini.txt files have bitten me also some time ago. A simple mistake but so easy to overlook.


Not a problem \:\) I'm just glad that I now have a nearly completely working script!

One thing I'm struggling with at the moment is that I need to convert some of the results (the toner levels) from strings to numerics and carry out some calculations on them. I'm carrying out a divide calculation but because I'm currently using CInt() to convert from string to number obviously I don't get the fractional part. Scratching my head about this one but I'm sure I'll crack it shortly...


kelp7
(Starting to like KiXtart)
2015-12-14 03:46 PM
Re: SNMP with Printers

(Perhaps 'VAL()' is my answer to this one...)

AllenAdministrator
(KiX Supporter)
2015-12-14 03:54 PM
Re: SNMP with Printers

If you look at my second response you will see you do have to have both values as "" to get the sections. Even though the values are blank, the function requires something to be there or it will bark at you. \:\)

kelp7
(Starting to like KiXtart)
2015-12-14 04:09 PM
Re: SNMP with Printers

Argh, from the Kixtart manual:

"/ Used to divide two numbers and return an integer result."

Really do not want integers! Going to go straight to Glenn's website now and look through some UDFs!


kelp7
(Starting to like KiXtart)
2015-12-14 04:43 PM
Re: SNMP with Printers

Even more interesting is that if I run a piece of code:

 Code:
$A = 4400.00
$B = 11000.00
$C = ($A / $B)


I do actually get a result that includes a decimal point and remainder! Not sure what the manual is talking about.

Still have the difficulty of not being able to convert a string to a number that's not an integer.


AllenAdministrator
(KiX Supporter)
2015-12-14 05:02 PM
Re: SNMP with Printers

Try
 Code:
cdbl($inivalue)


kelp7
(Starting to like KiXtart)
2015-12-14 05:02 PM
Re: SNMP with Printers

Interesting, okay thanks, I'll look that function up.

kelp7
(Starting to like KiXtart)
2015-12-14 05:04 PM
Re: SNMP with Printers

Perfect \:\) Thanks for that, it works.

Glenn BarnasAdministrator
(KiX Supporter)
2015-12-14 06:27 PM
Re: SNMP with Printers

 Originally Posted By: kelp7
Really do not want integers! Going to go straight to Glenn's website now and look through some UDFs!
Have you looked at KGen and the Kix Development Kit on my site? It simplifies management of app development and deployment.

Operation is pretty simple:
Create a Dev folder, with a KixLib subfolder. Can be a network share.
Define a System environment var called KixLibPath and point to the Dev\KixLib folder.
Copy the KGen.bat file to a folder that's in your Path (C:\Windows is OK for testing).

Create a subfolder in Dev for your project, and create your basic script.txt file there. Don't include any public UDFs in your code.
Optionally, break your script into modules, with your app-specific UDFs placed in a script.udf file in the same folder. I often break large files into multiple .UDF files in the project folder.

When you run (from a command prompt) KGEN script (without the .txt extension) it will parse your code, include all local .KXF and .UDF files, and then recursively scan your script and the external UDFs to include any required files from the KixLib folder. It creates a .KIX file ready to run with all needed UDFs. It also runs your finished script through the Sanity UDF, which checks for variable definitions, mismatched operator pairs (if/endif) and paired character sets (quotes, parens, and such).

The package is free to download and use, and has way more options and capabilities than I've mentioned here. Refer to the User Guide for complete information.

Using one of the advanced options (build.ini), I can run KGEN to build a new rev and copy it to the app folder on my machine. After local testing and validation, I re-run KGEN with a "PROD" argument and it re-gens the script, tokenizes it, and copies it to the shared folder for deployment.

Glenn


kelp7
(Starting to like KiXtart)
2015-12-15 11:13 AM
Re: SNMP with Printers

Hi Glenn,

That is awesome but I only do the very occasional bit of scripting, it's not a big part of what I do (hence my constant state of re-learning everything again and I only ever hang out in the Basic Scripting forum \:\) )

I'll take a look though just out of interest

Cheers
kelp


kelp7
(Starting to like KiXtart)
2015-12-15 11:18 AM
Re: SNMP with Printers

So, making good headway with the script today. I've decided to scrap the 'MODEL' part of the INI file and have now implemented a nifty bit of code that reads the model of the machine from the very first OID on the device. I've had to rename each section of the INI file to exactly match what comes back in the first OID on each device though.

Here's a couple of examples of what you get back from the first OID:

 Code:
.1.3.6.1.2.1.1.1.0,OctetString,Xerox Phaser 3320;Sys SW Version Phaser3320_V53.005.00.000 MAY-16-2014,MCB V2.50.04.00 MAY-16-2014,NIC V4.04.00,IOT V1.00.33,PCL5e 6.50.02.03,PCL6 6.23.00.02,PS 2.83.00.59.00.59 ,IBM/EPSON 5.29.01, IP Core 6.8.P


and

 Code:
.1.3.6.1.2.1.1.1.0,OctetString,Xerox WorkCentre 7835 v1 Multifunction System; System Software 071.010.103.04401, ESS 071.013.04411


for two different models. Just came up with this bit of code:

 Code:
$Cmd = 'snmpget.exe -r:' + $PrinterIP + ' -o:.1.3.6.1.2.1.1.1.0 -q'
$CmdResult = WshPipe($Cmd)
$CmdResult = Join($CmdResult[0], @CRLF)
$PModel = SubStr($CmdResult, Instr($CmdResult, "X"), (Instr($CmdResult, ";") - Instr($CmdResult, "X")))


which does the job nicely of populating the $PModel variable and that can then be used to find the right section of the INI (with the ReadProfileString function).

All looking great so far.

My only issue is that I am really going to have to create a data file containing a list of all the IPs of the printers we have and it'll cycle through this file querying each printer in turn. Bit annoying but I don't see any other way of doing it unless we change our system of not publishing printers in the directory.


kelp7
(Starting to like KiXtart)
2015-12-16 04:56 PM
Re: SNMP with Printers

Script finished and operational running twice a day via windows task scheduler.

Thanks guys for all your input and help.


NTDOCAdministrator
(KiX Master)
2015-12-16 09:02 PM
Re: SNMP with Printers

Great. Can you post a final code solution you came up with?

Thanks


kelp7
(Starting to like KiXtart)
2015-12-17 10:29 AM
Re: SNMP with Printers

Well, okay. But I have to warn you I am no amazing coder. I'm sure there are plenty of better ways to achieve the solution. Also, I'm now being asked whether it can put the printers it's already warned about previously at the bottom of the email away from any new ones. That's gonna be a fun project.

Anyway, here's what I came up with (some personal / site details edited out):

 Code:
$x = Open(1, ".\PrinterOut.txt", 5)
$x = Open(2, ".\PrinterList.dat", 2)
$x = WriteLine(1, "The following printers are getting low on toner, please visit and assist:" + @CRLF + @CRLF)
Dim $StoreVals[6]
$EmailNeeded = 0
$PrinterIP = ReadLine(2)
While @ERROR = 0
  $Cmd = 'snmpget.exe -r:' + $PrinterIP + ' -o:.1.3.6.1.2.1.1.1.0 -q -t:10'
  $CmdResult = WshPipe($Cmd)
  $CmdResult = Join($CmdResult[0], @CRLF)
  $PModel = SubStr($CmdResult, Instr($CmdResult, "X"), (Instr($CmdResult, ";") - Instr($CmdResult, "X")))
  $Count = 0
  $Flag = 0

  ; If the device is online and the device is a Xerox machine
  If Left($CmdResult, 1) <> "%" AND $PModel <> ""
    ; Get the supported values for a printer type
    $aIniVals = Split(ReadProfileString('.\PrinterData.ini', $PModel, ''), Chr(10))
    ; Make sure the device is one of those listed in the INI file otherwise report an error
    If UBound($aIniVals) > 0
      For Each $IniVal in $aIniVals
        If $IniVal
          $Oid = ReadProfileString('.\PrinterData.ini', $PModel, $IniVal)
          $Cmd = 'snmpget.exe -r:' + $PrinterIP + ' -o:' + $Oid + ' -q -t:10'
          $CmdResult = WshPipe($Cmd)
          $CmdResult = Join($CmdResult[0], @CRLF)
          If $IniVal <> "Location"
            $Cmd = 'snmpget.exe -r:' + $PrinterIP + ' -o:' + SUBSTR($Oid, 1, 23) + "8" + SUBSTR($Oid, 25, 4) + ' -q -t:10'
            $CmdResult2 = WshPipe($Cmd)
            $CmdResult2 = Join($CmdResult2[0], @CRLF)
            $CmdResult = CDbl($CmdResult)
            $CmdResult2 = CDbl($CmdResult2)
            $StoreVals[$Count] = ($CmdResult / $CmdResult2) * 100
          Else
            $StoreVals[$Count] = $CmdResult        
          EndIf
        EndIf
      $Count = $Count + 1
      Next
    Else
      $Count = 1
      $StoreVals[$Count] = "WARNING - Printer Model Not Found : Report this to 3rd line"
    EndIf

    $PrinterText = $PrinterIP + " : " + $PModel
    If $Count > 1
      $PrinterText = $PrinterText + " : " + SubStr($StoreVals[0], 1, Len($StoreVals[0]) - 2)
      For $x = 1 to ($Count - 2)
        If $StoreVals[$x] <= 5
          $PrinterText = $PrinterText + " : " + $aIniVals[$x] + " : " + $StoreVals[$x] + "%"
          $Flag = 1
          $EmailNeeded = 1
        EndIf
      Next
    EndIf

    If $Count = 1
      $PrinterText = $PrinterText + $PrinterIP + " : " + $StoreVals[$Count]
      $Flag = 1
      $EmailNeeded = 1
    EndIf

  EndIf

  If $Count = 0
    $PrinterText = $PrinterIP + " : Device is offline (or not a Xerox device, check IP)"
    $Flag = 1
    $EmailNeeded = 1
  EndIf

  If $Flag
    $x = WriteLine(1, $PrinterText + @CRLF)
  EndIf

  $PrinterIP = ReadLine(2)
LOOP

$x = Close(2)
$x = Close(1)

If $EmailNeeded
  Shell "CMD.EXE /C C:\Scripts\blat.exe PrinterOut.txt -to blahblah@@company.com -subject " + Chr(34) + "Printers Low In Toner" + Chr(34) + " -q"
EndIf

Exit


I realise I didn't comment a lot of it so if you can unpack this code, good luck to you.

Here are the file structures that it uses (not all contents of files uploaded, these are just to give the general idea):

1. The INI file (PrinterData.ini)

 Code:
[Xerox WorkCentre 5855 v1]
Location=.1.3.6.1.2.1.1.5.0
Black=.1.3.6.1.2.1.43.11.1.1.9.1.1

[Xerox WorkCentre 5955 v1]
Location=.1.3.6.1.2.1.1.5.0
Black=.1.3.6.1.2.1.43.11.1.1.9.1.1

[Xerox Phaser 6600DN]
Location=.1.3.6.1.2.1.1.6.0
Cyan=.1.3.6.1.2.1.43.11.1.1.9.1.1
Magenta=.1.3.6.1.2.1.43.11.1.1.9.1.2
Yellow=.1.3.6.1.2.1.43.11.1.1.9.1.3
Black=.1.3.6.1.2.1.43.11.1.1.9.1.4

[Xerox WorkCentre 6605DN]
Location=.1.3.6.1.2.1.1.6.0
Cyan=.1.3.6.1.2.1.43.11.1.1.9.1.1
Magenta=.1.3.6.1.2.1.43.11.1.1.9.1.2
Yellow=.1.3.6.1.2.1.43.11.1.1.9.1.3
Black=.1.3.6.1.2.1.43.11.1.1.9.1.4
etc


2. The list of printers (PrinterList.dat)

 Code:
10.140.192.129
10.140.192.134
10.140.192.135
10.140.192.139
10.140.192.143
10.140.192.180
10.140.192.202
etc




kelp7
(Starting to like KiXtart)
2015-12-17 10:36 AM
Re: SNMP with Printers

Also, if you'd like me to comment it then I can spend some time doing so if necessary...

kelp7
(Starting to like KiXtart)
2015-12-17 11:05 AM
Re: SNMP with Printers

And I've just noticed that I could have moved all those $EmailNeeded = 1 statements to one single statement in the last IF statement of the WHILE loop.

NTDOCAdministrator
(KiX Master)
2015-12-17 10:14 PM
Re: SNMP with Printers

No problem. Just that shared code and idea is the main reason for this site. No matter who writes the code there is almost always another way to write it. Commenting code is a good practice to get into though as one can leave it sit for years then when you pick it back up and are rusty or someone else has to take over the code it makes it much easier to see what's going on when it is documented.

You don't have to comment the code here that you posted, but in your production code it would be a good idea.

Thanks for posting and sharing


kelp7
(Starting to like KiXtart)
2015-12-22 10:30 AM
Re: SNMP with Printers

No problem. I have since developed the script further where, in its report, it will now distinguish between new problem printers and ones which it has previously notified on. The new file (PrinterPrevious.dat) is just a list of IP addresses.

 Code:
Global $PreviousIP[200]
$x = Open(1, ".\1PrinterOut.txt", 5)
$x = Open(2, ".\PrinterList.dat", 2)
$x = Open(3, ".\PrinterPrevious.dat", 2)
$x = Open(4, ".\2PreviousOut.txt", 5)

$PreviousIP[0] = ReadLine(3)
$PreviousTotal = 0
While @ERROR = 0
  $PreviousTotal = $PreviousTotal + 1
  $PreviousIP[$PreviousTotal] = ReadLine(3)
Loop
$x = Close(3)

Del ".\PrinterPrevious.dat"
$x = Open(3, ".\PrinterPrevious.dat", 5)

$x = WriteLine(1, "The following printers are getting low on toner, please visit and assist:" + @CRLF + @CRLF)
$x = WriteLine(4, @CRLF + "Previously notified printers:" + @CRLF + @CRLF)
Dim $StoreVals[6]
$EmailNeeded = 0
$PrinterIP = ReadLine(2)
While @ERROR = 0

  ; Check we haven't reported this printer previously
  $PreviousReport = 0
  For $x = 0 To $PreviousTotal
    If $PreviousIP[$x] = $PrinterIP
      $PreviousReport = 1
    EndIf
  Next

  $Cmd = 'snmpget.exe -r:' + $PrinterIP + ' -o:.1.3.6.1.2.1.1.1.0 -q -t:20'
  $CmdResult = WshPipe($Cmd)
  $CmdResult = Join($CmdResult[0], @CRLF)
  $PModel = SubStr($CmdResult, Instr($CmdResult, "X"), (Instr($CmdResult, ";") - Instr($CmdResult, "X")))
  $Count = 0
  $Flag = 0
  $FlagPrevious = 0

  ; If the device is online and the device is a Xerox machine
  If Left($CmdResult, 1) <> "%" AND $PModel <> ""
    ; Get the supported values for a printer type
    $aIniVals = Split(ReadProfileString('.\PrinterData.ini', $PModel, ''), Chr(10))
    ; Make sure the device is one of those listed in the INI file otherwise report an error
    If UBound($aIniVals) > 0
      For Each $IniVal in $aIniVals
        If $IniVal
          $Oid = ReadProfileString('.\PrinterData.ini', $PModel, $IniVal)
          $Cmd = 'snmpget.exe -r:' + $PrinterIP + ' -o:' + $Oid + ' -q -t:20'
          $CmdResult = WshPipe($Cmd)
          $CmdResult = Join($CmdResult[0], @CRLF)
          If $IniVal <> "Location"
            $Cmd = 'snmpget.exe -r:' + $PrinterIP + ' -o:' + SUBSTR($Oid, 1, 23) + "8" + SUBSTR($Oid, 25, 4) + ' -q -t:20'
            $CmdResult2 = WshPipe($Cmd)
            $CmdResult2 = Join($CmdResult2[0], @CRLF)
            $CmdResult = CDbl($CmdResult)
            $CmdResult2 = CDbl($CmdResult2)
            $StoreVals[$Count] = ($CmdResult / $CmdResult2) * 100
          Else
            $StoreVals[$Count] = $CmdResult        
          EndIf
        EndIf
      $Count = $Count + 1
      Next
    Else
      $Count = 1
      $StoreVals[$Count] = "WARNING - Printer Model Not Found : Report this to 3rd line"
    EndIf

    $PrinterText = $PrinterIP + " : " + $PModel
    If $Count > 1
      $PrinterText = $PrinterText + " : " + SubStr($StoreVals[0], 1, Len($StoreVals[0]) - 2)
      For $x = 1 to ($Count - 2)
        If $StoreVals[$x] <= 5
          $PrinterText = $PrinterText + " : " + $aIniVals[$x] + " : " + $StoreVals[$x] + "%"
          $Flag = 1
          $EmailNeeded = 1
        EndIf
      Next
    EndIf

    If $Count = 1
      $PrinterText = $PrinterText + $PrinterIP + " : " + $StoreVals[$Count]
      $Flag = 1
      $EmailNeeded = 1
    EndIf      
  EndIf

  If $Count = 0
    $PrinterText = $PrinterIP + " : Device is offline (check IP)"
    $Flag = 1
    $EmailNeeded = 1
  EndIf

  If $Flag = 1 And $PreviousReport = 0
    $x = WriteLine(1, $PrinterText + @CRLF)
    $x = WriteLine(3, $PrinterIP + @CRLF)
  EndIf

  If $Flag = 1 And $PreviousReport = 1
    $x = WriteLine(4, $PrinterText + @CRLF)
    $x = WriteLine(3, $PrinterIP + @CRLF)
  EndIf

  $PrinterIP = ReadLine(2)
Loop

$x = Close(3)
$x = Close(4)
$x = Close(2)
$x = Close(1)

If $EmailNeeded
  Shell "CMD.EXE /C COPY /B C:\Scripts\*.txt C:\Scripts\Message.txt > nul"
  Shell "CMD.EXE /C C:\Scripts\blat.exe Message.txt -to blahblah@example.com -subject " + Chr(34) + "Printers Low In Toner" + Chr(34) + " -q"
EndIf
Del ".\Message.txt"
Del ".\1PrinterOut.txt"
Del ".\2PreviousOut.txt"
Exit