- 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