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!

API Error 23 or 27 from ShellExecute opening a Pdf

Status
Not open for further replies.

Richard Guelzow

Programmer
Jan 6, 2022
22
US
Hi all - I'm puzzled by this one and not been able to come up with an answer to what I am observing. I have used ShellExecute to open documents [pdf, doc, jpeg] in my app for 20 years with no problems and no errors. I instantiate ShellExecute in my main.prg and use it throughout the app. Recently I have added the ability to download lab results into the app with the addition of downloading a pdf copy of the lab report as well as the actual lab values. Once downloaded, my app adds the location of the file to lab & documents tables. I can then open the pdf from the patient documents list using ShellExecute and it works as it always has.

My problem occurs with the new usage of ShellExecute from the lab form. I have code placed in a form method just as I do with the documents:
Code:
LOCAL cFilename
m.cFilename = patlab.pdfpath
ShellExecute(0,"open",m.cFilename,"","",1)

I have a button on the form that calls the form method and when I click button an API error 23 or 27 is generated depending on the computer system and then the pdf opens. I have been unable to determine the cause of the error. I have cleared ShellExecute and re-instantiated it locally in this form method - no difference. The pdf opens with no error in one part of the app and with a repeatable API error in this part. Any thoughts on where to go with this would be much appreciated. Thanks in advance.

Richard
 
Well, one thing should be clear, your ShellExecute call is not the problem, but the file association.

Monitor on which computers of all installation it only works sometimes. There's something going wrong with the file association.
Aside of that you could clearly improve your error message to include location of the error. Lineno and program. The basic usage example of ON ERROR in the help already teaches you to use LINENO() and PROGRAM().

Chriss
 
The other thing you can use is coverage logging. It's shooting birds with a cannon. But you get more out of it than the call stack tells you. And even that call stack info you have is not fully shown, every array row of the array
AStackInfo creates also tells you a line number. But only the top 2 stack levels really change throughout the execution of your code, you always have the EXE at the lowest level and your appapplication class start method seems to stick at level 2 all the time. And I think there is something odd about your call stack, I'd expect a method that starts the current form to show up on the stack pointing at a line of a DO form or a form creation. Maybe your application only has one form. In contrast of call stack info, coverage logging gives you all lines that are executed, also those that you already returned from in the call stack. Theyare logged by prg/vcsx file name and class/method/event name and lineno, even how deeply nested the execution was on the call stack.

And the coverage profiler can show you the code, but there are other ways to look at this. For example, by looking into the log and code side by side. The status bar of the code editor shows you the lineno or you copy code into notepad++ or excel to get line numbers. Many ways to do this. It wouldnt even be hard to take the info from a coverage log and automatically retrieve the actual code from the locaton given and create a text file that shows a code tracelog. Coverage profiler only shows the methods as they are and puts a counter of how many times a line was executed, for example in loop bodies.

What would also show up in the coverage log is how you get from ShellExeute into the error handlig routine. As said an error aka retuen value below 32 of ShellExecute does not trigger the error event of VFP and thus it's a mystery how you even get an error message out of this. The Shellexecute fails silent, in short, if it doesn't find the file or what to run by file extension, it simply does nothing, it doesn't even raise an error. But that's not pointing out your ShellExecute declare is wrong or you're parameterizing ShellExecute completely wrongly. That would cause a parameter count/type error, not a variable not found.

Chriss
 
God Morning Chris,

Hopefully I will have some time next week to dig into this. So let me be sure that I understand your last paragraph correctly. "ShellExecute() returning a value less than 32 does not trigger a VFP error event" Do I have that right? Let me try the coverage log and see what I can find. Thanks again.

Richard
 
Yes, you have that right. If Shellexecute failing for reasons of not finding the file or not finding the file type association returns a value <32, then that means the ShellExecte itself ran and , well, it returned a value. It is finished, and it doesn't trigger your error messagebox unless you have code like IF result<32 DO errorhandling and explicitly call the errorhandler, sing it to output that messagebox.

You can make a very simple experiment and call ShellExecute with a non existing file name, it won't cause a VFP error message.

The only reason ShellExecte would trigger an error is if its parameterization is completely wrong, like passing in a date for the parameter of a file name. Or passing in less parameters than necessary, or more than are allowed at all. Only that wold really cause an error that triggers ON ERROR.

That should be clear by documentation. As it's documented that Shellexecutes returns a value when it fails, it can't at the same time raise an error event. Not in VFP nor in Windows. It simply returns a value. It can't at the same time raise an error event. Neither an API function nor a native VFP function nor a user-defined function can raise an error and at the same time return a value. If it raises an error it steps out of the usual program execution and it can't fork and do both return a value to the caller and raise an error.

It's up to you to react to the return value of ShellExecute. If you don't, simply nothing happens. The report of the problem is simply ignored. But since you have an error message box, that must be caused by something, maybe even before the ShellExecute or after it. Whatever. It will show up if you debug it or log it. Either way.

Chriss
 
I even agree with that, you just will need to have a reproducable case, so you can trace what happens single stepping through the code. It can be tedious in comparison to look at the end portion of a log. Because the last bit of the log is what's most interesting, of course. You can search for an occurence of ON ERROR in the coverage log and then just look at the lines above that.

Chriss
 
Is patlab.pdfpath a nullable field and do you have a null value in some records? That would be a very simple reason for ShellExecute to fail even before it returns anything, but then the 23 is a mstery, it's surely not the return value of shellexecute, then.

Chriss
 
Chris - no this field is not nullable - I have plenty of records where this field is empty but not set to NULL. I will probably not have time to look at using the Debugger or the Coverage Profiler until next week. I will keep you posted. Thanks again to Chris & Mike.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top