- 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