Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28655 Discussions

Running system commands without opening a shell window

Jacob_Williams
New Contributor II
1,420 Views

My application is compiled with /SUBSYSTEM:WINDOWS, and I want to call some system commands without having a shell window appear.  SYSTEM and SYSTEMQQ open the shell window.  RUNQQ doesn't open a shell window, but it also doesn't seem to work for generic system commands, so I can't use it.  Is there an easy way to make this happen?  Do I have to resort to a Windows CreateProcess call, or is there an easy way to get the Intel routines to do what I want?  Thanks!

0 Kudos
6 Replies
Steven_L_Intel1
Employee
1,420 Views
0 Kudos
Jacob_Williams
New Contributor II
1,420 Views

I think this one doesn't wait for the process to finish, right?  I need one that waits for it to finish, like SYSTEMQQ does.

0 Kudos
Steven_L_Intel1
Employee
1,420 Views

Correct. In that case you will need to use CreateProcess. See here for an example.

0 Kudos
Jacob_Williams
New Contributor II
1,420 Views

It appears that CreateProcess is expecting the lpApplicationName to be an exe file.  Is that correct?  In my case, I want to make a generic system call that could be an exe, or a .bat file, a python script, or whatever.  Basically, the same stuff that SYSTEMQQ will accept, or can be typed into a DOS prompt.  When I try to use CreateProcess to run a python script (lpApplicationName='myscript.py'), it doesn't execute (error 193: ERROR_BAD_EXE_FORMAT).

Is it a path issue?  Do I need to do anything special to get the process to access the path environment variable?  When I open up a DOS prompt or use SYSTEMQQ I can execute this script fine using the script name.

Thanks!

0 Kudos
IanH
Honored Contributor II
1,420 Views

Yes - the "application" basically needs to be an executable of some sort (though I don't think .exe is mandatory) that the operating system loader knows how to handle.  Batch files and other scripts are not recognised at that level.

The usual solution to this is for your CreateProcess call to actually execute cmd.exe and ask it to execute the script.  In the msdn help for CreateProcess, see the last sentence of the description of the lpApplicationName parameter.

(I recall some special casing by CreateProcess of cmd.exe as an application, perhaps involving interaction with the COMSPEC environment variable or some sort of guarantee that you always get the real system command interpreter regardless of what games the user might play.  But I don't see that mentioned in the CreateProcess help.)

0 Kudos
Jacob_Williams
New Contributor II
1,420 Views

Thanks!  I think I've got it now.  For the record, here is the code.  runqq_v2 is the alternate RUNQQ that doesn't open a shell window when using /SUBSYSTEM:WINDOWS.  The example shows how to call it to execute a non-"application" using a cmd shell.


!********************************************************************************
	subroutine runqq_v2(filename,commandline,status_ok)
!********************************************************************************
	use kernel32
	use ifwinty
	use iso_c_binding,	only: C_NULL_CHAR
		
	implicit none

 	character(len=*),intent(in) :: filename
	character(len=*),intent(in) :: commandline
	logical,intent(out)			:: status_ok
		
	type(T_PROCESS_INFORMATION)	:: pinfo
	type(T_STARTUPINFO)			:: startupinfo
	integer						:: ret, path_len

	startupinfo = T_STARTUPINFO(	cb				= sizeof(startupinfo),&
									lpReserved		= 0,&
									lpDesktop		= 0,&
									lpTitle			= 0,&
									dwX				= 0,&
									dwY				= 0,&
									dwXSize			= 0,&
									dwYSize			= 0,&
									dwXCountChars	= 0,&
									dwYCountChars	= 0,&
									dwFillAttribute = 0,&
									dwFlags			= STARTF_USESHOWWINDOW,&
									wShowWindow		= SW_HIDE,&
									cbReserved2		= 0,&
									lpReserved2		= 0,&
									hStdInput		= 0,&
									hStdOutput		= 0,&
									hStdError		= 0)
 		
	ret = CreateProcess (	lpApplicationName	 = trim(filename)//C_NULL_CHAR,&
							lpCommandLine		 = trim(commandline)//C_NULL_CHAR,&
							lpProcessAttributes	 = NULL,&
							lpThreadAttributes	 = NULL,&
							bInheritHandles		 = TRUE,&
							dwCreationFlags		 = 0,&
							lpEnvironment		 = NULL,&
							lpCurrentDirectory	 = NULL,&
							lpStartupInfo		 = startupinfo,&
							lpProcessInformation = pinfo)
								
	if (ret == 0) then	!error
			
		ret = GetLastError()
		write(*,*) 'CreateProcess failed with error ', ret
		status_ok = .false.
			
	else
			
		! CreateProcess succeeded.
		status_ok = .true.
				
		!Wait for the process to finish
		ret = WaitForSingleObject(pinfo%hProcess, INFINITE)
			
		! Close handles, otherwise resources are lost
		ret = CloseHandle(pinfo%hThread)
		ret = CloseHandle(pinfo%hProcess)
			
	end if

!********************************************************************************
	end subroutine runqq_v2
!********************************************************************************	
	
!********************************************************************************	
	subroutine example()
!********************************************************************************	
	implicit none
	
	logical :: status_ok
	character(len=:),allocatable :: cmd_path,cmd_str
	integer :: ilen
		
	!get path to the shell:
	call get_environment_variable('ComSpec',length=ilen)
	allocate( character(len=ilen) :: cmd_path )
	call get_environment_variable('ComSpec',value=cmd_path)
	
	!script to run:
	cmd_str = 'myscript.py'
		
	!run the script from the command shell:
	call runqq_v2(cmd_path,'/c '//cmd_str,status_ok)
	if (.not. status_ok) write(*,*) 'Error'
		
!********************************************************************************	
	end subroutine example
!********************************************************************************	

 

0 Kudos
Reply