Solved

CreateProcess API Call

Posted on 1998-06-09
10
760 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
0
Comment
Question by:peterwest
  • 5
  • 4
10 Comments
 
LVL 4

Expert Comment

by:yowkee
ID: 1462898
   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.
0
 
LVL 5

Accepted Solution

by:
bin_huwairib earned 100 total points
ID: 1462899
peterwest,

It is important to understand that at creation time, the system gives each object an initial usage count of one. Then, just before CreateProcess returns, the function opens both the process and the thread object and places the process-relative handles for each in the hProcess and hThread members of the PROCESS_INFORMATION structure.
 
When CreateProcess opens these objects, the usage count for each increments to two. This means that before the Windows NT Executive can free the process object, the process must terminate (decrementing the usage count to one) and the parent process must call CloseHandle (decrementing the usage count to zero). To free the thread object, the thread must terminate and the parent process must close the handle to the thread object.
 
CAUTION: It is very important to close these handles. Failure to do so can result in a system memory leak because some Windows NT Executive objects are never destroyed.
 
Similar considerations are required when obtaining a process handle with OpenProcess. In this case too, the usage count is incremented by one, and unless the handle is closed, the process object will remain in memory even when the process itself has terminated.

Check the following example.
0
 
LVL 5

Expert Comment

by:bin_huwairib
ID: 1462900
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
0
 
LVL 2

Author Comment

by:peterwest
ID: 1462901
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
0
 
LVL 5

Expert Comment

by:bin_huwairib
ID: 1462902
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
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 2

Author Comment

by:peterwest
ID: 1462903
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

0
 
LVL 5

Expert Comment

by:bin_huwairib
ID: 1462904
peterwest,

OK, then remove the line:

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

0
 
LVL 2

Author Comment

by:peterwest
ID: 1462905
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

0
 
LVL 5

Expert Comment

by:bin_huwairib
ID: 1462906
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
0
 
LVL 2

Author Comment

by:peterwest
ID: 1462907
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

0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now