Edit

Create processes

The CreateProcess function creates a new process that runs independently of the creating process. For simplicity, this relationship is called a parent-child relationship.

Important

Security — handle inheritance: Set bInheritHandles to FALSE unless the child process specifically needs access to inherited handles. Inherited handles (file handles, sockets, tokens) can leak sensitive resources to child processes. When inheritance is required, use STARTUPINFOEX with UpdateProcThreadAttribute(PROC_THREAD_ATTRIBUTE_HANDLE_LIST, ...) to explicitly list only the handles the child needs.

Important

lpCommandLine must be writable: When passing a command line as the lpCommandLine parameter (second parameter), the buffer must be a writable character array — not a string literal or const pointer. The Unicode version (CreateProcessW) may modify this buffer in place. Passing a read-only string causes an access violation.

Note

Modern alternatives: For simpler process creation scenarios, consider System.Diagnostics.Process (.NET), _wspawnl/_wsystem (CRT), or ShellExecuteEx (for launching documents/URLs with verb handling). Use CreateProcess when you need full control over handle inheritance, process attributes, security descriptors, or creation flags.

The following code demonstrates how to create a process.

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

void _tmain( int argc, TCHAR *argv[] )
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    if( argc != 2 )
    {
        printf("Usage: %s [cmdline]\n", argv[0]);
        return;
    }

    // Start the child process. 
    if( !CreateProcess( NULL,   // No module name (use command line)
        argv[1],        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    ) 
    {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return;
    }

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
}

If CreateProcess succeeds, it returns a PROCESS_INFORMATION structure that contains handles and identifiers for the new process and its primary thread. The thread and process handles are created with full access rights, although you can restrict access if you specify security descriptors. When you no longer need these handles, close them by using the CloseHandle function.

You can also create a process by using the CreateProcessAsUser or CreateProcessWithLogonW functions. These functions let you specify the security context of the user account in which the process runs.