- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am launching a "legacy" DOS app from another cosole app. The display from the old DOS app is extensive and for many repeated launches it comsumes a lot of time. So I have tried to run it using CreateProcess instead of RUNQQ. However, the child app still shows its dos screen. It seems to share the same the caller (i.e. no different from runqq).
I would like to know how to do this to prevent the callee from doing all the elaborate text output.
Here is the heart of the createProcess call:
!STARTUPINOF sets the properties of the thread
call ZeroMemory (LOC (si), SIZEOFSTARTUPINFO)
dwCreate = IOR(HIGH_PRIORITY_CLASS,dwCreate)! /h
dwCreate = IAND(NOT(CREATE_NEW_CONSOLE),dwCreate) !turn off this bit to supress the DOS screen
!set to hide the console window
si%dwFlags =STARTF_USESHOWWINDOW
si%wShowWindow =SW_HIDE
!other startup info
si%cb= SIZEOFSTARTUPINFO
sa%nLength = SIZESECURITYATTRIBUTES
sa%lpSecurityDescriptor = NULL
sa%bInheritHandle = .true.
sb%nLength = SIZESECURITYATTRIBUTES
sb%lpSecurityDescriptor = NULL
sb%bInheritHandle = .true.
!Get the Path info
call zeromemory (LOC(szPath), len(szPath))
res=GETDRIVEDIRQQ(szpath)+1
szPath(res:res)=char(0)
!Run the requested PROGRAM (can we check for return code?)
call zeromemory (LOC(szArgs), SIZEOFszArgs)
szArgs= trim(cmd)//char(0) !watch SIZEOFSzArgs
! szArgs= 'cmd.exe /c '//trim(cmd)//char(0) !watch SIZEOFSzArgs
! res=len_trim(szArgs)+1 ; szArgs(res:res)=char(0)
fSuccess = CreateProcess(null_character, & szArgs, & ! command line (including program name)NULL_security_attributes, & NULL_security_attributes, &
.FALSE., & ! new process inherits handles?
dwCreate, & ! creation flags
NULL, & ! environment
szPath, & ! new current DirName si, & ! STARTUPINFO structure
pi) ! PROCESSINFORMATION structure
Also I would like to know if this scheme can return the exit/return code of the callee the way runqq would. Would it be in fuccess?
Thanks in advance
Tim H
I would like to know how to do this to prevent the callee from doing all the elaborate text output.
Here is the heart of the createProcess call:
!STARTUPINOF sets the properties of the thread
call ZeroMemory (LOC (si), SIZEOFSTARTUPINFO)
dwCreate = IOR(HIGH_PRIORITY_CLASS,dwCreate)! /h
dwCreate = IAND(NOT(CREATE_NEW_CONSOLE),dwCreate) !turn off this bit to supress the DOS screen
!set to hide the console window
si%dwFlags =STARTF_USESHOWWINDOW
si%wShowWindow =SW_HIDE
!other startup info
si%cb= SIZEOFSTARTUPINFO
sa%nLength = SIZESECURITYATTRIBUTES
sa%lpSecurityDescriptor = NULL
sa%bInheritHandle = .true.
sb%nLength = SIZESECURITYATTRIBUTES
sb%lpSecurityDescriptor = NULL
sb%bInheritHandle = .true.
!Get the Path info
call zeromemory (LOC(szPath), len(szPath))
res=GETDRIVEDIRQQ(szpath)+1
szPath(res:res)=char(0)
!Run the requested PROGRAM (can we check for return code?)
call zeromemory (LOC(szArgs), SIZEOFszArgs)
szArgs= trim(cmd)//char(0) !watch SIZEOFSzArgs
! szArgs= 'cmd.exe /c '//trim(cmd)//char(0) !watch SIZEOFSzArgs
! res=len_trim(szArgs)+1 ; szArgs(res:res)=char(0)
fSuccess = CreateProcess(null_character, & szArgs, & ! command line (including program name)NULL_security_attributes, & NULL_security_attributes, &
.FALSE., & ! new process inherits handles?
dwCreate, & ! creation flags
NULL, & ! environment
szPath, & ! new current DirName si, & ! STARTUPINFO structure
pi) ! PROCESSINFORMATION structure
Also I would like to know if this scheme can return the exit/return code of the callee the way runqq would. Would it be in fuccess?
Thanks in advance
Tim H
Link Copied
15 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
See CREATE_NEW_CONSOLE or DETACHED_PROCESS flags in documentation on CreateProcess.
Also, take a look on GetExitCodeProcess API (it can return the exit code even if the process has finished, until you CloseHandle(hProcess)).
Jugoslav
Also, take a look on GetExitCodeProcess API (it can return the exit code even if the process has finished, until you CloseHandle(hProcess)).
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Duj,
I changed my dwCreate to:
dwCreate = IOR(HIGH_PRIORITY_CLASS,dwCreate)
dwCreate = IOR(DETACHED_PROCESS,dwCreate)
dwCreate = IAND(NOT(CREATE_NEW_CONSOLE),dwCreate)
But I get the error: ERROR_INVALID_PARAMETER
The same happens with the thrid line above, taken out. Any hints?
Thanks again, Tim
I changed my dwCreate to:
dwCreate = IOR(HIGH_PRIORITY_CLASS,dwCreate)
dwCreate = IOR(DETACHED_PROCESS,dwCreate)
dwCreate = IAND(NOT(CREATE_NEW_CONSOLE),dwCreate)
But I get the error: ERROR_INVALID_PARAMETER
The same happens with the thrid line above, taken out. Any hints?
Thanks again, Tim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
DETACHED_PROCESS leaves the process without any console to write to so I'm not surprised it doesn't work -- but I wouldn't expect that kind of error (I'd expect a crash on first WRITE(*) statement). Nevertheless, I think the winning combination is HIGH_PRIORITY_CLASS + CREATE_NEW_CONSOLE.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry to be dense,
I am now thoroughly confused!
1. Are you saying that your initial idea of adding "Detached process" was not the way to go?
2. Are you saying that "Create new console" IS necessary?
3. But if I add (instead of exclude) "Create new console" I get a new console which is just what I want to avoid!
Your further help will be appreciated.
Tim H
I am now thoroughly confused!
1. Are you saying that your initial idea of adding "Detached process" was not the way to go?
2. Are you saying that "Create new console" IS necessary?
3. But if I add (instead of exclude) "Create new console" I get a new console which is just what I want to avoid!
Your further help will be appreciated.
Tim H
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, my first suggestion was based just on reading the docs -- when you said that DETACHED_PROCESS doesn't work I thought about it and found that it probably crashes when first WRITE(* is encountered. It would probably work if output is redirected to a file or a pipe (SI%hStdOutput) but I think it's an unnecesary complication.
OTOH, what's wrong with CREATE_NEW_CONSOLE? You also have SI%wShowWindow=SW_HIDE so the new console will be invisible.
OTOH, what's wrong with CREATE_NEW_CONSOLE? You also have SI%wShowWindow=SW_HIDE so the new console will be invisible.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Nothing is wrong with it.
I assumed that sw_HIDE simply _minimizes the window but I did not want ANY console created. Did I misunderstand?
I have used NOT(new_console) (and only HIGH_priority) with success in the context of a (com)DLL. SO the distinction seems to be from the fact that a console-app is calling createProcess.
Does this give any ideas?
One other related thing. As for the "exit code" you said to look at GetExitCodeProcess. Now Fortran pointers are uneccessaerily complicated (as compared to say C). I have no clue how to handle the DWord pointer args in GetExitCodeProcess. Do I just declare integer(dword) and use its value? Is there not a de-ref necessary??
Tim
p.s. Thanks for your time.
I assumed that sw_HIDE simply _minimizes the window but I did not want ANY console created. Did I misunderstand?
I have used NOT(new_console) (and only HIGH_priority) with success in the context of a (com)DLL. SO the distinction seems to be from the fact that a console-app is calling createProcess.
Does this give any ideas?
One other related thing. As for the "exit code" you said to look at GetExitCodeProcess. Now Fortran pointers are uneccessaerily complicated (as compared to say C). I have no clue how to handle the DWord pointer args in GetExitCodeProcess. Do I just declare integer(dword) and use its value? Is there not a de-ref necessary??
Tim
p.s. Thanks for your time.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Is the "legacy" app also in Fortran or is this just some executable for which you have no source? Does it accept any input from the user, or does it just list a bunch of stuff to the console for which you have no use?
Also, you don't need any pointers to use GetExitCodeProcess. Just pass the location of the integer.
James
Also, you don't need any pointers to use GetExitCodeProcess. Just pass the location of the integer.
James
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
> Nothing is wrong with it.
> I assumed that sw_HIDE simply _minimizes the window
> but I did not want ANY console created. Did I
> misunderstand?
Yes you did -- SW_MINIMIZE minimizes it and SW_HIDE hides it completely.
> I have used NOT(new_console) (and only HIGH_priority)
> with success in the context of a (com)DLL. SO the
> distinction seems to be from the fact that a
> console-app is calling createProcess.
>
> Does this give any ideas?
Well, in this case I'd prefer approach "make it work and let it stay that way" :-). It's possible also that the actual "callee" makes the difference. CVF console applications crash during WRITE(* when there's no console; I think that MSVC ones don't (I'm not sure).
> One other related thing. As for the "exit code" you
> said to look at GetExitCodeProcess. Now Fortran
> pointers are uneccessaerily complicated (as compared
> to say C). I have no clue how to handle the DWord
> pointer args in GetExitCodeProcess. Do I just declare
> integer(dword) and use its value? Is there not a
> de-ref necessary??
Just a general hint for "translating" API arguments: (to be on the safe side, always take a look at actual INTERFACE in ...DFInclude):
1) LPCTSTR, LPTSTR arguments usually translate to CHARACTER(*)
2) LPSomeStructure usually translates to SomeStructure
3) LPWORD, LPDWORD require LOC(iVariable)
4) LPVOID or LPBYTE is tricky; it is commonly used when the argument can be of more types. Usually, it requires LOC(Something).
For example:
Jugoslav
> I assumed that sw_HIDE simply _minimizes the window
> but I did not want ANY console created. Did I
> misunderstand?
Yes you did -- SW_MINIMIZE minimizes it and SW_HIDE hides it completely.
> I have used NOT(new_console) (and only HIGH_priority)
> with success in the context of a (com)DLL. SO the
> distinction seems to be from the fact that a
> console-app is calling createProcess.
>
> Does this give any ideas?
Well, in this case I'd prefer approach "make it work and let it stay that way" :-). It's possible also that the actual "callee" makes the difference. CVF console applications crash during WRITE(* when there's no console; I think that MSVC ones don't (I'm not sure).
> One other related thing. As for the "exit code" you
> said to look at GetExitCodeProcess. Now Fortran
> pointers are uneccessaerily complicated (as compared
> to say C). I have no clue how to handle the DWord
> pointer args in GetExitCodeProcess. Do I just declare
> integer(dword) and use its value? Is there not a
> de-ref necessary??
Just a general hint for "translating" API arguments: (to be on the safe side, always take a look at actual INTERFACE in ...DFInclude):
1) LPCTSTR, LPTSTR arguments usually translate to CHARACTER(*)
2) LPSomeStructure usually translates to SomeStructure
3) LPWORD, LPDWORD require LOC(iVariable)
4) LPVOID or LPBYTE is tricky; it is commonly used when the argument can be of more types. Usually, it requires LOC(Something).
For example:
1) GetCurrentDirectory(LEN(sDir), sDir) 2) LPSTARTUPINFO in CreateProcess 3) GetExitCodeProcess(hProcess, LOC(iExitCode)) 4) CHARACTER(100) szFile INTEGER nFiles ... RegQueryValueEx(hKey, "nFiles"C, 0, LOC(iType), LOC(szFile), LOC(iSize)) RegQueryValueEx(hKey, "MRUList"C, 0, LOC(iType), LOC(nFiles), LOC(iSize))
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The "legacy" code is not in fortran and its source is in another language for which I do not have a compiler besides its age. Reworking it in cvf will takes way more time than I'd like to spend.
It prints a huge amount of junk to the screen which slows things down on multiple calls.
tim
It prints a huge amount of junk to the screen which slows things down on multiple calls.
tim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the detailed answer Duj.
I undestand your point about twriting to a non-existent console, but the error as I've stated is the funny "invalid parameter".
I will try the hiding setup. Mymain need to eliminate the the consuming excessive screen writes to shorten long run times. One way or another makes no difference,
thanks again,
Tim
I undestand your point about twriting to a non-existent console, but the error as I've stated is the funny "invalid parameter".
I will try the hiding setup. Mymain need to eliminate the the consuming excessive screen writes to shorten long run times. One way or another makes no difference,
thanks again,
Tim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I asked because if it wasn't written in Fortran, you may be able to redirect standard output elsewhere by creating a suitable file handle (the null file seems ideal) and when you do your CreateProcess just have it inherit handles.
James
James
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jim, I looked up CreateProcess again, but have no idea how the handle inheriting scheme would work.
Care to give a sketch?
Thanks, Tim
Care to give a sketch?
Thanks, Tim
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A simple example. This runs a program that both does console output and has a side effect (to prove that it ran :-). Replace the command in the CreateProcess call as needed.
James
program spawn_quiet_child use kernel32 implicit none type (T_STARTUPINFO) si type (T_PROCESS_INFORMATION) pi integer(HANDLE) hNl integer(DWORD) status hNl = CreateFile('nul'c,GENERIC_ALL,0,NULL,OPEN_EXISTING,0,NULL) si%cb = SIZEOF (si) si%dwFlags = STARTF_USESTDHANDLES si%hStdInput = hNl si%hStdOutput = hNl si%hStdError = hNl if (CreateProcess(NULL,'msg /v * Hello'c,NULL,NULL,TRUE,0,NULL,NULL,si,pi) /= 0) then type *, 'Process created', pi%dwProcessId else type *, 'CreateProcess error', GetLastError() end if pause if (GetExitCodeProcess(pi%hProcess,LOC(status)) /= 0) then type '(a,z8.8)', 'exit code was ', status end if end
James
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'd be more comfortable if all the fields in si were initialized.
Steve
Steve
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortunately the compilers give us a zero'd structure. :-) Seriously, initializing variables, checking return status and closing/deallocating resources should always be done for production code, this is just something to illustrate a concept while saving some forum real estate, so is just enough to "work".
James
James
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page