Running system commands without opening a shell window

Running system commands without opening a shell window

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!

7 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
Retired 12/31/2016

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.

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

Retired 12/31/2016

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=''), 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.


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.)

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_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.
		! 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 = ''
	!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


Leave a Comment

Please sign in to add a comment. Not a member? Join today