Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. ShellExecute() launch .CHM and PDF file not work in Window 7

ShellExecute() launch .CHM and PDF file not work in Window 7

Scheduled Pinned Locked Moved C / C++ / MFC
helpquestionc++
25 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Andraw111

    my code is exactly same as yours, but I still cannot make it run in Window 7, it works fine in Window XP. My test mechine is Window 7 Enterprise. Is it possible related settings or security issue?

    enhzflepE Offline
    enhzflepE Offline
    enhzflep
    wrote on last edited by
    #6

    Not sure about what it could be. As a test, I set my Acrobat to always run as admin. When I ran the code, I was just asked if I want to run Acrobat.exe or not. When controlling COM objects - e.g MS Office. This behaviour is different. I have office apps set to run as Admin, so I can write files anywhere I like. If I try to create (say) an 'Excel.Application' or 'Word.Application' object from php, C++, VB or javascript, it fails unless the calling application also has admin rights. It sure sounds interesting. (but no-fun)

    A 1 Reply Last reply
    0
    • enhzflepE enhzflep

      Not sure about what it could be. As a test, I set my Acrobat to always run as admin. When I ran the code, I was just asked if I want to run Acrobat.exe or not. When controlling COM objects - e.g MS Office. This behaviour is different. I have office apps set to run as Admin, so I can write files anywhere I like. If I try to create (say) an 'Excel.Application' or 'Word.Application' object from php, C++, VB or javascript, it fails unless the calling application also has admin rights. It sure sounds interesting. (but no-fun)

      A Offline
      A Offline
      Andraw111
      wrote on last edited by
      #7

      So what should I do now?

      enhzflepE 1 Reply Last reply
      0
      • A Andraw111

        So what should I do now?

        enhzflepE Offline
        enhzflepE Offline
        enhzflep
        wrote on last edited by
        #8

        Find out and tell me, so I know too! ;P (ducks and runs for cover) Nah, on a more serious note - did you try with lpOperation holding a pointer to the string "open"? I've not seen the function used like this before, I've only ever seen it used with open specified. HOWEVER - I just remembered David's comment about it being memory related earlier and thought to check-out the integer values for the error-codes. Looking into winerror.h we see the following:

        #define ERROR_SUCCESS 0L #define NO_ERROR 0L #define ERROR_INVALID_FUNCTION 1L #define ERROR_FILE_NOT_FOUND 2L #define ERROR_PATH_NOT_FOUND 3L #define ERROR_TOO_MANY_OPEN_FILES 4L #define ERROR_ACCESS_DENIED 5L #define ERROR_INVALID_HANDLE 6L #define ERROR_ARENA_TRASHED 7L #define ERROR_NOT_ENOUGH_MEMORY 8L #define ERROR_INVALID_BLOCK 9L #define ERROR_BAD_ENVIRONMENT 10L #define ERROR_BAD_FORMAT 11L #define ERROR_INVALID_ACCESS 12L #define ERROR_INVALID_DATA 13L #define ERROR_OUTOFMEMORY 14L

        Which makes me feel foolish for not checking earlier, then going on to ask about the "open" verb. I guess your next bet would be to trawl the net for reports of it failing with an error of 8 (ERROR_NOT_ENOUGH_MEMORY) Like I said - Interesting problem (but not a fun one) Best, Simon

        1 Reply Last reply
        0
        • A Andraw111

          Dear all, HINSTANCE handle = ShellExecute(NULL, NULL, strHlpFile, NULL, NULL, SW_SHOW); I create a application in MFC, it works fine in Window XP and return 42 value, but if run it in Window 7, it cannot open the .CHM or PDF file, the return code is 8. What's the problem? how can I solve issue? I try to use system() to launch .CHM or PDF file, it works fine in both Window XP and Window 7, but it has MS-DOS black screen there, how can I let MS-DOS not shown? Thank you very much!

          S Offline
          S Offline
          Software_Developer
          wrote on last edited by
          #9

          Try passing 0

          handle = ShellExecute(0, NULL, strPdfFile, NULL, NULL, SW_SHOW);

          or Try using 'open' instead of 'NULL'

          handle = ShellExecute(NULL, "open", strPdfFile, NULL, NULL, SW_SHOW);

          or both

          1 Reply Last reply
          0
          • A Andraw111

            Dear all, HINSTANCE handle = ShellExecute(NULL, NULL, strHlpFile, NULL, NULL, SW_SHOW); I create a application in MFC, it works fine in Window XP and return 42 value, but if run it in Window 7, it cannot open the .CHM or PDF file, the return code is 8. What's the problem? how can I solve issue? I try to use system() to launch .CHM or PDF file, it works fine in both Window XP and Window 7, but it has MS-DOS black screen there, how can I let MS-DOS not shown? Thank you very much!

            S Offline
            S Offline
            Software_Developer
            wrote on last edited by
            #10

            Try passing a 0 instead of a NULL.

            HINSTANCE handle = ShellExecute(0, NULL, strPdfFile, NULL, NULL, SW_SHOW);

            L 1 Reply Last reply
            0
            • S Software_Developer

              Try passing a 0 instead of a NULL.

              HINSTANCE handle = ShellExecute(0, NULL, strPdfFile, NULL, NULL, SW_SHOW);

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #11

              Parameter 1 is an HWND so NULL is the correct value, and is equal to 0 so it would not have any effect. See here[^] for the full specification.

              One of these days I'm going to think of a really clever signature.

              S 1 Reply Last reply
              0
              • L Lost User

                Parameter 1 is an HWND so NULL is the correct value, and is equal to 0 so it would not have any effect. See here[^] for the full specification.

                One of these days I'm going to think of a really clever signature.

                S Offline
                S Offline
                Software_Developer
                wrote on last edited by
                #12

                True, Windows 7 UAC (User Account Control) screws things up. http://en.wikipedia.org/wiki/User_Account_Control[^] says this about ShellExecute:

                ShellExecute(hwnd, "runas", "C:\\Windows\\Notepad.exe", 0, 0, SW_SHOWNORMAL);

                In the absence of a specific directive stating what privileges the application requests, UAC will apply heuristics, to determine whether or not the application needs administrator privileges. For example, if UAC detects that the application is a setup program, from clues such as the filename, versioning fields, or the presence of certain sequences of bytes within the executable, in the absence of a manifest it will assume that the application needs administrator privileges.

                A 1 Reply Last reply
                0
                • S Software_Developer

                  True, Windows 7 UAC (User Account Control) screws things up. http://en.wikipedia.org/wiki/User_Account_Control[^] says this about ShellExecute:

                  ShellExecute(hwnd, "runas", "C:\\Windows\\Notepad.exe", 0, 0, SW_SHOWNORMAL);

                  In the absence of a specific directive stating what privileges the application requests, UAC will apply heuristics, to determine whether or not the application needs administrator privileges. For example, if UAC detects that the application is a setup program, from clues such as the filename, versioning fields, or the presence of certain sequences of bytes within the executable, in the absence of a manifest it will assume that the application needs administrator privileges.

                  A Offline
                  A Offline
                  Andraw111
                  wrote on last edited by
                  #13

                  Now we have another small project also created in C++, it also launch .CHM file from help menu: void CMainFrame::LaunchHelp(CString FilePath) { SHELLEXECUTEINFO sei; sei.cbSize = sizeof(SHELLEXECUTEINFO); sei.fMask = NULL; sei.hwnd = NULL; sei.lpVerb = "open"; sei.lpFile = FilePath; sei.lpParameters= NULL; sei.nShow = SW_SHOWMAXIMIZED; sei.hInstApp = NULL; sei.lpIDList = NULL; sei.lpClass = NULL; sei.hkeyClass = NULL; sei.dwHotKey = NULL; sei.hIcon = NULL; sei.hProcess = NULL; sei.lpDirectory = NULL; int ReturnCode = ::ShellExecuteEx(&sei); switch(ReturnCode) { case ERROR_FILE_NOT_FOUND: AfxMessageBox("The specified file was not found."); break; case ERROR_PATH_NOT_FOUND: AfxMessageBox("The specified path was not found."); break; case ERROR_ACCESS_DENIED: AfxMessageBox("Access to the specified file is denied."); break; } } I works fine in Window 7, I copy this function to my application (also created in C++), but after compile and test it in Window 7, still doesn't work, do we need change some settings to make app work in Window 7? I compare the settings, the only difference are that 1: in C++ - >Code Generation -> Use run time library: I use Multithreaded DLL, they use Multlhreaded; 2: in General Microsoft Foundation Classes: I use Use MFC in a Shared Library; they use Use MFC in a Static Library. Thanks!

                  S C 2 Replies Last reply
                  0
                  • A Andraw111

                    Now we have another small project also created in C++, it also launch .CHM file from help menu: void CMainFrame::LaunchHelp(CString FilePath) { SHELLEXECUTEINFO sei; sei.cbSize = sizeof(SHELLEXECUTEINFO); sei.fMask = NULL; sei.hwnd = NULL; sei.lpVerb = "open"; sei.lpFile = FilePath; sei.lpParameters= NULL; sei.nShow = SW_SHOWMAXIMIZED; sei.hInstApp = NULL; sei.lpIDList = NULL; sei.lpClass = NULL; sei.hkeyClass = NULL; sei.dwHotKey = NULL; sei.hIcon = NULL; sei.hProcess = NULL; sei.lpDirectory = NULL; int ReturnCode = ::ShellExecuteEx(&sei); switch(ReturnCode) { case ERROR_FILE_NOT_FOUND: AfxMessageBox("The specified file was not found."); break; case ERROR_PATH_NOT_FOUND: AfxMessageBox("The specified path was not found."); break; case ERROR_ACCESS_DENIED: AfxMessageBox("Access to the specified file is denied."); break; } } I works fine in Window 7, I copy this function to my application (also created in C++), but after compile and test it in Window 7, still doesn't work, do we need change some settings to make app work in Window 7? I compare the settings, the only difference are that 1: in C++ - >Code Generation -> Use run time library: I use Multithreaded DLL, they use Multlhreaded; 2: in General Microsoft Foundation Classes: I use Use MFC in a Shared Library; they use Use MFC in a Static Library. Thanks!

                    S Offline
                    S Offline
                    Software_Developer
                    wrote on last edited by
                    #14

                    The code below works and launches a helpfile in Windws 7.

                    #include
                    #include
                    #include

                    int main()
                    {

                      SHELLEXECUTEINFO sei = {0};
                      sei.cbSize = sizeof(SHELLEXECUTEINFO);
                      sei.lpVerb = \_T("open");
                      sei.lpFile = \_T("C:\\\\windows\\\\help.CHM");
                      sei.fMask = SEE\_MASK\_INVOKEIDLIST;
                      sei.nShow = SW\_SHOWDEFAULT;
                    
                      DWORD exitCode;
                      int RetVal = GetExitCodeProcess(sei.hProcess, &exitCode);
                      cout<<"Errorcode "<
                    
                    A 2 Replies Last reply
                    0
                    • A Andraw111

                      Dear all, HINSTANCE handle = ShellExecute(NULL, NULL, strHlpFile, NULL, NULL, SW_SHOW); I create a application in MFC, it works fine in Window XP and return 42 value, but if run it in Window 7, it cannot open the .CHM or PDF file, the return code is 8. What's the problem? how can I solve issue? I try to use system() to launch .CHM or PDF file, it works fine in both Window XP and Window 7, but it has MS-DOS black screen there, how can I let MS-DOS not shown? Thank you very much!

                      C Offline
                      C Offline
                      Charles Oppermann
                      wrote on last edited by
                      #15

                      Have you initialized COM first? From the remarks section on ShellExecute()[^]:

                      CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)

                      Can you use ShellExecuteEx[^]? ShellExecuteEx is preferable in this case because you'll get better result information.

                      Andraw111 wrote:

                      I try to use system() to launch .CHM or PDF file, it works fine in both Window XP and Window 7, but it has MS-DOS black screen there, how can I let MS-DOS not shown?

                      The system() C runtime function would not be appropriate here, as you are a Win32 application. Try this, from a command prompt, type start myfile.chm and report on what happens. Same for Runas.

                      /* Charles Oppermann */ http://weblogs.asp.net/chuckop

                      1 Reply Last reply
                      0
                      • A Andraw111

                        Now we have another small project also created in C++, it also launch .CHM file from help menu: void CMainFrame::LaunchHelp(CString FilePath) { SHELLEXECUTEINFO sei; sei.cbSize = sizeof(SHELLEXECUTEINFO); sei.fMask = NULL; sei.hwnd = NULL; sei.lpVerb = "open"; sei.lpFile = FilePath; sei.lpParameters= NULL; sei.nShow = SW_SHOWMAXIMIZED; sei.hInstApp = NULL; sei.lpIDList = NULL; sei.lpClass = NULL; sei.hkeyClass = NULL; sei.dwHotKey = NULL; sei.hIcon = NULL; sei.hProcess = NULL; sei.lpDirectory = NULL; int ReturnCode = ::ShellExecuteEx(&sei); switch(ReturnCode) { case ERROR_FILE_NOT_FOUND: AfxMessageBox("The specified file was not found."); break; case ERROR_PATH_NOT_FOUND: AfxMessageBox("The specified path was not found."); break; case ERROR_ACCESS_DENIED: AfxMessageBox("Access to the specified file is denied."); break; } } I works fine in Window 7, I copy this function to my application (also created in C++), but after compile and test it in Window 7, still doesn't work, do we need change some settings to make app work in Window 7? I compare the settings, the only difference are that 1: in C++ - >Code Generation -> Use run time library: I use Multithreaded DLL, they use Multlhreaded; 2: in General Microsoft Foundation Classes: I use Use MFC in a Shared Library; they use Use MFC in a Static Library. Thanks!

                        C Offline
                        C Offline
                        Charles Oppermann
                        wrote on last edited by
                        #16

                        You're calling ShellExecute_**Ex**_ but testing the return value for the for SE_ERR_ values? With ShellExecuteEx[^], the return value is true/false and the more information is provided by GetLastError(). For backward compatibility, the SE_ERR_ codes are placed in hInst member of the structure. Try this instead:

                        SHELLEXECUTEINFO sei = { sizeof(sei) }; // Will zero out the structure, no need to set NULL on everything
                        sei.fMask = SEE_MASK_NOASYNC // Important when you don't have a message loop
                        sei.lpFile = FilePath;
                        sei.nShow = SW_SHOWMAXIMIZED; // Annoying to force apps to open full screen
                        if (false == ShellExecuteEx(&sei))
                        {
                        // Check GetLastError() here
                        }

                        /* Charles Oppermann */ http://weblogs.asp.net/chuckop

                        S A 2 Replies Last reply
                        0
                        • C Charles Oppermann

                          You're calling ShellExecute_**Ex**_ but testing the return value for the for SE_ERR_ values? With ShellExecuteEx[^], the return value is true/false and the more information is provided by GetLastError(). For backward compatibility, the SE_ERR_ codes are placed in hInst member of the structure. Try this instead:

                          SHELLEXECUTEINFO sei = { sizeof(sei) }; // Will zero out the structure, no need to set NULL on everything
                          sei.fMask = SEE_MASK_NOASYNC // Important when you don't have a message loop
                          sei.lpFile = FilePath;
                          sei.nShow = SW_SHOWMAXIMIZED; // Annoying to force apps to open full screen
                          if (false == ShellExecuteEx(&sei))
                          {
                          // Check GetLastError() here
                          }

                          /* Charles Oppermann */ http://weblogs.asp.net/chuckop

                          S Offline
                          S Offline
                          Software_Developer
                          wrote on last edited by
                          #17

                          Right, GetExitCodeProcess() likewise also gets the error code.

                          #include
                          #include
                          #include

                          int main()
                          {

                            SHELLEXECUTEINFO sei = {0};
                            sei.cbSize = sizeof(SHELLEXECUTEINFO);
                            sei.lpVerb = \_T("open");
                            sei.lpFile = \_T("C:\\\\windows\\\\help.CHM");
                            sei.fMask = SEE\_MASK\_INVOKEIDLIST;
                            sei.nShow = SW\_SHOWDEFAULT;
                          
                            DWORD exitCode;
                            int RetVal = GetExitCodeProcess(sei.hProcess, &exitCode);
                            cout<<"Errorcode "<
                          
                          1 Reply Last reply
                          0
                          • S Software_Developer

                            The code below works and launches a helpfile in Windws 7.

                            #include
                            #include
                            #include

                            int main()
                            {

                              SHELLEXECUTEINFO sei = {0};
                              sei.cbSize = sizeof(SHELLEXECUTEINFO);
                              sei.lpVerb = \_T("open");
                              sei.lpFile = \_T("C:\\\\windows\\\\help.CHM");
                              sei.fMask = SEE\_MASK\_INVOKEIDLIST;
                              sei.nShow = SW\_SHOWDEFAULT;
                            
                              DWORD exitCode;
                              int RetVal = GetExitCodeProcess(sei.hProcess, &exitCode);
                              cout<<"Errorcode "<
                            
                            A Offline
                            A Offline
                            Andraw111
                            wrote on last edited by
                            #18

                            Now I cannot simply say that ::ShellExecuteEx(&sei) doesn't work in Window 7. The problem is that it doesn't work in my application created before. I have a app created using VC++ 6.0 last year, everything is fine except that I cannot open .CHM file from it. Today I create a new application in MFC in VC++ 6.0, then use the exactly same function as the old application, it can open the .CHM file without any problem. I check all the project settings for both application, they are same, why same function works in one application, but failed in another application?

                            1 Reply Last reply
                            0
                            • C Charles Oppermann

                              You're calling ShellExecute_**Ex**_ but testing the return value for the for SE_ERR_ values? With ShellExecuteEx[^], the return value is true/false and the more information is provided by GetLastError(). For backward compatibility, the SE_ERR_ codes are placed in hInst member of the structure. Try this instead:

                              SHELLEXECUTEINFO sei = { sizeof(sei) }; // Will zero out the structure, no need to set NULL on everything
                              sei.fMask = SEE_MASK_NOASYNC // Important when you don't have a message loop
                              sei.lpFile = FilePath;
                              sei.nShow = SW_SHOWMAXIMIZED; // Annoying to force apps to open full screen
                              if (false == ShellExecuteEx(&sei))
                              {
                              // Check GetLastError() here
                              }

                              /* Charles Oppermann */ http://weblogs.asp.net/chuckop

                              A Offline
                              A Offline
                              Andraw111
                              wrote on last edited by
                              #19

                              Yes, you are right, ShellExecuteEx() return true or false. But still cannot solve my problem.

                              C 1 Reply Last reply
                              0
                              • S Software_Developer

                                The code below works and launches a helpfile in Windws 7.

                                #include
                                #include
                                #include

                                int main()
                                {

                                  SHELLEXECUTEINFO sei = {0};
                                  sei.cbSize = sizeof(SHELLEXECUTEINFO);
                                  sei.lpVerb = \_T("open");
                                  sei.lpFile = \_T("C:\\\\windows\\\\help.CHM");
                                  sei.fMask = SEE\_MASK\_INVOKEIDLIST;
                                  sei.nShow = SW\_SHOWDEFAULT;
                                
                                  DWORD exitCode;
                                  int RetVal = GetExitCodeProcess(sei.hProcess, &exitCode);
                                  cout<<"Errorcode "<
                                
                                A Offline
                                A Offline
                                Andraw111
                                wrote on last edited by
                                #20

                                I check the return code by: int RetVal = GetExitCodeProcess(sei.hProcess, &exitCode); both XP and window 7 return 0.

                                1 Reply Last reply
                                0
                                • A Andraw111

                                  Yes, you are right, ShellExecuteEx() return true or false. But still cannot solve my problem.

                                  C Offline
                                  C Offline
                                  Charles Oppermann
                                  wrote on last edited by
                                  #21

                                  Andraw111 wrote:

                                  Yes, you are right, ShellExecuteEx() return true or false.
                                  But still cannot solve my problem.

                                  Okay, but what is it returning? True or False? If false, did you check GetLastError()? What was it's value?

                                  /* Charles Oppermann */ http://weblogs.asp.net/chuckop

                                  A 2 Replies Last reply
                                  0
                                  • C Charles Oppermann

                                    Andraw111 wrote:

                                    Yes, you are right, ShellExecuteEx() return true or false.
                                    But still cannot solve my problem.

                                    Okay, but what is it returning? True or False? If false, did you check GetLastError()? What was it's value?

                                    /* Charles Oppermann */ http://weblogs.asp.net/chuckop

                                    A Offline
                                    A Offline
                                    Andraw111
                                    wrote on last edited by
                                    #22

                                    Thanks for reply, it return 8. But strange thing is that if I create a brand new MFC project and use the same codes to open .CHM file, it works fine, why?

                                    C 1 Reply Last reply
                                    0
                                    • C Charles Oppermann

                                      Andraw111 wrote:

                                      Yes, you are right, ShellExecuteEx() return true or false.
                                      But still cannot solve my problem.

                                      Okay, but what is it returning? True or False? If false, did you check GetLastError()? What was it's value?

                                      /* Charles Oppermann */ http://weblogs.asp.net/chuckop

                                      A Offline
                                      A Offline
                                      Andraw111
                                      wrote on last edited by
                                      #23

                                      Finally I found what cause the .CHM file cannot open in Window 7. In my MFC application, I have a project setting: Link -> Output ->Reserve field, I put "0x40000000". I create a testing application, if I don't set "0x40000000" to Reserve field, it works fine, otherwise, it cannot open .CHM file in Window 7. Even I know the reason, I still cannot solve the problem, since our project is very large, if I remove that setting, when I run my application I get "XX MFC application has encountered a problem and needs to close....".

                                      1 Reply Last reply
                                      0
                                      • A Andraw111

                                        Thanks for reply, it return 8. But strange thing is that if I create a brand new MFC project and use the same codes to open .CHM file, it works fine, why?

                                        C Offline
                                        C Offline
                                        Charles Oppermann
                                        wrote on last edited by
                                        #24

                                        I strongly suspect that COM initialization is at issue here[^]. Earlier, I mentioned that COM has to be initialized as follows:

                                        CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)

                                        This is why I think you're new project works and the old one doesn't. Is your old project using multithreaded COM? If so, the calls might fail. [Just saw your other post that resolves your issue. I'm posting this for other people who might encounter ShellExecute problems.]

                                        /* Charles Oppermann */ http://weblogs.asp.net/chuckop

                                        A 1 Reply Last reply
                                        0
                                        • C Charles Oppermann

                                          I strongly suspect that COM initialization is at issue here[^]. Earlier, I mentioned that COM has to be initialized as follows:

                                          CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)

                                          This is why I think you're new project works and the old one doesn't. Is your old project using multithreaded COM? If so, the calls might fail. [Just saw your other post that resolves your issue. I'm posting this for other people who might encounter ShellExecute problems.]

                                          /* Charles Oppermann */ http://weblogs.asp.net/chuckop

                                          A Offline
                                          A Offline
                                          Andraw111
                                          wrote on last edited by
                                          #25

                                          Ok, I will add them, thanks!

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups