Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

"Printer not ready", but client is not trying to print

Sydney Savoy

Programmer
Jan 15, 2024
2
CA
One of my company's clients recently lost access to an old printer, and ever since then, when she tries to run an export on our program, she receives the error message, "Printer not ready". Changing her default printer has not fixed it.

The trouble is, she's not even trying to print! The export writes and then displays a simple text file.

I haven't been able to reproduce the error on any system I can use for debugging; it's only on the machines of two users in the same client company.

I've pasted the code below. What could be causing this issue?

lparameter lheading

local lnPage_Wdth, lcDevice, lnPage_len, lcRepFile, lcRepBak, lcPath, mOk
sele spsrep
goto top
lnPage_Wdth = 160
lnPage_len = 59
mpage_no = 0
this.lnLine = 1
lcDevice = set('device')
if !set('device',1)==lcDevice
lcDevice = lcDevice+" "+set('device',1)
endif
if isnull(this.repfilenm) or empty(this.repfilenm)
this.repfilenm = left(thisform.tag,5)+"REP.TXT"
else
if at('.',this.repfilenm) = 0
this.repfilenm = this.repfilenm + '.TXT'
endif
endif
lcPath = thisform.spsrep.getreppath()
lcRepFile = lcPath+this.repfilenm
lcRepBak = lcPath+left(this.repfilenm,rat('.',this.repfilenm)) + 'BAK'
if file(lcRepBak)
delete file (lcRepBak)
endif
if file(lcRepFile)
rename (lcRepFile) to (lcRepBak)
endif

mOk = fcreate(lcrepfile)
fclose(mOk)
if mOk > 0
set device to FILE (lcRepFile)
else
ogx.gmessagebox('Invalid or inaccessable Path: '+lcPath, 16, thisform.Caption)
this.errorflag = .T.
return .f.
endif

if reccount() = 0
this.spsh(lnPage_Wdth, lheading)
@ this.lnLine+1,10 say ogx.oxlt.translateword("********** NOTHING TO PRINT ************")
if used('spsrep')
use in spsrep
endif
set device to &lcDevice
return
endif
this.lnLine = 1
this.spsh(lnPage_Wdth, lheading)

mbt_no = space(4)
mpst_mth = ' '
mfscl_yr = space(4)
mblank_msg = .f.
scan
if mblank_msg
mblank_msg = .f.
if empty(nvl(fscl_yr,'')) and empty(nvl(pst_mth,0)) and empty(nvl(bt_cd,'')) and empty(nvl(vc_ctl,''));
and empty(nvl(py_nm,'')) and empty(nvl(cur_cd,'')) and not empty(nvl(msg,''))
* print message on same line, carry over to next line on right most space rather than truncate
if len(msg) <= 50
@ this.lnLine,110 say left(msg, 50)
else
@ this.lnLine,110 say substr(msg,1,rat(' ',left(msg,50)))
this.lnLine = this.lnLine + 1
@ this.lnLine,110 say substr(msg,rat(' ',left(msg,50)),50)
endif
this.lnLine = this.lnLine + 1
loop
else
this.lnLine = this.lnLine + 1
endif
endif
if this.lnLine >= lnPage_len - 8
this.spsh(lnPage_Wdth, lheading)
endif

@ this.lnLine,0 say fscl_yr
@ this.lnLine,6 say padl(pst_mth, 2, '0')
@ this.lnLine,10 say bt_cd
@ this.lnLine,16 say vc_ctl
@ this.lnLine,24 say left(py_nm, 44)
if nvl(amt,0) <> 0 or not empty(vc_ctl)
@ this.lnLine,69 say amt pict "9,999,999,999.99"
endif
if this.ShowFCur and (nvl(chq_amt,0) <> 0 or not empty(vc_ctl))
@ this.lnLine,86 say chq_amt pict "9,999,999,999.99"
@ this.lnLine,103 say cur_cd
endif
if not empty(msg)
* print message on same line, carry over to next line on right most space rather than truncate
if len(msg) <= 50
@ this.lnLine,110 say left(msg, 50)
else
@ this.lnLine,110 say substr(msg,1,rat(' ',left(msg,50)))
this.lnLine = this.lnLine + 1
@ this.lnLine,110 say substr(msg,rat(' ',left(msg,50)),50)
endif
this.lnLine = this.lnLine + 1
mblank_msg = .f.
else
mblank_msg = .t.
endif
endscan

set device to &lcDevice
if used('spsrep')
use in spsrep
endif
return
 

If you get that error message it points out their device setting is PRINTER instead of SCREEN or FILE.
 
My guess is that your SET DEVICE TO FILE is either pointing to an invalid location, an invalid filename, or the user does not have sufficient write access to that location.
 
Code:
lcDevice = set('device')
if !set('device',1)==lcDevice
lcDevice = lcDevice+" "+set('device',1)
endif
That makes no sense, what would make sense to me would be

Code:
If Set('Device') == "FILE"
lcDevice = "FILE "+Set('Device',1)
Else
lcDevice = "FILE default.txt"
Endif
 
I think it's even simpler as you use
Code:
set device to FILE (lcRepFile)
for all your @ say commands to output to that file.

The code seems to try to reset set device setting to what it was initially. Well, that's only working halfways.
Wither you just finally SET DEVICE TO SCREEN or to set it to the default Windows printer use
SET DEVICE TO PRINTER (SET('PRINTER',2))

If SET('DEVICE') is just PRINTER and you finally SET DEVICE TO PRINTER, you might point to a printer not existing, which causes that error.
 
My guess is that your SET DEVICE TO FILE is either pointing to an invalid location, an invalid filename, or the user does not have sufficient write access to that location.

This sounds like the likely culprit, thank you. How would one implement checking for permission to write to a location, for user-friendly error messaging?

The code seems to try to reset set device setting to what it was initially. Well, that's only working halfways.
Wither you just finally SET DEVICE TO SCREEN or to set it to the default Windows printer use
SET DEVICE TO PRINTER (SET('PRINTER',2))

If SET('DEVICE') is just PRINTER and you finally SET DEVICE TO PRINTER, you might point to a printer not existing, which causes that error.

This one also seems fairly likely. If this is the problem I assume there's no simple way to test for it, other than a custom ON ERROR procedure?
 
no simple way to test for it, other than a custom ON ERROR procedure?
What is difficult about a custom ON ERROR procedure?
Even if you just make it save error number, linenumber, program etc. into an error log file and just display the error message to the user, you would now not need to guess in which line the error actually gets triggered. And that would be very very very very very very very very helpful.

I forgot to say very.
 
Look, if you don't have any error handling you can't go wrong in establishing a simple handler.

First notice, as a developer not having ON ERROR set up means in case of an error you get the error message box with several buttons of which one is "suspend". Which is a nice feature during development, because clicking that, starting the debugger, you actually see where the error came from.

But, that suspend button doesn't exit when an error happens in an EXE, so end users don't have this, they have no IDE, no debugger, no source code.

The help gives you a sample about ON ERROR that's already better than that default.
 
MY final guess, I could be wrong:

When you establish ON ERROR you'll get errors logged from all over the place not within this code. Assumption about this is that the (almost) final code is the root of problems starting after it ran:
Code:
set device to &lcDevice

lcDevice is determined at the code start and overall this looks like resetting the DEVICE setting to what it was previously to this code using a FILE as device.

You could almost safely assume the initial device is SCREEN, as that's the normal interface of an application, neither a printer nor a file. So the natural end would be SET DEVICE TO SCREEN and you don't need to initially determine the current SET("Device") and SET("Device",1) in the first part of the code at all.

Based on my assumption all the error logged will point to @...SAY commands that work otherwise, just not after this file output did run.
 
This sounds like the likely culprit, thank you. How would one implement checking for permission to write to a location, for user-friendly error messaging?



This one also seems fairly likely. If this is the problem I assume there's no simple way to test for it, other than a custom ON ERROR procedure?
You may have a look on try catch endtry
for file checking you may use ntest = Fcreate(cfile) - if ntest=-1 (error) , check help / hackers guide on lowlevel functions
 

Part and Inventory Search

Sponsor

Back
Top