windows下创建进程,CreateProcess()详解及用法
2014-04-17 18:04
513 查看
windows下想要创建一个子进程不如linux的fork函数来得方便,通过CreateProcess函数创建一个新的进程,函数的定义如下
[cpp] view
plaincopy
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 // 新进程返回的信息
);
下面写一个创建进程和简单的控制示例,首先创建一个小程序,作为子进程的实体
[cpp] view
plaincopy
#include<iostream>
#include<Windows.h>
using namespace std;
int main(int argc, char *argv[])
{
cout << "args_num: " << argc << endl;
for(int i = 0;i < argc;i ++){
cout << "arg " << i << " = " << argv[i] << endl;
}
return 0;
}
主要是打印进程的传入参数列表,下面是创建子进程的代码,运行后可以看到,子进程也能获取到传入参数了。
[cpp] view
plaincopy
#include<iostream>
#include<Windows.h>
using namespace std;
int main()
{
char cWindowsDirectory[MAX_PATH];
//LPTSTR 与 wchar_t* 等价(Unicode环境下)
LPTSTR cWinDir = new TCHAR[MAX_PATH];
GetCurrentDirectory(MAX_PATH, cWinDir);
LPTSTR sConLin = wcscat(cWinDir , L"\\..\\Debug\\another.exe a b c d");
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
//创建一个新进程
if(CreateProcess(
NULL, // 指向一个NULL结尾的、用来指定可执行模块的宽字节字符串
sConLin, // 命令行字符串
NULL, // 指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。
NULL, // 如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承。<同上>
false,// 指示新进程是否从调用进程处继承了句柄。
0, // 指定附加的、用来控制优先类和进程的创建的标
// CREATE_NEW_CONSOLE 新控制台打开子进程
// CREATE_SUSPENDED 子进程创建后挂起,直到调用ResumeThread函数
NULL, // 指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境
NULL, // 指定子进程的工作路径
&si, // 决定新进程的主窗体如何显示的STARTUPINFO结构体
&pi // 接收新进程的识别信息的PROCESS_INFORMATION结构体
))
{
cout << "create process success" << endl;
//下面两行关闭句柄,解除本进程和新进程的关系,不然有可能不小心调用TerminateProcess函数关掉子进程
// CloseHandle(pi.hProcess);
// CloseHandle(pi.hThread);
}
else{
cerr << "failed to create process" << endl;
}
Sleep(100);
//终止子进程
TerminateProcess(pi.hProcess, 300);
//终止本进程,状态码
ExitProcess(1001);
return 0;
}
CreateProcess的参数虽然多而且麻烦,其实大部分设置为NULL即可,右边这个链接里面有多进程编程相关的函数介绍:http://blog.csdn.net/bxhj3014/article/details/2082255
=======================CreateProcess()详解及用法=======================
CreateProcess() 函数原型如下:
[C++] 纯文本查看 复制代码
?
该函数用来创建一个新的进程。
第 1 个参数 lpApplicationName 是输入参数,指向启动进程的 exe 文件。
第 2 个参数 lpCommandLine 是输入参数,是启动进程的命令行中的参数。
当这两个参数都不为 NULL 时,第 1 个参数指定要启动的进程 exe 文件(不带参数),第 2 个参数指定启动进程所需参数。第 1 个参数也可以为 NULL,此时第 2 个参数就不能为 NULL,在 lpCommandLine 需要指定出要启动的程序名以及所接参数,彼此间以空格隔开,其中第 1 个参数即是程序名。
第 3 个参数 lpProcessAttributes 是输入参数,指向 SECURITY_ATTRIBUTES 结构变量,是进程的安全属性,可以为 NULL 则使用默认的安全属性。
第 4 个参数 lpThreadAttributes 是输入参数,同第 3 个参数一样,指向 SECURITY_ATTRIBUTES 结构变量。
第 5个参数 bInheritHandles 是输入参数,表示新进程是否从调用进程处继承了句柄。如果参数的值为 TRUE,调用进程中的每一个可继承的打开句柄都将被子进程继承。被继承的句柄与原进程拥有完全相同的值和访问权限;如果设为 FALSE,那么不继承。
第 6 个参数 dwCreationFlags 是输入参数,表示进程的创建标志以及优先级控制。如 :CREATE_NEW_CONSOLE 会使新建的控制台程序拥有一个新的控制台;DEBUG_PROCESS 调用进程将被当作一个调试程序,并且新进程会被当作被调试的进程。系统把被调试程序发生的所有调试事件通知给调试器。
第 7 个参数 lpEnvironment 是输入参数,指向新进程的环境变量块,如果设置为 NULL,那么使用父进程的环境变量。
第 8 个参数 lpCurrentDirectory 是输入参数,指定创建后新进程的当前目录,如果设置为 NULL,那么就在父进程所在的当前目录。
第 9 个参数 lpStartupInfo 是输入参数,指向一个 STARTUPINFO 结构,该结构里可以设定启动信息,可以设置为 NULL 。
第 10 个参数 lpProcessInformation 是输出参数,指向一个 PROCESS_INFORMATION 结构,返回被创建进程的信息。
测试代码:
[C++] 纯文本查看 复制代码
?
上面程序启动谷歌 Chrome 浏览器并打开 www.groad.net 这个主页。在程序中,当第 1 个参数为 NULL 时,要启动的程序以及网址参数均指定在第 2 个参数中。注意,不能直接将参数 szPrameter 直接填写到第 2 个参数中,因为指定的命令行参数中含有空格,这样往往会造成参数解析错误,比如它会被解析成:
C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe www.groad.net.exe
也就是会认为 chrome.exe www.groad.net.exe 这就是一个程序,这是无法执行的。
而将命令行参数拷贝到数组中却是可行的,但如此一来却要多定义一个数组。如果是英文 Windows 环境,并无需构建多字符程序,那么可以将引号把路径括起来,这也不会出错,比如:
CreateProcess (NULL, "\"Path to exe\" -p1-p2 -p3", ...);
注意上面的路径使用反斜杠转义了括起路径的双引号。
但是,如果在第 1 个参数和第 2 个参数里分别指定程序名和参数,那么也无需添加一个数组来存储命令行参数,但第 2 个参数中指定的命令行参数注意前面要添加一个空格,否则可能无法正确解析参数,比如:
LPTSTR szPname = TEXT("D:\\Program Files (x86)\\Maxthon3\\Bin\\Maxthon.exe");
LPTSTR szPrameter = TEXT("www.groad.net"); //网址前无空格,错误。正确的形式是添加一个空格
这里只是针对浏览器打开网址这种情况,并非所有的情形都会没问题,比如我测试时,IE 和 MaxThon 是需要在网址面前添加空格的,否则打开的是一个空白页。但对于 Chrome ,不管网址前加不加空格都只能打开空白页,得用上面添加的数组情况方能正常。这也许和浏览器程序本身有关。如果用的是记事打开一些文本,如果后面的文本路径参数不添加空格,那么打开空白,反之正常;而对于 UE ,那么即使后面不添加空格也照样打开,所以从这两个例子看来,仍然是和程序本身有关。但是,添加一个空格会保持较好的兼容性,如若还不行,可以考虑用一个数组来接纳所有的命令行参数。
另外,程序中使用了 WaitForSingleObject() 函数以等待子进程的退出,如当我们关闭了浏览器,那么上面的程序也随之结束,否则一直在那等待。
转:http://www.groad.net/bbs/thread-6367-1-1.html
[cpp] view
plaincopy
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 // 新进程返回的信息
);
下面写一个创建进程和简单的控制示例,首先创建一个小程序,作为子进程的实体
[cpp] view
plaincopy
#include<iostream>
#include<Windows.h>
using namespace std;
int main(int argc, char *argv[])
{
cout << "args_num: " << argc << endl;
for(int i = 0;i < argc;i ++){
cout << "arg " << i << " = " << argv[i] << endl;
}
return 0;
}
主要是打印进程的传入参数列表,下面是创建子进程的代码,运行后可以看到,子进程也能获取到传入参数了。
[cpp] view
plaincopy
#include<iostream>
#include<Windows.h>
using namespace std;
int main()
{
char cWindowsDirectory[MAX_PATH];
//LPTSTR 与 wchar_t* 等价(Unicode环境下)
LPTSTR cWinDir = new TCHAR[MAX_PATH];
GetCurrentDirectory(MAX_PATH, cWinDir);
LPTSTR sConLin = wcscat(cWinDir , L"\\..\\Debug\\another.exe a b c d");
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
//创建一个新进程
if(CreateProcess(
NULL, // 指向一个NULL结尾的、用来指定可执行模块的宽字节字符串
sConLin, // 命令行字符串
NULL, // 指向一个SECURITY_ATTRIBUTES结构体,这个结构体决定是否返回的句柄可以被子进程继承。
NULL, // 如果lpProcessAttributes参数为空(NULL),那么句柄不能被继承。<同上>
false,// 指示新进程是否从调用进程处继承了句柄。
0, // 指定附加的、用来控制优先类和进程的创建的标
// CREATE_NEW_CONSOLE 新控制台打开子进程
// CREATE_SUSPENDED 子进程创建后挂起,直到调用ResumeThread函数
NULL, // 指向一个新进程的环境块。如果此参数为空,新进程使用调用进程的环境
NULL, // 指定子进程的工作路径
&si, // 决定新进程的主窗体如何显示的STARTUPINFO结构体
&pi // 接收新进程的识别信息的PROCESS_INFORMATION结构体
))
{
cout << "create process success" << endl;
//下面两行关闭句柄,解除本进程和新进程的关系,不然有可能不小心调用TerminateProcess函数关掉子进程
// CloseHandle(pi.hProcess);
// CloseHandle(pi.hThread);
}
else{
cerr << "failed to create process" << endl;
}
Sleep(100);
//终止子进程
TerminateProcess(pi.hProcess, 300);
//终止本进程,状态码
ExitProcess(1001);
return 0;
}
CreateProcess的参数虽然多而且麻烦,其实大部分设置为NULL即可,右边这个链接里面有多进程编程相关的函数介绍:http://blog.csdn.net/bxhj3014/article/details/2082255
=======================CreateProcess()详解及用法=======================
CreateProcess() 函数原型如下:
[C++] 纯文本查看 复制代码
?
第 1 个参数 lpApplicationName 是输入参数,指向启动进程的 exe 文件。
第 2 个参数 lpCommandLine 是输入参数,是启动进程的命令行中的参数。
当这两个参数都不为 NULL 时,第 1 个参数指定要启动的进程 exe 文件(不带参数),第 2 个参数指定启动进程所需参数。第 1 个参数也可以为 NULL,此时第 2 个参数就不能为 NULL,在 lpCommandLine 需要指定出要启动的程序名以及所接参数,彼此间以空格隔开,其中第 1 个参数即是程序名。
第 3 个参数 lpProcessAttributes 是输入参数,指向 SECURITY_ATTRIBUTES 结构变量,是进程的安全属性,可以为 NULL 则使用默认的安全属性。
第 4 个参数 lpThreadAttributes 是输入参数,同第 3 个参数一样,指向 SECURITY_ATTRIBUTES 结构变量。
第 5个参数 bInheritHandles 是输入参数,表示新进程是否从调用进程处继承了句柄。如果参数的值为 TRUE,调用进程中的每一个可继承的打开句柄都将被子进程继承。被继承的句柄与原进程拥有完全相同的值和访问权限;如果设为 FALSE,那么不继承。
第 6 个参数 dwCreationFlags 是输入参数,表示进程的创建标志以及优先级控制。如 :CREATE_NEW_CONSOLE 会使新建的控制台程序拥有一个新的控制台;DEBUG_PROCESS 调用进程将被当作一个调试程序,并且新进程会被当作被调试的进程。系统把被调试程序发生的所有调试事件通知给调试器。
第 7 个参数 lpEnvironment 是输入参数,指向新进程的环境变量块,如果设置为 NULL,那么使用父进程的环境变量。
第 8 个参数 lpCurrentDirectory 是输入参数,指定创建后新进程的当前目录,如果设置为 NULL,那么就在父进程所在的当前目录。
第 9 个参数 lpStartupInfo 是输入参数,指向一个 STARTUPINFO 结构,该结构里可以设定启动信息,可以设置为 NULL 。
第 10 个参数 lpProcessInformation 是输出参数,指向一个 PROCESS_INFORMATION 结构,返回被创建进程的信息。
测试代码:
[C++] 纯文本查看 复制代码
?
C:\\Users\\Administrator\\AppData\\Local\\Google\\Chrome\\Application\\chrome.exe www.groad.net.exe
也就是会认为 chrome.exe www.groad.net.exe 这就是一个程序,这是无法执行的。
而将命令行参数拷贝到数组中却是可行的,但如此一来却要多定义一个数组。如果是英文 Windows 环境,并无需构建多字符程序,那么可以将引号把路径括起来,这也不会出错,比如:
CreateProcess (NULL, "\"Path to exe\" -p1-p2 -p3", ...);
注意上面的路径使用反斜杠转义了括起路径的双引号。
但是,如果在第 1 个参数和第 2 个参数里分别指定程序名和参数,那么也无需添加一个数组来存储命令行参数,但第 2 个参数中指定的命令行参数注意前面要添加一个空格,否则可能无法正确解析参数,比如:
LPTSTR szPname = TEXT("D:\\Program Files (x86)\\Maxthon3\\Bin\\Maxthon.exe");
LPTSTR szPrameter = TEXT("www.groad.net"); //网址前无空格,错误。正确的形式是添加一个空格
这里只是针对浏览器打开网址这种情况,并非所有的情形都会没问题,比如我测试时,IE 和 MaxThon 是需要在网址面前添加空格的,否则打开的是一个空白页。但对于 Chrome ,不管网址前加不加空格都只能打开空白页,得用上面添加的数组情况方能正常。这也许和浏览器程序本身有关。如果用的是记事打开一些文本,如果后面的文本路径参数不添加空格,那么打开空白,反之正常;而对于 UE ,那么即使后面不添加空格也照样打开,所以从这两个例子看来,仍然是和程序本身有关。但是,添加一个空格会保持较好的兼容性,如若还不行,可以考虑用一个数组来接纳所有的命令行参数。
另外,程序中使用了 WaitForSingleObject() 函数以等待子进程的退出,如当我们关闭了浏览器,那么上面的程序也随之结束,否则一直在那等待。
转:http://www.groad.net/bbs/thread-6367-1-1.html
相关文章推荐
- 【转载】详解CreateProcess调用内核创建进程的过程
- 详解CreateProcess调用内核创建进程的过程
- 进程创建过程详解 CreateProcess
- Windows下创建进程-CreateProcess()
- 进程创建函数CreateProcess()与创建流程详解
- windows和linux的进程创建 CreateProcess 和 fork
- windows 下在一个进程中使用createprocess创建一个窗口进程,并获取这个窗口的HWND句柄
- Windows下的进程创建API--CreateProcess使用经验漫谈
- Windows创建进程winAPI-CreateProcess
- linux ulimit命令参数及用法详解--linux限定shell启动进程资源
- 思路:如何跳过CreateProcess调用底层创建进程函数
- 第四章 进程(6)CreateProcess函数详解
- windows创建一个执行可执行文件的进程!
- useradd命令_Linux useradd 命令用法详解:创建的新的系统用户
- squid命令_Linux squid 命令用法详解:squid服务器守护进程
- windows内核状态下进程创建解析
- Windows操作系统下创建进程的过程
- Linux下进程的创建过程分析(_do_fork/do_fork详解)--Linux进程的管理与调度(八)【转】
- YII Framework框架使用YIIC快速创建YII应用之migrate用法实例详解
- linux守护进程原理及创建详解