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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

ShellExecute THandle 1

Status
Not open for further replies.

cehowski

Technical User
Dec 1, 2006
39
US
After trial & error and a review of FAQs, etc. I came up with the following, which will open Crystal Reports .Rpt files automatically, through an file association with a 3rd party Report Viewer. In case the files have been moved, or the network or drive mappings weren't available, I wanted to display an error message:

procedure TForm1.Button1Click(Sender: TObject);
var
ReturnValue : THandle;
begin
ReturnValue := 0;
ReturnValue := ShellExecute(0, 'open', pchar('V:\DDSO Reporter\Organization.Rpt'), nil, nil, SW_NORMAL);
if ReturnValue < 32 then
showmessage('The requested file cannot be opened at this time. Please check your network connections and Drive Mappings.')
end;

If I read the WINApi help correctly, the return value will be less than 32 if there was a problem opening the document (it had been moved, or the network was down, etc., and (I'm assuming) more than 32 (the Handle assigned by Windows) if it was alright. Does anyone know if this is the most effective way to do this. This does work, but I'm not sure it's the best way to do it.
 
the return value is an integer not a handle.
you will get other return values for different errors.

Code:
procedure TForm1.Button1Click(Sender: TObject);
var
 errorcode: integer;
begin
 errorcode :=
  ShellExecute(0, 'open', pchar('c:\test.txt'), nil, nil, SW_NORMAL);
 case errorcode of
  2:showmessage('file not found');
  3:showmessage('path not found');
  5:showmessage('access denied');
  8:showmessage('not enough memory');
  32:showmessage('dynamic-link library not found');
  26:showmessage('sharing violation');
  27:showmessage('filename association incomplete or invalid');
  28:showmessage('DDE request timed out');
  29:showmessage('DDE transaction failed');
  30:showmessage('DDE busy');
  31:showmessage('no application associated with the given filename extension');
 end;
 
{
 SE_ERR_FNF              = 2;
 SE_ERR_PNF              = 3;
 SE_ERR_ACCESSDENIED     = 5;
 SE_ERR_OOM              = 8;
 SE_ERR_DLLNOTFOUND      = 32;
 SE_ERR_SHARE            = 26;
 SE_ERR_ASSOCINCOMPLETE  = 27;
 SE_ERR_DDETIMEOUT       = 28;
 SE_ERR_DDEFAIL          = 29;
 SE_ERR_DDEBUSY          = 30;
 SE_ERR_NOASSOC          = 31;
 }
end;

Aaron
John Mutch Electronics
 
Aaron,

Thanks for the example - This should probably be added to the FAQs, as it is a more complete example of using ShellExecute, and responding to the Return Value.

I guess a THandle is an integer value as well, and a THandle <= 32 represents an errorcode. Does it matter which is used? I tested mine, by showing the return value in a message box, and one thing I noticed was that the error #2 was returned (FileNotFound), even though I was actually using a bad path as well (a non-existent drive letter), so I'm wondering in what case the "PathNotFound" error would be raised (not that it matters I guess)?. When the routine was successful, it would return the # 42.

Once again, thanks for your help.
 
Just to expand on Aaron's answer, if the return code is <= 32 then you can use the SysErrorMessage function to return the error message, this means that you don't need to write the case statement for every possible error value.

e.g.
Code:
  ReturnValue := ShellExecute(0, 'open', 'C:\test.txt', nil, nil, SW_NORMAL);
  if ReturnValue <= 32 then
    ShowMessage(SysErrorMessage(ReturnValue));
Or you can use the RaiseLastWin32Error to raise an exception with the error message and error code.

Steve
 
Thanks Steve - It's nice to be able to get such help. I hope I can contribute myself in the future.
 
Once again, thanks for the help everybody. I just noticed that when I use SysErrorMessage, and there is no association for the file type, the error comes back as "A device attached to the system is not functioning." The return value (which I displayed at the end of the message)was 31, which, according to what I've seen, should be "no application association". Am I looking at two different error types or something, or is it just a difference between the definition and the message? The the Windows error for 31 is SE_ERR_NOASSOC, so I would think the error could be better described than by the "A device attached to the system is not functioning." I guess it doesn't matter a lot, but "inquiring minds want to know".

The current code looks like this:

procedure TForm1.Button1Click(Sender: TObject);
var
ReturnValue : THandle;
begin
ReturnValue := 0;
ReturnValue := ShellExecute(0, 'open', pchar('V:\DDSO Reporter\Organization.Rpt'), nil, nil, SW_NORMAL);
if ReturnValue <= 32 then
showmessage(SysErrorMessage(ReturnValue)+ ' '+ IntToStr(ReturnValue))
end;
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top