We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

CreateProcess API Call

peterwest
peterwest asked
on
Medium Priority
866 Views
Last Modified: 2012-06-21
Hi there,

I'm using the CreateProcess API call to spawn an instance of another programme.  There are typically two different scenarios where this call is being used.  The first is one where the process is created and then the WaitForSingleObject call is used to ensure that the process completes before execution continues and the other is where the process is simply created and then execution continues.  My question relates to this second scenario.

In the event of creating the process and then continuing is there anything else I need to do with the process??  At the moment i'm just closing the handle to the process using CloseHandle(handle id) - will this cause any problems??  The process I am starting is created in it's own WOW VDM and I left the programme running for a few hours and the machine crashed because it ran out of memory - i've got a suspicion that I've got a memory leak and I wondered if it was related to the creation of these processes!!!

Any ideas?

Pete
Comment
Watch Question

Commented:
   For creating process and then continuing, you have nothing else need to do instead of CreateProcess. And if you have no need to refer to the created process any more, closehandle on both process handle and the thread handle (both in last parameter PROCESS_INFORMATION) are OK. The calls to Closehandle cause the system to decrement the usage count for the process and thread to 0(if no other program refer to that process), allow object's memory to be freed.

If you are running multiple VDMs, each VDM consumes a significant amount of physical storage(memory). That might be the problem to crash the program.

Hope this help.
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
Example
=======
Private Type PROCESS_INFORMATION
 hProcess As Long
 hThread As Long
 dwProcessId As Long
 dwThreadId As Long
End Type
 
Private Type STARTUPINFO
 cb As Long
 lpReserved As String
 lpDesktop As String
 lpTitle As String
 dwX As Long
 dwY As Long
 dwXSize As Long
 dwYSize As Long
 dwXCountChars As Long
 dwYCountChars As Long
 dwFillAttribute As Long
 dwFlags As Long
 wShowWindow As Integer
 cbReserved2 As Integer
 lpReserved2 As Long
 hStdInput As Long
 hStdOutput As Long
 hStdError As Long
End Type
 
Private Declare Function CreateProcess Lib "kernel32" Alias _
      "CreateProcessA" (ByVal lpApplicationName As String, ByVal _
      lpCommandLine As String, lpProcessAttributes As Any, _
      lpThreadAttributes As Any, ByVal bInheritHandles As Long, _
      ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal _
      lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, _
      lpProcessInformation As PROCESS_INFORMATION) As Long
 
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal _
      dwAccess As Long, ByVal fInherit As Integer, ByVal hObject _
      As Long) As Long
 
Private Declare Function TerminateProcess Lib "kernel32" (ByVal _
      hProcess As Long, ByVal uExitCode As Long) As Long
 
Private Declare Function CloseHandle Lib "kernel32" (ByVal _
      hObject As Long) As Long
 
Const SYNCHRONIZE = 1048576
Const NORMAL_PRIORITY_CLASS = &H20&
 
Private Sub Form1_Click()
 Dim pInfo As PROCESS_INFORMATION
 Dim sInfo As STARTUPINFO
 Dim sNull As String
 
 sInfo.cb = Len(sInfo)
 success& = CreateProcess(sNull, "Calc.exe", ByVal 0&, ByVal 0&, _
      1&, NORMAL_PRIORITY_CLASS, ByVal 0&, sNull, sInfo, pInfo)
 
 MsgBox "Calculator has been launched!"
 
 ret& = TerminateProcess(pInfo.hProcess, 0&)
 ret& = CloseHandle(pInfo.hThread)
 ret& = CloseHandle(pInfo.hProcess)
 
 MsgBox "Calculator has terminated!"
End Sub


Best regards
Bin Huwairib

Author

Commented:
Hi again,

Just one final thing that i need to know... At the moment i'm using CreateProcess to spawn a programme, once the API call has been made I immediately unload the application that generated the instance of the programme and the newly created process carries on running.  How can I use a TerminateProcess API call for this??   I assumed that because I closed the handles in my app, as soon as the spawned programme finished it would terminate the process and release the memory to the system!!

Thanks

Pete
peterwest,

You should use TerminateProcess API before closing the process handle to make sure that memory was released properly, check my above example.

Bin Huwairib

Author

Commented:
Hi again,

Won't using the TerminateProcess API call simply terminate the application that I've just spawned??  I need this application to continue running once i've terminated the application that created it....

Pete

peterwest,

OK, then remove the line:

 ret& = TerminateProcess(pInfo.hProcess, 0&)

Author

Commented:
Hi,

That's what i've got already - here's a copy of the sub-routine I use to spawn the programme.  There parameters are thus:

sProgName - The directory and name of the executable
sProgDescript - A description of the programme, simply used to display a status message
bHidden - Determines if the spawned programme will be visible or not
bWin16App - If set to true then the programme is initialised in it's own WOW VDM session.
bWaitUntilDone - If set to true the programme waits for the process to complete before continuing.

-----------------------------------------------------------------
Sub SpawnProgramme(sProgName As String, sProgDescript As String, bHidden As Boolean, Optional bWin16App As Boolean, Optional bWaitUntilDone As Boolean)
'------------------------------------------------------------------------------------------------------------------------
' This routine spawns an instance of the specified programme and, depenedent on the calling parameters, will either wait
' until the process terminates before continuing or will simply carry on, allowing the process to continue.
'------------------------------------------------------------------------------------------------------------------------
' Written by:   P. J. West
' Date:         8th June 1998
'------------------------------------------------------------------------------------------------------------------------

    'Declare local variables
    Dim ProcInfo As PROCESS_INFORMATION
    Dim StartInfo As STARTUPINFO
    Dim lRetVal As Long
   
    'Set up the error handler
    On Error GoTo SpawnProgrammeError
   
    'Initialise the startupinfo structure
    StartInfo.cb = Len(StartInfo)
    StartInfo.dwFlags = STARTF_USESHOWWINDOW
    StartInfo.wShowWindow = Not bHidden
   
    'Update the status panel
    statPanel.Text = "Spawning instance of " + Trim$(sProgDescript) + "..."
   
    DoEvents
   
    'Create the shelled process; if bWin16App was set true then create the process in it's own WOW VDM
    If bWin16App Then
        lRetVal = CreateProcessA(0&, sProgName, 0&, 0&, 0&, NORMAL_PRIORITY_CLASS Or CREATE_SEPARATE_WOW_VDM, 0&, 0&, StartInfo, ProcInfo)
    Else
        lRetVal = CreateProcessA(0&, sProgName, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, StartInfo, ProcInfo)
    End If
   
    'If the calling routine specified that this command must be executed before continuing then loop until
    'the process is completed
    If bWaitUntilDone Then
        statPanel.Text = "Waiting for instance of " + Trim$(sProgDescript) + " to complete..."
        DoEvents
        Do
            lRetVal = WaitForSingleObject(ProcInfo.hProcess, 500)
            DoEvents
        Loop Until lRetVal = 0
    End If
   
    'Close the handle to the process and the thread
    lRetVal = CloseHandle(ProcInfo.hProcess)
    lRetVal = CloseHandle(ProcInfo.hThread)
   
Exit Sub

SpawnProgrammeError:
    DoEvents
    sModule = "FRMMAIN.FRM"
    sProcedure = "SpawnProgramme"
    sReference = ""
    sMessage = Err.Description
    iNumber = Err.Number
    sAction = ProcessError()
    FreeLocks
    Select Case sAction
    Case "Resume"
        Resume
    Case "Resume Next"
        Resume Next
    Case Else
        Unload Me
        End
    End Select
    DoEvents

End Sub

peterwest,

Your code didn't work with me, so I've made some changes in it and it is working fine now, here it is.

Private Type PROCESS_INFORMATION
 hProcess As Long
 hThread As Long
 dwProcessId As Long
 dwThreadId As Long
End Type

Private Type STARTUPINFO
 cb As Long
 lpReserved As String
 lpDesktop As String
 lpTitle As String
 dwX As Long
 dwY As Long
 dwXSize As Long
 dwYSize As Long
 dwXCountChars As Long
 dwYCountChars As Long
 dwFillAttribute As Long
 dwFlags As Long
 wShowWindow As Integer
 cbReserved2 As Integer
 lpReserved2 As Byte
 hStdInput As Long
 hStdOutput As Long
 hStdError As Long
End Type

Private Type SECURITY_ATTRIBUTES
 nLength As Long
 lpSecurityDescriptor As Long
 bInheritHandle As Long
End Type

Private Const STARTF_USESHOWWINDOW = &H1
Private Const NORMAL_PRIORITY_CLASS = &H20
Private Const SW_HIDE = 0
Private Const SW_SHOW = 5

Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As Any, lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Sub SpawnProgramme(sProgName As String, sProgDescript As String, bHidden As Boolean, Optional bWin16App As Boolean, Optional bWaitUntilDone As Boolean)
 Dim ProcInfo As PROCESS_INFORMATION
 Dim StartInfo As STARTUPINFO
 Dim lRetVal As Long
 Dim sNull As String

 On Error GoTo SpawnProgrammeError

 StartInfo.cb = Len(StartInfo)
 StartInfo.dwFlags = STARTF_USESHOWWINDOW
 StartInfo.wShowWindow = IIf(bHidden, SW_HIDE, SW_SHOW)
 Text1.Text = "Spawning instance of " + Trim$(sProgDescript) + "..."

 DoEvents

 'Create the shelled process; if bWin16App was set true then create the process in it's own WOW VDM
 If bWin16App Then
  'lRetVal = CreateProcess(0&, sProgName, 0&, 0&, 0&, NORMAL_PRIORITY_CLASS Or CREATE_SEPARATE_WOW_VDM, 0&, 0&, StartInfo, ProcInfo)
 Else
  lRetVal = CreateProcess(sNull, sProgName, ByVal 0&, ByVal 0&, 1&, NORMAL_PRIORITY_CLASS, ByVal 0&, sNull, StartInfo, ProcInfo)
 End If

 'If the calling routine specified that this command must be executed before continuing then loop until
 'the process is completed
 If bWaitUntilDone Then
  Text1.Text = "Waiting for instance of " + Trim$(sProgDescript) + " to complete..."
  DoEvents
  Do
   lRetVal = WaitForSingleObject(ProcInfo.hProcess, 500)
   DoEvents
  Loop Until lRetVal = 0
 End If

 'Close the handle to the process and the thread
 lRetVal = CloseHandle(ProcInfo.hProcess)
 lRetVal = CloseHandle(ProcInfo.hThread)
Exit Sub

SpawnProgrammeError:
 MsgBox Err.Description
 Resume Next
End Sub

Private Sub Command1_Click()
 SpawnProgramme "calc.exe", "Calculater", False, False, False
End Sub


* By the way I only used the code on 32 bit enviornment, I didn't check it on 16-bit.

Bin Huwairib

Author

Commented:
Hi again,

I give up - the whole reason I was using the api to create the process in a seperate WOW VDM was because when my application was respawned it in turn generated another process which caused the session to crash.

The process generated by my programme is now no longer required so I can create all the other processes in a single shared VDM.  Problem solved.

Thanks for your help anyway

Pete

Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.