-
Oct 8th, 2000, 07:49 AM
#1
Thread Starter
New Member
I have a network of about 55 computers (netware & NT) all running Win98 workstations. We have about 5 network printers and copiers to which a computer can print. What I'd like to do is build, if possible, a simple VB program to intercept what they are printing (from any application) and capture certain information about the print jobs before it gets sent off to the specified printer.
For example, when a user selects print from the menu in MS Word, and after the Ok button is pressed on the printers dialog window, have my program then pop up asking the user to fill in specific information (who they want to charge for the print job...this is typically an internal billing code, etc.).
The program would have to capture the name/driver of the printer users are printing to, the document they printed, number of pages, number of copies, date/time, etc.
Is/are there Windows API's to help in my programming of this application? I've been, unsuccessfully, searching MSDN, web sites, etc. on how to intercept/detect a print job. Any help would be greatly appreciated!
Thanks ahead of time...
-
Oct 8th, 2000, 02:56 PM
#2
Fanatic Member
some idea's:
- Use EnumJobs and a timer, i will provide some code if nessecary. Not a good way
- Use C++ and build your own print monitor/driver(no clue how, just know it's very difficult)
- If NT Workstations then use FindFirstPrinterChangeNotification & related functions(must have NT Workstation)
hope this helps
GWDASH
[b]VB6, Perl, ASP, HTML, JavaScript, VBScript, SQL, C, C++, Linux , Java, PHP, MySQL, XML[b]
-
Oct 11th, 2000, 05:29 AM
#3
Thread Starter
New Member
Thanks for the info GW... If you would be so kind as to post some code to get me going, I'd appreciate it. I'm resigned to VB (v6) now, but would eventally like to move to C++, if possible. I know VB and very little of C.
Thanks again.
Steve
-
Oct 17th, 2000, 05:26 PM
#4
Hyperactive Member
I might take a look at the project for you
And I'll only ask for 1% of the estimated recovery your company makes due to correct billing codes
hehe
If you work for Lawyers or Accountants, that should make them balk..hehe
Anyhow I'll let you know if I can do it. Now where did that win32API book go?..
Regards
-
Oct 17th, 2000, 06:25 PM
#5
Hyperactive Member
Right then
OK I had a look and the API's needed are not that bad to use. To extract the user or machine name that submitted the job will take some time (structure not in api32.txt so I have to create them carefully lest I crash)
The reason we would need the machine name is to determine if the job just added to the queue was in fact this pc's.
Do all your PC's have computer names? I assume they do and that there are no duplicates. Tell me if this is not the case OK? I can't use username because if the user is logged in on two machines, they would get the prompt on both!
I'll let you know if a few hours how I have managed to get on. if someone posts you a solution before me, then all the better right ?
-
Oct 17th, 2000, 07:14 PM
#6
Fanatic Member
To Add to your discussion, see http://www.vbapi.com and the GetUserName Function. For Machine, useGetComputerName function.
Had to Change, wrong function name!!
[Edited by gwdash on 10-17-2000 at 10:24 PM]
GWDASH
[b]VB6, Perl, ASP, HTML, JavaScript, VBScript, SQL, C, C++, Linux , Java, PHP, MySQL, XML[b]
-
Oct 17th, 2000, 09:29 PM
#7
Hyperactive Member
damnation
Curses to the FindFirstPrinterChangeNotification API!
When I specify some PRINTER_NOTIFY_INFO in the call, I get back a handle of -1 and GetLastError returns 0. So I have no idea why it doesn't work. If I specify 0 (thats ok according to the documentation), I get a valid handle, but it seems to be for all queues on the network. In any case, it's for more printers than the one I am monitoring because it is right next to me. Unless people add jobs and delete them immediately or something...
Anyhow, I am writing this in case someone happens to be able to guess what's wrong, and to let SteveLG know that my intended solution is not yet ready! So far I can tell when jobs get added or deleted but I can't get any info about the job at all...
Grrrrr
-
Oct 18th, 2000, 03:07 PM
#8
Fanatic Member
Could you PLEASE give me the FindFirstPrinterChange Notification Code. I need it for an app i'm writing. I've been all over looking for it!!!
Just what you have so far is fine. if you do finish it, though, could you please send it to Me!!!
GWDASH
[b]VB6, Perl, ASP, HTML, JavaScript, VBScript, SQL, C, C++, Linux , Java, PHP, MySQL, XML[b]
-
Oct 18th, 2000, 08:20 PM
#9
Hyperactive Member
Here you are. Please let me know if you figure out the problem I have on the network.
I stuck with the code and finally worked out where I was going wrong although it was only a guess. It seems that I need to learn a bit more about the structure of a VB array as opposed to a C array.
In any case, the code works to this point :
Successfully sees any job related notification on the local queue (probably works also on any network queue that is not Netware!)
I only extract the printer name, user name and machine name ans status string for now. You can also get many other bits of info like bytes printed, total pages etc.
Yet to be done: Well there is alot to do! And these things are just for the spooler side of life.
1) use the JOB STATUS constants to work out what each stats is telling us (Easy)
2) respond to system events involving printers (probably hard - I ahven't looked at it yet). Currently, if the user prints to a printer we are not watching, then of course, we won't know.
Also, if a printer we ARE watching is renamed or deleted, we don't get to know about it. There is an API to use for this as well.
So without further ado, here is my progress to date (I am pleased to at least be able to deliver working code even though it is quite unsatisfactory in parts).
Cheers
Code:
VERSION 5.00
Begin VB.Form frmSpy
Caption = "Spooler Spy"
ClientHeight = 2595
ClientLeft = 1095
ClientTop = 1515
ClientWidth = 4485
LinkTopic = "Form1"
PaletteMode = 1 'UseZOrder
ScaleHeight = 2595
ScaleWidth = 4485
Begin VB.CommandButton cmdExit
Caption = "Exit"
Height = 375
Left = 1560
TabIndex = 2
Top = 1680
Width = 1095
End
Begin VB.CommandButton cmdSpy
Caption = "Spy"
Height = 375
Left = 1560
TabIndex = 0
Top = 240
Width = 1095
End
Begin VB.Label lblWatching
Height = 255
Left = 840
TabIndex = 1
Top = 960
Width = 2655
End
End
Attribute VB_Name = "frmSpy"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit
' Types with Suffix 2 are from Dan Appleman's API book but I think they are wrong
Private Type PRINTER_NOTIFY_OPTIONS2
Version As Long
Flags As Long
Count As Long
pTypes As Long
End Type
Private Type PRINTER_NOTIFY_OPTIONS_TYPE2
Type As Integer
Reserved0 As Integer
Reserved1 As Long
Reserved2 As Long
Count As Long
pFields As Long
End Type
Private Type PRINTER_NOTIFY_INFO2
Version As Long
Flags As Long
Count As Long
End Type
Private Type PRINTER_NOTIFY_INFO_DATA2
Type As Integer
Field As Integer
Reserved As Long
Id As Long
Buf As Long
End Type
' suffix 1 are from MSDN documentation
Private Type PRINTER_NOTIFY_INFO_DATA1
Type As Integer
Field As Integer
Reserved As Long
Id As Long
cbBuf As Long ' part of union also awData[0]
pBuf As Long ' part of union
End Type
Private Type PRINTER_NOTIFY_OPTIONS_TYPE1
Type As Integer
Reserved0 As Integer
Reserved1 As Long
Reserved2 As Long
Count As Long
pFields As Long ' to array of Integer
End Type
Private Type PRINTER_NOTIFY_OPTIONS1
Version As Long
Flags As Long
Count As Long
pTypes As Long 'to array of PRINTER_NOTIFY_OPTIONS_TYPE
End Type
Private Type PRINTER_NOTIFY_INFO1
Version As Long
Flags As Long
Count As Long
aData As Long ' to array of PRINTER_NOTIFY_INFO_DATA
End Type
' this is also form Dan's book...conflicting?
' but it's the winner
Private Type PRINTER_NOTIFY_INFO3
Version As Long
Flags As Long
Count As Long
aData(4) As PRINTER_NOTIFY_INFO_DATA1 ' Varies
' this works but only because I have specified adata(4) here when
' I know I am only asking for 3 pnid's
' I need to learn how to use a pointer to a VB array which is what adata
End Type
Private Type PRINTER_DEFAULTS
pDatatype As String
pDevMode As Long
DesiredAccess As Long
End Type
Private Const PRINTER_CHANGE_ADD_FORM = &H10000
Private Const PRINTER_CHANGE_ADD_JOB = &H100
Private Const PRINTER_CHANGE_ADD_PORT = &H100000
Private Const PRINTER_CHANGE_ADD_PRINT_PROCESSOR = &H1000000
Private Const PRINTER_CHANGE_ADD_PRINTER = &H1
Private Const PRINTER_CHANGE_ADD_PRINTER_DRIVER = &H10000000
Private Const PRINTER_CHANGE_ALL = &H7777FFFF
Private Const PRINTER_CHANGE_CONFIGURE_PORT = &H200000
Private Const PRINTER_CHANGE_DELETE_FORM = &H40000
Private Const PRINTER_CHANGE_DELETE_JOB = &H400
Private Const PRINTER_CHANGE_DELETE_PORT = &H400000
Private Const PRINTER_CHANGE_DELETE_PRINT_PROCESSOR = &H4000000
Private Const PRINTER_CHANGE_DELETE_PRINTER = &H4
Private Const PRINTER_CHANGE_DELETE_PRINTER_DRIVER = &H40000000
Private Const PRINTER_CHANGE_FAILED_CONNECTION_PRINTER = &H8
Private Const PRINTER_CHANGE_FORM = &H70000
Private Const PRINTER_CHANGE_JOB = &HFF00
Private Const PRINTER_CHANGE_PORT = &H700000
Private Const PRINTER_CHANGE_PRINT_PROCESSOR = &H7000000
Private Const PRINTER_CHANGE_PRINTER = &HFF
Private Const PRINTER_CHANGE_PRINTER_DRIVER = &H70000000
Private Const PRINTER_CHANGE_SET_FORM = &H20000
Private Const PRINTER_CHANGE_SET_JOB = &H200
Private Const PRINTER_CHANGE_SET_PRINTER = &H2
Private Const PRINTER_CHANGE_SET_PRINTER_DRIVER = &H20000000
Private Const PRINTER_CHANGE_TIMEOUT = &H80000000
Private Const PRINTER_CHANGE_WRITE_JOB = &H800
Private Const WAIT_FAILED = -1&
Private Const WAIT_OBJECT_0 = 0
Private Const WAIT_ABANDONED = &H80&
Private Const WAIT_ABANDONED_0 = &H80&
Private Const WAIT_TIMEOUT = &H102&
Private Const WAIT_IO_COMPLETION = &HC0&
Private Const STILL_ACTIVE = &H103&
Private Const INFINITE = -1&
Private Const STANDARD_RIGHTS_REQUIRED = &HF0000
Private Const PRINTER_ACCESS_ADMINISTER = &H4
Private Const PRINTER_ACCESS_USE = &H8
Private Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)
Private Const PRINTER_NOTIFY_FIELD_SERVER_NAME = &H0
Private Const PRINTER_NOTIFY_FIELD_PRINTER_NAME = &H1
Private Const PRINTER_NOTIFY_FIELD_SHARE_NAME = &H2
Private Const PRINTER_NOTIFY_FIELD_PORT_NAME = &H3
Private Const PRINTER_NOTIFY_FIELD_DRIVER_NAME = &H4
Private Const PRINTER_NOTIFY_FIELD_COMMENT = &H5
Private Const PRINTER_NOTIFY_FIELD_LOCATION = &H6
Private Const PRINTER_NOTIFY_FIELD_DEVMODE = &H7
Private Const PRINTER_NOTIFY_FIELD_SEPFILE = &H8
Private Const PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR = &H9
Private Const PRINTER_NOTIFY_FIELD_PARAMETERS = &HA
Private Const PRINTER_NOTIFY_FIELD_DATATYPE = &HB
Private Const PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR = &HC
Private Const PRINTER_NOTIFY_FIELD_ATTRIBUTES = &HD
Private Const PRINTER_NOTIFY_FIELD_PRIORITY = &HE
Private Const PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY = &HF
Private Const PRINTER_NOTIFY_FIELD_START_TIME = &H10
Private Const PRINTER_NOTIFY_FIELD_UNTIL_TIME = &H11
Private Const PRINTER_NOTIFY_FIELD_STATUS = &H12
Private Const PRINTER_NOTIFY_FIELD_STATUS_STRING = &H13
Private Const PRINTER_NOTIFY_FIELD_CJOBS = &H14
Private Const PRINTER_NOTIFY_FIELD_AVERAGE_PPM = &H15
Private Const PRINTER_NOTIFY_FIELD_TOTAL_PAGES = &H16
Private Const PRINTER_NOTIFY_FIELD_PAGES_PRINTED = &H17
Private Const PRINTER_NOTIFY_FIELD_TOTAL_BYTES = &H18
Private Const PRINTER_NOTIFY_FIELD_BYTES_PRINTED = &H19
Private Const JOB_NOTIFY_FIELD_PRINTER_NAME = &H0
Private Const JOB_NOTIFY_FIELD_MACHINE_NAME = &H1
Private Const JOB_NOTIFY_FIELD_PORT_NAME = &H2
Private Const JOB_NOTIFY_FIELD_USER_NAME = &H3
Private Const JOB_NOTIFY_FIELD_NOTIFY_NAME = &H4
Private Const JOB_NOTIFY_FIELD_DATATYPE = &H5
Private Const JOB_NOTIFY_FIELD_PRINT_PROCESSOR = &H6
Private Const JOB_NOTIFY_FIELD_PARAMETERS = &H7
Private Const JOB_NOTIFY_FIELD_DRIVER_NAME = &H8
Private Const JOB_NOTIFY_FIELD_DEVMODE = &H9
Private Const JOB_NOTIFY_FIELD_STATUS = &HA
Private Const JOB_NOTIFY_FIELD_STATUS_STRING = &HB
Private Const JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR = &HC
Private Const JOB_NOTIFY_FIELD_DOCUMENT = &HD
Private Const JOB_NOTIFY_FIELD_PRIORITY = &HE
Private Const JOB_NOTIFY_FIELD_POSITION = &HF
Private Const JOB_NOTIFY_FIELD_SUBMITTED = &H10
Private Const JOB_NOTIFY_FIELD_START_TIME = &H11
Private Const JOB_NOTIFY_FIELD_UNTIL_TIME = &H12
Private Const JOB_NOTIFY_FIELD_TIME = &H13
Private Const JOB_NOTIFY_FIELD_TOTAL_PAGES = &H14
Private Const JOB_NOTIFY_FIELD_PAGES_PRINTED = &H15
Private Const JOB_NOTIFY_FIELD_TOTAL_BYTES = &H16
Private Const JOB_NOTIFY_FIELD_BYTES_PRINTED = &H17
Private Const PRINTER_NOTIFY_TYPE = &H0
Private Const JOB_NOTIFY_TYPE = &H1
Private Const INVALID_HANDLE_VALUE = -1
Private Const PRINTER_NOTIFY_OPTIONS_REFRESH = &H1
Private Const PRINTER_NOTIFY_INFO_DISCARDED = &H1
Private Const JOB_STATUS_BLOCKED_DEVQ = &H200
Private Const JOB_STATUS_DELETED = &H100
Private Const JOB_STATUS_DELETING = &H4
Private Const JOB_STATUS_ERROR = &H2
Private Const JOB_STATUS_OFFLINE = &H20
Private Const JOB_STATUS_PAPEROUT = &H40
Private Const JOB_STATUS_PAUSED = &H1
Private Const JOB_STATUS_PRINTED = &H80
Private Const JOB_STATUS_PRINTING = &H10
Private Const JOB_STATUS_RESTART = &H800
Private Const JOB_STATUS_SPOOLING = &H8
Private Const JOB_STATUS_USER_INTERVENTION = &H10000
Private Declare Function FindFirstPrinterChangeNotification& Lib "winspool.drv" (ByVal hPrinter As Long, ByVal fdwFlags As Long, ByVal fdwOptions As Long, ByVal pPrinterNotifyOptions As Long)
Private Declare Function FindNextPrinterChangeNotification& Lib "winspool.drv" (ByVal hChange As Long, pdwChange As Long, ByVal pPrinterNotifyOptions As Long, ppPrinterNotifyInfo As Long)
Private Declare Function FindClosePrinterChangeNotification& Lib "winspool.drv" (ByVal hChange As Long)
Private Declare Function FreePrinterNotifyInfo Lib "winspool.drv" (ByVal addr As Long) As Long
Private Declare Function OpenPrinter& Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, pDefault As PRINTER_DEFAULTS)
Private Declare Function ClosePrinter& Lib "winspool.drv" (ByVal hPrinter As Long)
Private Declare Function WaitForSingleObject& Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long)
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function GetLastError Lib "kernel32" () As Long
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
Dim hNotification As Long
Dim hPrinter As Long
Dim quitFlag As Boolean
Dim watching As Boolean
Dim s1 As String, s2 As String
Private Sub cmdExit_Click()
quitFlag = True
If Not watching Then Unload Me
End Sub
Private Sub cmdSpy_Click()
watching = True
lblWatching.Caption = watching
Dim res As Long
Dim lFlags As Long
Dim x As Long
Dim c As Integer
Dim mbres As Long
mbres = vbOK
Dim pDefault As PRINTER_DEFAULTS
With pDefault
.pDatatype = vbNullString
.pDevMode = 0
.DesiredAccess = PRINTER_ACCESS_USE
End With
If hPrinter <> 0 Then Call ClosePrinter(hPrinter)
res = OpenPrinter(Printer.DeviceName, hPrinter, pDefault)
If res = 0 Then
Debug.Print "Unable to open printer " & Printer.DeviceName & " " & GetLastError
Exit Sub
Else
Debug.Print "Open printer " & Printer.DeviceName
End If
Dim pni As PRINTER_NOTIFY_INFO3
Dim pnid() As PRINTER_NOTIFY_INFO_DATA1
Dim pnot As PRINTER_NOTIFY_OPTIONS_TYPE1
Dim pno As PRINTER_NOTIFY_OPTIONS1
Dim myData(4) As PRINTER_NOTIFY_INFO_DATA1
Dim myOptions(0) As PRINTER_NOTIFY_OPTIONS_TYPE1
Dim myInfo(4) As Integer
Dim ppni As Long, ppno As Long
myInfo(0) = JOB_NOTIFY_FIELD_MACHINE_NAME
myInfo(1) = JOB_NOTIFY_FIELD_USER_NAME
myInfo(2) = JOB_NOTIFY_FIELD_PRINTER_NAME
myInfo(3) = JOB_NOTIFY_FIELD_TOTAL_PAGES
myInfo(4) = JOB_NOTIFY_FIELD_STATUS
With myOptions(0)
.Type = JOB_NOTIFY_TYPE
.Count = 5
.pFields = VarPtr(myInfo(0))
End With
With myData(0)
.Type = JOB_NOTIFY_TYPE
.Field = JOB_NOTIFY_FIELD_MACHINE_NAME
End With
With myData(1)
.Type = JOB_NOTIFY_TYPE
.Field = JOB_NOTIFY_FIELD_USER_NAME
End With
With myData(2)
.Type = JOB_NOTIFY_TYPE
.Field = JOB_NOTIFY_FIELD_PRINTER_NAME
End With
With myData(3)
.Type = JOB_NOTIFY_TYPE
.Field = JOB_NOTIFY_FIELD_PAGES_PRINTED
End With
With myData(4)
.Type = JOB_NOTIFY_TYPE
.Field = JOB_NOTIFY_FIELD_STATUS_STRING
End With
With pno
.Count = 1
.Version = 2
.pTypes = VarPtr(myOptions(0))
.Flags = PRINTER_NOTIFY_OPTIONS_REFRESH
End With
ppno = VarPtr(pno)
' option 1
' OK
'hNotification = FindFirstPrinterChangeNotification(hPrinter, PRINTER_CHANGE_JOB, 0, 0)
'option2 was crap so it's gone -
'option 3
' results in dll error 120 (This function is not supported on this system. )
' OK when not using network printer
hNotification = FindFirstPrinterChangeNotification(hPrinter, 0, 0, ppno)
'option 4
' results in dll error 120 (This function is not supported on this system. )
' OK when not using network printer
'hNotification = FindFirstPrinterChangeNotification(hPrinter, PRINTER_CHANGE_JOB, 0, ppno)
If hNotification = INVALID_HANDLE_VALUE Then
Debug.Print "Unable to create notification object " & GetLastError
watching = False
lblWatching.Caption = watching
Exit Sub
End If
Do
' currently, with option 1 above, I get a signal of -256 every 10 seconds!
' which is not documented. I assume somehing on the network is doing this
' perhaps to keep the queue refreshed or something??
' my printer queue in the office is called "\\AKTHSE1\THSE11_4SI_MP_UX"
' when a real job is queued, I don't get a signal
' stop the press! it works fine for a printer I set up locally (FILE:)
' so it must be to do with the network or the Netware queue.
' Continuing with tests on local queue instead.
res = WaitForSingleObject(hNotification, 500)
If res = WAIT_TIMEOUT Then
' do nothing. set quitflag if you want to
Else
res = FindNextPrinterChangeNotification(hNotification, lFlags, 0, ppni)
Debug.Print res, lFlags, GetLastError
If (lFlags And PRINTER_CHANGE_ADD_JOB) = PRINTER_CHANGE_ADD_JOB Then
Debug.Print Now & " Job was added"
End If
If (lFlags And PRINTER_CHANGE_WRITE_JOB) = PRINTER_CHANGE_WRITE_JOB Then
Debug.Print Now & " Job was written"
End If
If (lFlags And PRINTER_CHANGE_DELETE_JOB) = PRINTER_CHANGE_DELETE_JOB Then
Debug.Print Now & " Job was deleted"
End If
If ppni <> 0 Then
CopyMemory ByVal (VarPtr(pni)), ByVal ppni, Len(pni)
Debug.Print "pni:", "Flags", "Count", "Version", "aData"
Debug.Print "pni:", pni.Flags, pni.Count, pni.Version, VarPtr(pni.aData(0))
If pni.Count > 0 Then
'ReDim pnid(pni.Count - 1)
' tricky stuff. aData is not a pointer but the first
' byte of the array of pnid
' I might have a problem here because the pBuf seems
' to point to a buffer, but I can't get the string out of it
'CopyMemory pnid(0), addr, Len(pnid(0)) * pni.Count
' attempt # 2 - maybe the aData points to a safearray?
' darn documentation is hard to follow
pnid = pni.aData 'will this work?
If (pni.Flags And PRINTER_NOTIFY_INFO_DISCARDED) = PRINTER_NOTIFY_INFO_DISCARDED Then
Debug.Print "Some data was discarded "
' to be done: use PRINTER_NOTIFY_OPTIONS_REFRESH to get the discarded data
End If
Debug.Print "pnid : ", "Type", "Field", "Id", "cbBuf", "pBuf"
For c = 0 To UBound(pnid)
Debug.Print "pnid : ", pnid(c).Type, pnid(c).Field, pnid(c).Id, pnid(c).cbBuf, pnid(c).pBuf,
PrintPrinterNotifyInfoData pnid(c)
Next
End If
res = FreePrinterNotifyInfo(ppni)
End If
End If
DoEvents
Loop While Not quitFlag
watching = False
lblWatching.Caption = watching
If quitFlag Then Unload Me
End Sub
Private Sub PrintPrinterNotifyInfoData(pnid As PRINTER_NOTIFY_INFO_DATA1)
With pnid
Select Case .Type
Case PRINTER_NOTIFY_TYPE
Case JOB_NOTIFY_TYPE
Select Case .Field
Case JOB_NOTIFY_FIELD_PRINTER_NAME
Debug.Print "Printer Name: " & GetStringFromLPSTR(.pBuf, .cbBuf),
Case JOB_NOTIFY_FIELD_MACHINE_NAME
Debug.Print "Machine Name: " & GetStringFromLPSTR(.pBuf, .cbBuf),
Case JOB_NOTIFY_FIELD_USER_NAME
Debug.Print "User Name: " & GetStringFromLPSTR(.pBuf, .cbBuf),
Case JOB_NOTIFY_FIELD_STATUS_STRING
Debug.Print "Status: " & GetStringFromLPSTR(.pBuf, .cbBuf),
Case JOB_NOTIFY_FIELD_PAGES_PRINTED
Debug.Print "Pages Printed: " & CStr(.cbBuf),
Case JOB_NOTIFY_FIELD_TOTAL_BYTES
Debug.Print "Total Bytes: " & CStr(.cbBuf),
Case JOB_NOTIFY_FIELD_TOTAL_PAGES
Debug.Print "Total Pages: " & CStr(.cbBuf),
Case JOB_NOTIFY_FIELD_STATUS
Debug.Print "Status: " & CStr(.cbBuf),
Case Else
Debug.Print "Unparsed filed value = " & .Field,
End Select
End Select
End With
Debug.Print
End Sub
Private Function GetStringFromLPSTR(ByVal lpstr As Long, ByVal chars As Long) As String
Dim myStringRes As String
Dim bString() As Byte
Dim c As Long
Dim pos1 As Long
c = 40
' lpstr is wide string that is null terminated
' I've messed around in here to try to get it working
' but it doesn't look like a string in here at all...
' finally working I think...
If chars <= 0 Then Exit Function
ReDim bString(chars - 1)
CopyMemory bString(0), ByVal lpstr, chars
myStringRes = StrConv(bString, vbUnicode)
GetStringFromLPSTR = Left(myStringRes, InStr(1, myStringRes, Chr(0)))
End Function
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If Not quitFlag And watching Then
quitFlag = True
Cancel = True
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
If hNotification <> 0 Then FindClosePrinterChangeNotification (hNotification)
If hPrinter <> 0 Then ClosePrinter hPrinter
End Sub
Let me know if you find it useful..
-
Oct 19th, 2000, 07:41 AM
#10
This is some cool code...
I'm in need of something similar, have a look at my problem and let me please know what you think of it?
Problem: In a school, students are printing, and now have to pay an amount of money for each color/black&white print.
They pay this when they pick up the paper from the printer, where now somebody is sitting al day. (Price is $0.10 for BW and $0.25 for color but that's not what this is about). What I'd like to do is capture the printjob before it goes to the printer. Then, on a "billing" computer students must use their school-passes to enter a valid code and or password, and when this code is valid it is send to the server as a "go on, print it". If not, the print-job will be dropped after some time (say 5 mins). The "bills" will be printed monthly or so...
In short: Student prints, goes to computer to enter his/her code and the print comes out. If code is invalid or a "time-out" occurs, the printjob is cancelled.
The part of the billing-computer, communication with the server and so on I can do. But for catching the printjobs and "holding them" is where I depend on you guys! I'm hoping you'd take a thought about my problem and tell me if you'd like to help me solve it... (I'd like to help solving too ... )
Any ideas or suggestions this far?
-
Oct 19th, 2000, 07:45 AM
#11
I just had a (great) idea: Is it possible using VB to write my own "printer-driver"? If so, I could use the student's computers to send the printjob to my driver, pop-up a window (or share the printer on the "billing-computer") and make them enter the code. Then I could "forward" the printjob to the desired printer. This way I'd be in full control over the print-job...
Any ideas?
-
Oct 19th, 2000, 10:23 AM
#12
Fanatic Member
You can use the API to Register A "Monitor" to do that, but i don't think it can be done in VB
GWDASH
[b]VB6, Perl, ASP, HTML, JavaScript, VBScript, SQL, C, C++, Linux , Java, PHP, MySQL, XML[b]
-
Oct 19th, 2000, 05:11 PM
#13
Hyperactive Member
Change of mind
After rwading about Print Monitors I realise that this is not the way to go because a Print Monitor works between the spooler and the printer. By then, the helpful user with the info they need to tell us have gone...
Also, my previous attempt is of limited use as well for the same reason.
So I've started to look at PrintHookProc. Setting up a hook so that the instant the user click Print In any application (and to any printer) on that machine, then our code can run. For monitored network printers we could popup a dialog asking for certain information. If they don't provide it then we don't pass on the print command.
It's an idea only and it is a little advance for me at present. I have to go off and read about hooking in general so if anyone else is game enough to have a look, then let us know please
Cheers
-
Oct 22nd, 2000, 02:45 AM
#14
Hyperactive Member
Was this thread of use toi anyone?
SteveLG, gwdash?
Just wondering.
Regards
-
Oct 24th, 2000, 04:22 PM
#15
Member
this has me thinking
OK, now that i'm totally confused and brain storming like crazy. I start to wonder...
Will any of this work on a local PC & printer? If I wanted a simple app to keep track of everything going to the printer, could i use this code, or would i have to make any changes in it?
BTW.. Anyone know the name of the driver that controls that spooler dialog?
-
Oct 24th, 2000, 04:44 PM
#16
Hyperactive Member
Locally works fine
-
Oct 25th, 2000, 03:39 PM
#17
Fanatic Member
GWDASH
[b]VB6, Perl, ASP, HTML, JavaScript, VBScript, SQL, C, C++, Linux , Java, PHP, MySQL, XML[b]
-
Nov 14th, 2000, 04:10 PM
#18
New Member
SteveLG:
There's a neat program called 'RedMon' (Redirection Port Monitor), that comes with the Win32 port of Ghostscript, which might be handy for what you're trying to do.
It basically takes a print job within Win95/98/NT and feeds it into the stdin of a program, such as Ghostscript. It also comes with a program called 'redrun', which copies its stdio (the printed document) to a temporary file on disk and then runs another program. Like a print manager you're attempting to create.
Here's the URL for redrun:
http://www.cs.wisc.edu/~ghost/redmon/index.html
There's a few other interesting tidbits on the page, including information on how to set up RedMon and Ghostscript to write .pdf files, as a free alternative to Adobe's PDFWriter software.
Hope this helps.
-
Jul 10th, 2018, 06:51 PM
#19
Fanatic Member
Re: Help!!! API to Intercept Print Jobs?
Originally Posted by ;145719
This is some cool code...
I'm in need of something similar, have a look at my problem and let me please know what you think of it?
Problem: In a school, students are printing, and now have to pay an amount of money for each color/black&white print.
They pay this when they pick up the paper from the printer, where now somebody is sitting al day. (Price is $0.10 for BW and $0.25 for color but that's not what this is about). What I'd like to do is capture the printjob before it goes to the printer. Then, on a "billing" computer students must use their school-passes to enter a valid code and or password, and when this code is valid it is send to the server as a "go on, print it". If not, the print-job will be dropped after some time (say 5 mins). The "bills" will be printed monthly or so...
In short: Student prints, goes to computer to enter his/her code and the print comes out. If code is invalid or a "time-out" occurs, the printjob is cancelled.
The part of the billing-computer, communication with the server and so on I can do. But for catching the printjobs and "holding them" is where I depend on you guys! I'm hoping you'd take a thought about my problem and tell me if you'd like to help me solve it... (I'd like to help solving too ... )
Any ideas or suggestions this far?
My suggestion is to use a web server. The client passes the document, and the print command, the server accepts the document, prints it. Returns the print success. The way the type cloud prints.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|