- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
this is somewhat of a continuation of an issue that I've had here, which was very helpfully solved.
now I've ran into an issue where I need to call an executable and redirect the input.
Previsouly it was done via:
CALL SYSTEM('C:\DATA\Executable.exe < Instruction.txt')
Calling an executable is not an issue, I've found some examples out there for CreateProcess winapi and it works fine. Below is a sample code that I've adopted.
SUBROUTINE ExecuteProgram(CommanLine)
USE KERNEL32
IMPLICIT NONE
CHARACTER(LEN=*), INTENT(IN) :: CommanLine
INTEGER :: rval
TYPE(T_STARTUPINFO) :: si
TYPE(T_PROCESS_INFORMATION) :: pi
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
CommanLine, & ! 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
rval = WaitForSingleObject (pi%hProcess, INFINITE)
rval = CloseHandle (pi%hProcess)
rval = CloseHandle (pi%hThread)
END IF
END SUBROUTINE ExecuteProgram
Now how on earth can I redirect input?
Thanks in advance!
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What you are asking is really a Windows API question rather than a Fortran question; since the code that you showed is simply Fortran "glue" code for Windows Kernel32 calls. The natural answer is that you should locate a similar Windows API call for redirecting input, or call CMD.EXE and use its redirection facilities.
I do not do Windows programming, so I cannot give you a specific answer.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The STARTUPINFO structure has a component for a standard input handle. https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/ns-processthreadsapi-_startupinfoa
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve for the pointers.
I've redirected the StdIn of the child process to a pipe and also have sent the intruction. I now have a different issues.
The child process essentially promts the user for the name of the input file and then for name of the output file.
Using Call System(Program.exe < Input.txt) this executes the program just fine.
The contents of the pipe are identical to the information in Input.txt, however the child process just sits there not advancing past the initial promt. What am I missing?
Below is my current code including a bit where I just check the read end of the pipe to see if the information arrives.
SUBROUTINE ExecuteProgram(CommandLine)
USE KERNEL32
IMPLICIT NONE
CHARACTER(LEN=*), INTENT(IN) :: CommandLine
INTEGER :: rval
INTEGER(HANDLE) :: hR = NULL, hW = NULL, HT
LOGICAL(BOOL) :: WriteDone = .FALSE.
INTEGER(DWORD) :: dwRead = 0, dwWritten = 0
CHARACTER(LEN=20) :: StrIn
TYPE(T_STARTUPINFO) :: si
TYPE(T_PROCESS_INFORMATION) :: pi
TYPE(T_SECURITY_ATTRIBUTES) :: sa
sa%nLength = sizeof(sa)
sa%lpSecurityDescriptor = NULL
sa%bInheritHandle = TRUE
IF(.NOT.CreatePipe(hR,hW,sa,0)) STOP
IF(.NOT.SetHandleInformation(hW, HANDLE_FLAG_INHERIT, 0)) STOP
CALL ZeroMemory (LOC(pi), SIZEOF(pi))
CALL ZeroMemory (LOC(si), SIZEOF(si))
si%cb = SIZEOF(si)
si%dwFlags = STARTF_USESHOWWINDOW
si%wShowWindow = SW_SHOWNORMAL
si%hStdInput = hR
si%hStdOutput = NULL
si%hStdError = NULL
!si%dwFlags = .NOT.STARTF_USESTDHANDLES
IF (CreateProcess (NULL, & ! process name
CommandLine, & ! command line
NULL, & ! security attributes
NULL, & ! thread attributes
TRUE, & ! handle inheritance
0, & ! creation flags
NULL, & ! environment block
NULL, & ! initial working path
si, & ! startup info
pi) ) THEN ! process info
rval = CloseHandle (pi%hProcess)
rval = CloseHandle (pi%hThread)
ELSE
Stop
END IF
StrIn = 'gas.inp'//CHAR(13)//CHAR(10)//'gas.out'//CHAR(13)//CHAR(10)
WriteDone = WriteFile(hW, Loc(StrIn), SizeOf(StrIn), loc(dwWritten), NULL)
IF(.NOT.CloseHandle(hW)) STOP
!hT = CreateFile('C:\test\INPUT.TXT',GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL)
!WriteDone = ReadFile(hT, Loc(StrIn), SizeOf(StrIn), loc(dwRead), NULL)
!WriteDone = WriteFile(hW, Loc(StrIn), dwRead, loc(dwWritten), NULL)
!IF(.NOT.CloseHandle(hT)) STOP
!IF(.NOT.CloseHandle(hW)) STOP
!Quick and dirty, check the read end of the pipe
hW = CreateFile('C:\test\OUTPUT.TXT',GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL)
WriteDone = ReadFile(hR, Loc(StrIn), SizeOf(StrIn), loc(dwRead), NULL)
WriteDone = WriteFile(hW, Loc(StrIn), dwRead, loc(dwWritten), NULL)
IF(.NOT.CloseHandle(hW)) STOP
END SUBROUTINE ExecuteProgram
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I've never worked with pipes, but if I were facing this situation I would first create a test case using separate programs and run them each in the debugger to make sure the pipe I/O was working properly. Note that you can also attach the debugger to different processes.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page