1、CreateProcess参数介绍

1、CreateProcess参数介绍

【并发编程二】c++创建子进程CreateProcess()

一、创建子进程

二、demo

三、构建、编译、运行

四、相关知识介绍

1、CreateProcess 参数介绍

1.1、lpApplicationName

1.2、lpCommandLine

1.3、lpProcessAttributes

1.4、lpThreadAttributes

1.5、bInheritHandles

1.6、dwCreationFlags

1.7、lpEnvironment

1.8、lpCurrentDirectory

1.9、lpStartupInfo

1.10、lpProcessInformation

2、int main(int argc, char*argv[])

五、进程相关的API

一、创建子进程

windows系统

BOOL CreateProcess(

LPCTSTR lpApplicationName, // 应用程序名称

LPTSTR lpCommandLine, // 命令行字符串

LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程的安全属性

LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性

BOOL bInheritHandles, // 是否继承父进程的属性

DWORD dwCreationFlags, // 创建标志

LPVOID lpEnvironment, // 指向新的环境块的指针

LPCTSTR lpCurrentDirectory, // 指向当前目录名的指针

LPSTARTUPINFO lpStartupInfo, // 传递给新进程的信息

LPPROCESS_INFORMATION lpProcessInformation // 新进程返回的信息

);

Linux系统popen()会调用fork()产生子进程

FILE * popen( const char * command,const char * type);

二、demo

1、父进程

main.cpp

#include

#include

using namespace std;

int main(int argc, char*argv[])

{

cout << "i am father process" << endl;

STARTUPINFO si = { sizeof(STARTUPINFO) };//在产生子进程时,子进程的窗口相关信息

PROCESS_INFORMATION pi; //子进程的ID/线程相关信息

DWORD returnCode;//用于保存子程进的返回值;

// char commandLine[] = "C:\\Users\\jx\\Desktop\\test01\\lib\\Debug\\childprocess.exe -l"; //测试命令行参数一

char commandLine[] = "childprocess.exe -l a b c"; //测试命令行参数一

BOOL bRet = CreateProcess( //调用失败,返回0;调用成功返回非0;

NULL, //一般都是空;(另一种批处理情况:此参数指定"cmd.exe",下一个命令行参数 "/c otherBatFile")

commandLine, //命令行参数

NULL, //_In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,

NULL, //_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,

FALSE, //_In_ BOOL bInheritHandles,

CREATE_NEW_CONSOLE, //新的进程使用新的窗口。

NULL, //_In_opt_ LPVOID lpEnvironment,

NULL, //_In_opt_ LPCTSTR lpCurrentDirectory,

&si, //_In_ LPSTARTUPINFO lpStartupInfo,

&pi); //_Out_ LPPROCESS_INFORMATION lpProcessInformation

if (0 != bRet)

{

std::cout << "Create Child Process sucess!" << std::endl;

//等待子进程结束

WaitForSingleObject(pi.hProcess, -1);

std::cout << "Child Process is finished" << std::endl;

//获取子进程的返回值

GetExitCodeProcess(pi.hProcess, &returnCode);

std::cout << "Child Process return code:" << returnCode << std::endl;

}

else

{

std::cout << "Create child Process error!"<

return 0;

}

system("pause");

CloseHandle(pi.hThread);

CloseHandle(pi.hProcess);

return 0;

}

CmakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)

PROJECT(process)

ADD_EXECUTABLE(process main.cpp)

ADD_SUBDIRECTORY(childprocess)

SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")

2、子进程

main.cpp

#include

using namespace std;

int main(int argc,char* argv[])

{

std::cout << "i am a child process." << std::endl;

if (argc>= 2)

{

int paramID = 0;

while (paramID < argc-1)

{

cout << argv[paramID] << endl;

paramID++;

}

std::cout << "sucess:the return code will be 0" << std::endl;

system("pause");

return 0;

}

else

{

std::cout << "failed:the return code will be -1" << std::endl;

system("pause");

return -1;

}

}

CmakeLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)

SET(TARGET "childprocess")

ADD_EXECUTABLE(childprocess main.cpp)

SET(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")

SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")

三、构建、编译、运行

1、构建

cmake -B build

2、编译

cmake --build build

3、运行

父进程输出

子进程输出

四、相关知识介绍

1、CreateProcess 参数介绍

CreatProcess()需要若干参数来指定新进程的运行方式,但实际使用中多半参数都是用不到的,可以设置为NULL

1.1、lpApplicationName

该参数的类型是LPCTSTR,其实就是一个const char*的传统C字符串,

实际使用中常常把lpApplicationName设置为Null,lpCommandLine参数来指定可执行文件名

1.2、lpCommandLine

该参数的类型是LPTSTR,即一个以’0’结尾的char*的C传统字符串

这个参数用于指定传递给新进程的命令行参数,更多时候我们把可执行文件名也包含在内(这意味着lpApplicationName应该设置为Null)

如果lpApplicationName不为Null,那lpCommandLine就会原封不动的作为命令行参数传递,所以当指定了lpApplicationNAme后就不应该再在lpCommandLine中写可执行文件名了

1.3、lpProcessAttributes

进程对象设置安全性,即返回的新进程对象句柄能否被子进程继承。

一般传递NULL,让windows把进程内核对象设为默认安全性(默认不能被继承)

1.4、lpThreadAttributes

进程对象设置安全性,

一般也传递NULL设置为默认安全性,也就是句柄不能被继承,

1.5、bInheritHandles

这个同样是关于安全性的标识符,是个BOOL型变量,用于控制新进程是否可以从调用进程处继承所有可继承的句柄,

1.6、dwCreationFlags

这是个DWORD的标识,用于设置新进程创建的方式

CREATE_NEW_CONSOLE //要求系统为新进程创建一个新的控制台窗口(否则会和原进程共用一个控制台窗口)CREATE_NO_WINDOW //不为新进程创建窗口,可以用这个来创建一个没有窗口的应用程序DEBUG_PROCESS //将新进程作为被调试程序而原进程被当做调试器,新进程和其创建的其他进程中发生的特定事件都会被通知原进程CREATE_UNICODE_ENVIRONMENT //告诉系统新进程的环境块包含Unicode字符(默认为ANSI)

1.7、lpEnvironment

这个参数指向一块包含新进程要使用的环境字符串的内存,通常传入NULL表示继承原进程的环境字符串,

1.8、lpCurrentDirectory

该参数用于设置新进程的当前驱动器和目录,必须是一个以’0’结尾的绝对路径字符串,如果用不到特殊设置可以直接传递NULL表示新进程的工作目录和创建新进程的原进程工作目录一致,一般就用NULL。

1.9、lpStartupInfo

这个参数指向一个STARTUPINFO或STARTUPINFOEX的结构,一般应用程序会期待仅使用默认值,所以大可以全部置零

1.10、lpProcessInformation

输出参数,指向一个 PROCESS_INFORMATION 结构,返回被创建进程的信息。

typedef struct _PROCESS_INFORMATION {HANDLE hProcess;HANDLE hThread;DWORD dwProcessId;DWORD dwThreadId;} PROCESS_INFORMATION, *PPROCESS_INFORMATION,*LPPROCESS_INFORMATION;

分别是进程句柄、线程句柄、进程ID和线程ID

每创建一个新进程都会产生一个进程内核对象和一个线程内核对象,前两个参数就是对应的进程对象的句柄和主线程对象的句柄,而每一个进程和线程windows都会分配一个独一无二的标识符,后两个参数就对应创建的进程的ID和进程的主线程的ID

通常情况下我们会忽略进程ID和线程ID,一般使用相应的句柄进行跟踪控制,如果一定要使用ID的话应该注意一件事:系统中ID是可重用的,这意味着当一个进程或线程终止后同一个ID会分配给其他的新进程或线程,应当及时更新ID,避免出错.

一个进程可以有多个进程句柄,但是只有一个进程id。

进程句柄和现场句柄不再使用时,建议关闭。handle(进程句柄表中的索引),这是指向对象的间接指针(在您的具体情况下,ETHREAD)。如果没有关闭,则句柄-对象(ETHREAD)将不是空闲的(直到您的进程终止,并且所有句柄都将关闭)参考进程终止后是否需要关闭线程句柄?

2、int main(int argc, char*argv[])

main 函数的参数只能有两个,还规定 argc 是整型变量,argv 是指向字符串的指针数组。

2.1、argc 是命令行总的参数个数。

2.2、char *argv[ ] 是指针数组,数组中的每个元素都是 char * 类型,即数组中每个元素都会指向一个字符串。从本文demo可以看到,子进程的argv就是父进程传递进来的lpCommandLine。

五、进程相关的API

Windows多进程编程

参考1、链接: WinAPI执行外部程序和创建新进程:CreateProcess()的使用2、链接: Windows多进程编程3、链接: windows下创建进程,CreateProcess()详解及用法

🎨 相关创意作品

微信群上限40人怎么办 微信群上限40人解决方法【教程】
自动取款机转账多久到账呢?
365bet线路检测

自动取款机转账多久到账呢?

📅 07-25 👁️ 3124
中国式网游王者之证怎么获取 中国式网游王者之证获取攻略