Link to home
Start Free TrialLog in
Avatar of tmaga
tmaga

asked on

Calling a windows API function from within a c++ program

I am at a loss for how to call the windows API function "FindExecutable" from within my c++ program.

I am trying to create a program that can determine if a particular file type (html in my case), is supported on the computer where the program is being run.

What I need help with is the semantics.  I reviewed the Win32 Programmer's Reference, but I don't know how to combine the description in the Win32 reference with the actual program code (what do I put in the #include statement, do I have to declare any variables, etc).

How does a c++ program look when it incorporates this (or any)  Windows API function?

FYI: I'm using a Borland C++ compiler.

Please help.
Thanks.
Avatar of tmaga
tmaga

ASKER

Edited text of question.
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
In order to safely call a Win32 API from a C++ program you should do the following:

1) #include <windows.h> above all code that uses the APIs (top of C++/H flie is fine).

2) Use the global scope (::) operator.
    Example: int x = ::FindExecutable( /* ... */ );

   
Ooops, alexo is of course right - I got distracted by the C Area...

(BTW: alexo, still looking for the article, but no luck so far...)
Avatar of tmaga

ASKER

When I put the following :

#include <windows.h>

      BOOL IsFileTypeSupported ( char* pszFile);
      BOOL IsFileTypeSupported ( char* pszFile)
{
      char acAppName [ MAX_PATH];

      if ( 31 != FindExecutable (  pszFile, NULL, acAppName))
      {
            return ( TRUE);
      }

      return (FALSE);
}

The compiler returns the following two errors:

1. Undefined symbol "MAX_PATH" in function IsFileTypeSupported(char*)
2. Call to undefined function 'FindExecutable' in function IsFileTypeSupported(char*)

I have been trying to figure this out for several hours now, playing with different variations of the above (what is MAX_PATH represent?).

Is this code snippet supposed to be able to be run as it is, or as a function called from function main()?

In case you haven't guessed, I'm not really familar with programming in C++ yet.

Please help.
Thanks.
>>Is this code snippet supposed to be able to be run as it
>>is, or as a function called from function main()?

Well, it won't run 'as is', a 'main()' function is still needed...

'MAX_PATH' is the 'official' constant for the maximum amount of characters of a file's path (including the drive letter, directories and the file name itself), the definition is in windef.h: '#define MAX_PATH 260'. But I'm surprised that it is not recognized, as windef.h is included by windows.h - to overcome this, simply try

#include <windows.h>
#include <windef.h>
#include <shellapi.h>

I forgot to add shellapi.h, thus 'FindExecutable()' was undefined - sorry...



Avatar of tmaga

ASKER

As soon as I put the "#include <windef.h>" line into the code, upon compilation, there were 26 errors and multiple warnings?!?

I changed the "char acAppName [ MAX_PATH ];" to "char acAppName [ 260 ];" and removed the reference to windef.h, and everything worked out fine.

Oh, and one other comment, in your "if" statement, the API call will be true if it returns any value greater than 32.

Following is the code that I finally got to work:

#include <stdio.h>
#include <windows.h>
#include <shellapi.h>

BOOL IsFileTypeSupported ( char* pszFile);

BOOL IsFileTypeSupported ( char* pszFile)
{
      char acAppName [ 260 ];

      if (FindExecutable (pszFile, NULL, acAppName) > 32)
            return (TRUE);
      return (FALSE);
}

int main()
{
      char *pszFile="c:\\test.html";

      if (IsFileTypeSupported(pszFile)) printf("File type is supported.\n");
      else printf("File type is not supported.\n");

      return(0);
}

Any thoughts on why the "#include <windef.h> caused such a problem?
>>Oh, and one other comment, in your "if" statement, the
>>API call will be true if it returns any value greater than
>>32.

Yes, from the docs:

" Returns

If the function succeeds, the return value is the instance handle of the executable file associated with the
specified filename. (This handle could also be the handle of a dynamic data exchange [DDE] server
application.) If there is an error, the return value is less than or equal to 32. The possible error values are listed
in the following Comments section. "

That's why it returns 'TRUE' for these values ;-)

And I'm puzzled about windef.h - what compiler are you using?


Avatar of tmaga

ASKER

I'm using the  Borland C++ version 4.52 compiler.

Just to confirm, it is possible to write a program (and run it from a CD)  that:

1. creates a test file (html format) on the computer's hard drive,
2. use the FindExecutable function to tell whether that file format is reigstered,
3. given the results of the function call, either:
          a. launch a seperate installation executable, or
          b. launch the already registered application.

Yes?

Thanks for your help.
Well, I once did this (created a 32bit watcom frontend to call the default browser from a 16bit legacy Borland app):

#include <windows.h>

int PASCAL WinMain( HANDLE ,
                    HANDLE ,
                    LPSTR  lpszCmdLine,
                    int    
                  )
{

    char        acExe[ 1024];

    HINSTANCE   hInst;
    UINT        uRC;

    if  (   !GetPrivateProfileString    (   "browse",
                                            "sPath",
                                            "",
                                            acExe,
                                            1024,
                                            "wdex.ini"
                                        )
        )
        {
            hInst   =   FindExecutable  (   "wdex.htm", NULL,   acExe);

            if  (   32  >=  ( int) hInst)   return( ( int) hInst);
        }
       

    hInst   =   ShellExecute    (   NULL,
                                    "open",
                                    acExe,
                                    lpszCmdLine,
                                    NULL,
                                    SW_SHOWNORMAL
                                );

    if  (   32  >=  ( int) hInst)   return( ( int) hInst);

    return( 0);
}

So the answer is: Yes...

(BTW: To use an already running instance, you'd eventually have to establish a DDE conversation)
Avatar of tmaga

ASKER

Thank you for all the help.  Although I don't understand that code that you included with your last response.   :-)