- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I need my program to launch an app, as though from a command line. The problem is that I don't know the path to the app. I have tried various forms of SYSTEM, RUNQQ, FINDFILEQ, and FULLPATHQQ to no avail.
The particular present example is launching Adobe Reader, so I need to execute the file AcroRead32.exe. As far as I can see, my program needs the complete to this file in order to launch it.
I know that I can do a SYSTEM call like "Dir C:\AcroRead32.exe /s > parsethis.txt", and then write code to extract the path from this txt output file. But surely there must be a better way? Even this solution assumes that the app is in the C: drive.
Isn't there some way to return the path to an arbitrary filename from within Fortran?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Have you checked for this on CodeProject? I "requisitioned" some of their code for a VB app I wrote to find an executable.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What you really want is ShellExecute - and open the file not the application. This is the same as if you had double-clicked on the PDF (or whatever) file and uses the users file association.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here's some code which launches Acrobat to open a selected pdf file. First the pdf file is selected from a directory (which lives at a standard offset in the calling program's directory tree), then the full pathname to the selected file, which will be something like
AdobePath = 'C:\Program Files\Adobe\Acrobat 6.0\Reader\AcroRd32.exe'//CHAR(0)
is submitted to CreateProcess() using the class name for Adobe (which is presumed to be already installed on the computer):
SUBROUTINE ViewPDF USE ShellOut USE CmnDlgs USE charfunc IMPLICIT NONE INTEGER :: nc, np CHARACTER(LEN=256) :: findpdf CHARACTER(LEN=200), PARAMETER :: pdfFilter = "PDF files (*.pdf)"c//"*.pdf"c//""c CALL full_path (RootPath, "docs", "*", "pdf", fpname) IF (.NOT.CmnDlgOpenFile(ghwndMain, pdfFilter, fpname)) RETURN nc = INDEX(fpname, CHAR(0)) IF (chcnt(AdobePath, LEN(AdobePath)) > 0) THEN np = INDEX(AdobePath, CHAR(0)) findpdf = AdobePath(1:np-1)//" "//fpname(1:nc) ! the Adobe acrobat classname has evidently changed since ! version 6, and the new class name is 'AcrobatSDIWindow' !CALL Launch (findpdf, 'AdobeAcrobat'C) ! classname discovered with Spy++ CALL Launch (findpdf, 'AcrobatSDIWindow'C) ! classname discovered with Spy++ ELSE np = MessageBox (ghwndMain, 'PDF reader not initialized'c, 'Error'c, MB_OK) END IF END SUBROUTINE ViewPDF
and where
SUBROUTINE Launch (progname, classname) IMPLICIT NONE CHARACTER(LEN=*), INTENT(IN) :: progname, classname INTEGER :: rval !CHARACTER(LEN=8), PARAMETER :: dllname = 'rsc.dll'c CHARACTER(LEN=40) :: emsg TYPE(T_STARTUPINFO) :: si TYPE(T_PROCESS_INFORMATION) :: pi ! TYPE T_PROCESS_INFORMATION ! SEQUENCE ! integer(HANDLE) hProcess ! knowns HANDLE ! integer(HANDLE) hThread ! knowns HANDLE ! integer(DWORD) dwProcessId ! knowns DWORD ! integer(DWORD) dwThreadId ! knowns DWORD ! END TYPE ! disallow multiple child processes; previous shellouts ! must have been already terminated by the user IF (IsWindow(hwnd_ChildProcess) == 0) THEN CALL ZeroMemory (LOC(pi), SIZEOF(pi)) CALL ZeroMemory (LOC(si), SIZEOF(si)) si%cb = SIZEOF(si) si%dwFlags = STARTF_USESHOWWINDOW si%wShowWindow = SW_SHOWNORMAL IF (CreateProcess (NULL, & ! process name progname, & ! command line NULL_SECURITY_ATTRIBUTES, & ! security attributes NULL_SECURITY_ATTRIBUTES, & ! thread attributes FALSE, & ! handle inheritance 0, & ! creation flags NULL, & ! environment block NULL, & ! initial working path si, & ! startup info pi) ) THEN ! process info ! let the process load itself rval = WaitForInputIdle (pi%hProcess, 2000) ! get its window handle from the classname hwnd_ChildProcess = FindWindow (classname, NULL) ! if this fails we must never hook the main ! Kiltel window, or the system will be unreachable IF (hwnd_ChildProcess == ghwndMain) hwnd_ChildProcess = 0 CALL mousehook (hwnd_ChildProcess) rval = CloseHandle (pi%hProcess) rval = CloseHandle (pi%hThread) ! problem creating new process ELSE rval = GetLastError() SELECT CASE (rval) CASE (ERROR_FILE_NOT_FOUND) emsg = 'FILE NOT FOUND'C CASE (ERROR_DIRECTORY) emsg = 'DIRECTORY NOT FOUND'C CASE (ERROR_PATH_NOT_FOUND) emsg = 'PATH NOT FOUND'C CASE (ERROR_BAD_PATHNAME) emsg = 'BAD PATH NAME'C CASE DEFAULT emsg = 'Cannot create process'c END SELECT rval = MessageBox (ghwndMain, emsg, "Launch Error"C, & IOR(MB_OK,MB_ICONERROR)) END IF END IF END SUBROUTINE Launch
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@paul , I used to do things like in your code but Dr Fortran's method using shellexecute is much better in my opinion. It is a one liner, you tell windows to open the pdf file and let windows chose the application that is set up for opening pdfs. I found I had to otherwise 'fix' the code from time to time as windows and/or acrobat was updated.
ret = ShellExecute (& hwnd = NULL, & !!2 lpOperation = "open"C, & !!3 lpFile = trim(filename)//char(0), & !!4 lpParameters = NULL_CHARACTER, & !!5 lpDirectory = NULL_CHARACTER, & !!6 nShowCmd = SW_SHOWNORMAL) !!7
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ShellExecute also honours any customisations that the user has made - if they have associated PDF files with a viewer other than acrobat reader, they are going to be a little annoyed when your program arbitrarily ignores that association.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ianh wrote:
ShellExecute also honours any customisations that the user has made - if they have associated PDF files with a viewer other than acrobat reader, they are going to be a little annoyed when your program arbitrarily ignores that association.
Yeah, I get annoyed when apps open web pages in MSIE when I have Chrome set as default. ShellExecute is really useful for a lot of things.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve, you are absolutely right--at least for my present application, ShellExecute does exactly what I need. Tried it and it worked the first time. Thanks for posting it and the link to your excellent documentation.
For other apps I will hold the Dir c:\---- /s > LookHere.txt in reserve.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The problem with trying to do a DIR is that executable file names can change and such a DIR command can take a long time. If there's a particular application you need and ShellExecute doesn't suffice, see if the application provider offers a way to get the installed location from the registry or environment variables. There are so many things that can go wrong with a "big hammer" DIR approach.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page