MFC-CreateProcess创建一个新的进程和它的主线程并执行外部程序

发布时间 2023-04-23 13:37:17作者: 天子骄龙

 

    CONST TCHAR path[] = _T("C:\\Users\\Administrator\\Desktop\\test.exe");
    PROCESS_INFORMATION info;
    STARTUPINFO si = { sizeof(si) };

    BOOL b= CreateProcess(path,NULL,NULL,NULL, FALSE,NULL,NULL,NULL, &si, &info);//创建一个新的进程和它的主线程
    /*
    这个新进程运行指定的可执行文件
    参数1:LPCTSTR lpApplicationName  指向一个NULL结尾的,可执行文件的路径
            这个字符串可以是可执行模块的绝对路径,也可以是相对路径
            这个参数可以被设为NULL,在这种情况下,可执行模块的名字必须处于 lpCommandLine 参数最前面并由空格符与后面的字符分开
            即使指定了lpApplicationName也会把lpCommmandLine(命令行参数)原封不动的作为命令行参数传递,所以应避免重复传递可执行文件名的问题
            实际使用中常常把lpApplicationName设置为Null,用lpCommandLine参数来指定可执行文件名,这样可以扩大windows寻找可执行文件的范围
    参数2:LPTSTR lpCommandLine  这个参数用于指定传递给新进程的命令行参数
            更多时候我们把可执行文件名也包含在内(这意味着lpApplicationName应该设置为Null)
            非常量字符串
    参数3:LPSECURITY_ATTRIBUTES lpProcessAttributes   指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。
            如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承
    参数4:LPSECURITY_ATTRIBUTES lpThreadAttributes  同样是一个指向SECURITY_ATTRIBUTES结构的指针,决定的是线程是否被继承.通常置为NULL
    参数5:BOOL bInheritHandles   用于控制新进程是否可以从调用进程处继承所有可继承的句柄,而被继承的句柄与原进程拥有完全相同的值和访问权限
            设置为TRUE新进程将继承调用CreateProcess的原进程的所有可继承的句柄,而设置为FALSE则不会继承原进程的任何句柄
    参数6:DWORD dwCreationFlags  用于设置新进程创建的方式
            CREATE_DEFAULT_ERROR_MODE   新的进程不继承调用进程的错误模式。CreateProcess函数赋予新进程当前的默认错误模式作为替代
                    应用程序可以调用SetErrorMode函数设置当前的默认错误模式
            CREATE_NEW_CONSOLE  新的进程将使用一个新的控制台,而不是继承父进程的控制台。这个标志不能与DETACHED_PROCESS标志一起使用
            CREATE_NEW_PROCESS_GROUP  新进程将是一个进程树的根进程。进程树中的全部进程都是根进程的子进程
            CREATE_SEPARATE_WOW_VDM  如果被设置,新进程将会在一个私有的虚拟DOS机(VDM)中运行
            CREATE_SHARED_WOW_VDM  如果WIN.INI中的Windows段的DefaultSeparateVDM选项被设置为真,
                    这个标识使得CreateProcess函数越过这个选项并在共享的虚拟DOS机中运行新进程
            CREATE_SUSPENDED  新进程的主线程会以暂停的状态被创建,直到调用ResumeThread函数被调用时才运行
            CREATE_UNICODE_ENVIRONMENT  如果被设置,由lpEnvironment参数指定的环境块使用Unicode字符,如果为空,环境块使用ANSI字符
            DEBUG_PROCESS  如果这个标志被设置,调用进程将被当做一个调试程序,并且新进程会被当做被调试的进程。
                    系统把被调试程序发生的所有调试事件通知给调试器。
                    如果你使用这个标志创建进程,只有调用进程(调用CreateProcess函数的进程)可以调用WaitForDebugEvent函数
            DEBUG_ONLY_THIS_PROCESS  如果此标志没有被设置且调用进程正在被调试,新进程将成为调试调用进程的调试器的另一个调试对象。
                    如果调用进程没有被调试,有关调试的行为就不会产生
            DETACHED_PROCESS  对于控制台进程,新进程没有访问父进程控制台的权限。新进程可以通过AllocConsole函数自己创建一个新的控制台。
                    这个标志不可以与CREATE_NEW_CONSOLE标志一起使用
            CREATE_NO_WINDOW  系统不为新进程创建CUI窗口,使用该标志可以创建不含窗口的CUI程序

    参数7:LPVOID lpEnvironment    指向一块包含新进程要使用的环境字符串的内存,通常传入NULL表示继承原进程的环境字符串,一般是用不到的,放心传NULL就好
    参数8:LPCTSTR lpCurrentDirectory  用于设置新进程的当前驱动器和目录,
            必须是一个以’0’结尾的绝对路径字符串,如果用不到特殊设置可以直接传递NULL表示新进程的工作目录和创建新进程的原进程工作目录一致,一般就用NULL
    参数9:LPSTARTUPINFO lpStartupInfo   这个参数指向一个STARTUPINFO或STARTUPINFOEX的结构,一般应用程序会期待仅使用默认值,所以大可以全部置零
    参数10:LPPROCESS_INFORMATIONlpProcessInformation  指向LPPROCESS_INFOMATION结构的指针,
            这个结构由调用CreateProcess的进程创建,由CreateProcess更改,用于返回新建进程的信息
            typedef struct _PROCESS_INFORMATION {
                                 HANDLE hProcess;
                                 HANDLE hThread;
                                DWORD  dwProcessId;
                                 DWORD  dwThreadId;
                    } PROCESS_INFORMATION, *PPROCESS_INFORMATION,*LPPROCESS_INFORMATION;
    返回值:如果函数执行成功,返回非零值。
            如果函数执行失败,返回零
            可以使用GetLastError函数获得错误的附加信息

    */
    DWORD error = GetLastError();
    CString str;
    str.Format(_T("b=%d\r\n"),b);
    ::OutputDebugString(str);

    str.Format(_T("error=%d\r\n"), error);
    ::OutputDebugString(str);