|
|
|||||||
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! |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
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... |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
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! |
||||||||
|
|
|||||||
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 !! |
||||||||
|
|
|||||||
What is ENDPRINTER? If its a comment it should start with # or ;. |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
Kelp, So - as Allen pointed out, the built-in ReadProfileString has some pretty useful capabilities. Code: $List = ReadProfileString('inifile.ini', 'Xerox 6600') Code: $aList = Split($List, @CRLF) So - to find out how many parameters you have: Code: $Params = UBound($aList) 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 Glenn Hey Allen - when the hell did "built-in" become "inbuilt"? |
||||||||
|
|
|||||||
Basta! |
||||||||
|
|
|||||||
LOL... scripting for over a decade causes spots of memory starvation so be kind Glenn :-) |
||||||||
|
|
|||||||
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"! (I like me just the way I am and have no plans to revert to anyone else!) Glenn |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
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). |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
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!! |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
Hey - don't be hangin' around spreading those germy bits 'n bytes! Feel better! |
||||||||
|
|
|||||||
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... |
||||||||
|
|
|||||||
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 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 |
||||||||
|
|
|||||||
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! |
||||||||
|
|
|||||||
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! |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
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... |
||||||||
|
|
|||||||
(Perhaps 'VAL()' is my answer to this one...) |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
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! |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
Try Code: cdbl($inivalue) |
||||||||
|
|
|||||||
Interesting, okay thanks, I'll look that function up. |
||||||||
|
|
|||||||
Perfect Thanks for that, it works. |
||||||||
|
|
|||||||
Originally Posted By: kelp7 Really do not want integers! Going to go straight to Glenn's website now and look through some UDFs! 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 |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
Script finished and operational running twice a day via windows task scheduler. Thanks guys for all your input and help. |
||||||||
|
|
|||||||
Great. Can you post a final code solution you came up with? Thanks |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
Also, if you'd like me to comment it then I can spend some time doing so if necessary... |
||||||||
|
|
|||||||
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. |
||||||||
|
|
|||||||
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 |
||||||||
|
|
|||||||
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 |