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 Mike Lewis 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
 
What exactly do you mean by an "API error"? What actually are you seeing? Is it a VFP error message - the kind that is trapped by ON ERROR? If so, what does ERROR() return? Or is the error displayed by whatever utility you are using to display the PDF?

If ShellExecute() itself fails for any reason, it usually returns its own error code, this being an integer between 1 and 32. I suggest you trap that code and report it here, like this:

Code:
LOCAL cFilename, lnReply
m.cFilename = patlab.pdfpath
lnReply = ShellExecute(0,"open",m.cFilename,"","",1)
IF lnReply <= 32
  MESSAGEBOX("Error " + TRANSFORM(lnReply))
ENDIF

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Look into patlab.pdfpath.

Is it a relative path? ShellExecute won't know relative to what.

Chriss
 
Morning guys,

Mike - I have trapped the error I receive either a 23 or a 27 return code. This is what I was referring to as an API error.

Chris - these are full paths like d:\vvllabpath\file_name.pdf. Drive letter substitution is used so no UNC server references are used.

Thank you. Richard
 

WINAPI said:
If the function succeeds, it returns a value greater than 32. If the function fails, it returns an error value that indicates the cause of the failure.

ERROR_CRC 23 (0x17) Data error (cyclic redundancy check).
ERROR_SECTOR_NOT_FOUND 27 (0x1B) The drive cannot find the sector requested.

mJindrova
 
I have trapped the error I receive either a 23 or a 27 return code

For the complete avoidance of doubt, are those the values returned from ShellExecute()? The reason I ask is that your code does not show that you are trapping that returned value.

shellapi.h does not list an error 23 from ShellExecute. It shows error 27 as SE_ERR_ASSOCINCOMPLETE, which I take to mean that there is something wrong with the file's extension (which presumably is PDF): either the extension is not present in this case, or it is not properly registered in the Windows registry.

One way of checking ShellExecute() is to run the file from Windows. In other words, right-click on the filename (for example in a folder window) and choose Open. Doing that, in effect, runs ShellExecute() behind the scenes. If doing it that way works, there is something wrong with your code. If it doesn't work, it is something wrong with the filename, the registration of the file association, or perhaps the file itself.

mJindrova: Those errors you quoted don't look anything like ShellExecute() errors. More like something to do with low-level disk access.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thanks guys,

Mike - you are correct I did not display trapping the ShellExecute return code. But I am doing exactly as you indicated when I am running in diagnostic mode. Also, I came across your excellent Introducing ShellExecute from 2002 in FoxStuff. Excellent overview.

New information - Not all computers are affected by this problem. Several users report no error when opening the pdf from this location. It does not appear to be related to the pdf viewer in use. Most are set to Adobe Reader free or the Edge pdf viewer. It also does not appear to be related to Win10 or Win11. Some work some don't. I agree these are unusual errors. Also, the document is valid and can be opened from the pdf viewer directly, or Windows Explorer, or from another location in my app with no error. In fact, after the error is reported the pdf opens in the indicated viewer normally.

Thanks to all for helping me with this.
Richard
 
ShellExecute documentation also tells you to call the GetLAstError API function in case ShellExecute returns a value <=32, the direct return value is a clue but not the only error information you get. So you should do that. And then look up what the returned error number from GetLAstError means.

I also find 27 is the SE_ERR_ASSOCINCOMPLETE constant, which means the PDF file association is incomplete. I don't find something meaningful for 23, as Mike. In both casses, 23 or 27, GetLAstError should give you another error and thus another hint what's wrong.

I know you don't get return value of 31, but that error SE_ERR_NOASSOC (31) would mean that no file association is available. So 27 differs from that situation, it seems PDF is a registered format, but the file association - what should be used to open a PDF - is incomplete or broken on such computers. That's something that needs to be fixed in the right manner. It's not good to open a PDF when the file extension is not associated, and then pick an application (liek adobe reader) to open the PDF file and check "always open with" in the dialog. That's causing an incomplete file association. It's unfortunately the most often known or recommended way to associate applications with file extensions, but it's not working always.



Chriss
 
In fact, after the error is reported the pdf opens in the indicated viewer normally.

Hang on. The document opens normally. So, in that respect, there is no error. So how is that you see an error message?. Do you see some sort of a message box? If so, is that a FoxPro message box? Or what?

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike thanks again. Here is what it looks like. My app uses the Codemine framework so the framework is trapping the error and this is the display. Variable '23' is the numeric return code from ShellExecute().

New Information: Occasionally restarting Windows gets rid of the error for a while. Again, yes after the error ShellExecute indeed opens & displays the pdf normally.

VL_Error_from_ShellExecute_ydpyer.jpg
 
Then 12 is the VFP error number? Why?

If ShellExecute returns a number below 32 that does trigger an ON ERROR or in other words does not raise an error event.
What's your code after ShellExecute? Of course a number can never be a variabe name.

Chriss
 
So it very much looks like something is going wrong within Codemine. That message box is not a native VFP message box. It is presumably generated by Codemine. But it doesn't really make sense. As Chris says, a number can't be a variable.

Also, there is nothing to say that this error is caused by ShellExecute(). All it is saying is that an error occurred somewhere in your OpenPDF routine. In fact, there is no way for ShellExecute() to return a "variable not found" error, so we really need to look beyond that.

And also, 23 isn't the error number. And presumably nor is 27. So all we have said so far about the values that ShellExecute() returns - and all the stuff about an error in the file association - all that is irrelevant.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thanks guys - No I agree it does not make sense. To clarify the 23 & 27 are the numeric return codes from ShellExecute if I capture & display them and they then display as the above posted VFP error 12. Mike, I decided to follow your above line of thought "Hang on. The document opens normally. So, in that respect, there is no error." So what I have done is to trap the VFP error 12 when it comes from form method 'openpdf' in the Error method of my form. No error is displayed and the pdf opens very nicely. So far I do not notice any downside to doing this. There is no code in form.openpdf() method other that the ShellExecute() code. Thanks.

Richard
 
If there is no other code than the shellexecute, then how comes you get an error 12. That is the error variable not found. And you can't use 23 as a variable name in code. There must be an error in your error handler that causes it to try to acceess the "variable" 23. And that then causes error 12.

Well, and you should do more than ShellExecute, fully handling that function by its documentation means checking whether its result is >32 and if not, call GetLastError, not trigger or call error handling.

Chriss
 
This all sounds very strange to me. Richard, it's good that you've got it working, and I could understand it if you if you decided to take no further action. But, if this was me, I would still want to know what is at the root of the problem.

Codemine is telling you that there is a "variable not found" error in labform001.openpdf. But you say that the only code in that method is the ShellExecute(). It is evident that that code cannot produce that error. Also, the error message itself is dubious, given that a variable name cannot be numeric.

Running the program in the debugger, single-stepping though the relevant code, or alternatively setting a breakpoint on ERROR(), should give a clue to what is going on.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Richard, one small detail occurs to me. I notice your code includes the following:

Code:
m.cFilename = patlab.pdfpath
ShellExecute(0,"open",m.cFilename,"","",1)

I wonder if trailing spaces in the pdfpath field might be causing a problem. You could try changing it to the following:

Code:
m.cFilename = [highlight #FCE94F]ALLTRIM([/highlight]patlab.pdfpath[highlight #FCE94F])[/highlight]
ShellExecute(0,"open",m.cFilename,"","",1)

This might be completely irrelevant. But it might just be worth trying it.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
As it works sometimes and not other times, I dont think it's that. But Mike has a point, especially if the field is varchar and you rely on it giving you trimmed values. Notice a varchar field stores whatever you put into it. It will not pad the value you store into it with spaces up to the field width as a normal char field does. But a varchar is storing leading and trailing spaces when they are in the value you store. And you get them out again. So in the end Mike can be right about using ALLTRI anyway. Or you use a varchar field and store ALLTRIMmed values into it, so you don't need to alltrim when reading out the field. I just think as this is likely older code, there is no use of varchar and that won't explain it. Maybe you use a Memo field to not need ALLTRIM, but all the thoughts about varchar apply to that, too. Memos don't trim values you store into them, you can have trailing or leading spaces.

As we drilled down to the errors and their meaning, 27 does not come from ShellExecute looking for the association of PDF plus several spaces, that would cause an error because of no association, error 32, not error 27. There must be something broken about the PDF association. That cold be about DDE and the action defined for opening PDF files on top of the file type association.

And leading spaces would not cause the wrong file type association to be looked up, but would lead to the even simpler error of file not found.

Chriss
 
Morning guys,

When the problem cropped up, I tried the code with & without ALLTRIM() and it did not make a difference. The fields that the file path/name are stored in are standard VFP character fields. I also tried mimicking the method code from the other area of the app where these same pdf files always open without error. In that part of the app the file path/name is passed into the method as a parameter, not pulled directly from the table. This again made no difference. My final attempt was to assume the possibility that some corruption exists in the Openpdf() method code [non-visual code/characters. etc.], so I deleted the method from the form and recreated, typing the code back in by hand [no copy/paste], once again this made no difference.

Thanks again, I really appreciate all your input. Strange problem and I am not totally comfortable with just trapping the error, ignoring, and moving on, but I need to provide functional code to my users at this point. Likely I will continue to see if I can find a more satisfactory solution for this problem. Thanks.

Richard
 
Well, there is a simple option to call a PDF reader directly, instead of letting it be started by shellexecute. The only advantage Shellexecute has, if things are all right with file associations, is that the user (or admin of the computers) has control about what reader software is used and can switch it without you changing anything.

Without any add on Firefox is able to render a PDF file, so one thing that works is (for example)
Code:
Run /N "C:\Program Files\Mozilla Firefox\firefox.exe" "C:\Users\ChrissM\Documents\11750052.pdf"
Which you can generalize to
Code:
lcPDFFullpathFilename = patlab.pdfpath
Run /N "C:\full\path\to\pdf reader.exe" "&lcPDFFullpathFilename"
Other readers/viewers might not accept a parameter or need the right command line option, like /o for open or -o or in whatever command line options are available.

Btw, I have tried with leading and/or trailing space in the file name, by the way, and Firefox does not care about that, but that's not saying leading/trailing whitespace is unimportant in general. I tried the VFP internal functions and both FILE() and FOPEN() don't care about spaces, indeed. It's still better style to not depend on such mildness of applications, functions or the file system.

The disadvantage of such an approach is you depend on the EXE you pick for PDF opening. And specifically to Firefox, the browser opens with that PDF in a new tab, but depending on what is set up for Firefox it can open up all previous tabs, too, which might take a bit. I bet there are further options for starting firefox as a new window with only the PDF, too. Using a dedicated PDF viewer executable is the better option.

Chriss
 
Thanks again Chris - I thought about and looked into the option of not using ShellExecute a couple of days ago and rejected the idea due to the fact that there is an over 20-year tradition of opening pdfs [and other types of documents] using the ShellExecute virtue of respecting the Windows file association, allowing users to set their computer as they wish. I am going to stick with what I currently have at least for now and continue to ponder the erratic behavior of ShellExecute in this particular location of my app. Thanks again.

Richard
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top