Chapter04-CreateProcess函数详解

CreateProcess函数原型如下:

BOOL CreateProcess(
	PCTSTR pszApplicationName,
	PTSTR pszCommandLine,
	PSECURITY_ATTRIBUTES psaProcess,
	PSECURITY_ATTRIBUTES psaThread,
	BOOL bInheritHandles,
	DWORD fdwCreate,
	PVOID pvEnvironment,
	PCTSTR pszCurDir,
	PSTARTUPINFO psiStartInfo,
	PPROCESS_INFORMATION ppiProcInfo);


 
 

 
 

一、参数 PCTSTR pszApplicationName 和 参数PTSTR pszCommandLine

该参数类型为PTSTR,在函数运行过程中,CreateProcess函数会修改其值,

    但是在CreateProcess返回前又会复原为原来传入时的值.

//所以如下调用可能会出错:
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcess(NULL, TEXT("NOTEPAD"), NULL, NULL,
				FALSE, 0, NULL, NULL, &si, &pi);

//正确的调用应该是先将其传给一个变量,然后将该变量作为参数传入:
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
TCHAR szCommandLine[] = TEXT("NOTEPAD");
CreateProcess(NULL, szCommandLine, NULL, NULL,
				FALSE, 0, NULL, NULL, &si, &pi);

如果pszApplicationName 值为NULL时,CreateProcess函数就会解析pszCommandLine参数,pszCommandLine参数需要包含一个进程创建的所有参数,如新进程的可执行文件名。如果程序没有后缀名,默认的后缀名是.exe。CreateProcess函数会按照如下五种顺序来搜寻对应的程序名:

  1. 主调进程.exe文件的所在目录。
  2. 主调进程的的当前目录。
  3. windows 系统目录,即GetSystemDirectory返回的System32子文件夹。
  4. windows目录。
  5. PATH环境变量中列出的目录。

如果如果pszApplicationName 值不为NULL时,你必须在pszApplicationName传入可执行文件名(包含后缀名)。并且没有指定可执行文件的路径,reateProcess函数假设可执行文件就在当前目录,如果没有找到,则函数直接返回FALSE,不会按照上面那五种目录进行查找。实例如下:

// Make sure that the path is in a read/write section of memory.
TCHAR szPath[] = TEXT("WORDPAD README.TXT");
// Spawn the new process.
CreateProcess(TEXT("C:\\WINDOWS\\SYSTEM32\\NOTEPAD.EXE"),szPath,...);


二、参数psaProcess, psaThread, 和 bInheritHandles

创建一个新进程时一个进程和一个基线程。由于两个都是Kernel Object,都需要有两个对应的 PSECURITY_ATTRIBUTES的结构体。 psaProcess 和 psaThread 分别指向这两个结构体。你可以通过设置这两个 结构体的值来设置对应的子进程和基线程的安全属性,如果这两个值都为NULL 时,则系统将赋予进程和基线程默认 安全描述符。 父进程在 以后再创建子进程时,通过把 bInhertHandles参数设置为TRUE,就可以让新的子进程继承父进程所有
可继承的句柄(handle) 一个实例如下:

/************************************************************
Module name: Inherit.cpp
Notices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre
************************************************************/
#include <Windows.h>
#include <tchar.h>

int WINAPI _tWinMain (HINSTANCE hInstanceExe, HINSTANCE,
						PTSTR pszCmdLine, int nCmdShow) 
{
		// Prepare a STARTUPINFO structure for spawning processes.
		STARTUPINFO si = { sizeof(si) };
		SECURITY_ATTRIBUTES saProcess, saThread;
		PROCESS_INFORMATION piProcessB, piProcessC;
		TCHAR szPath[MAX_PATH];

		// Prepare to spawn Process B from Process A.
		// The handle identifying the new process
		// object should be inheritable.
		saProcess.nLength = sizeof(saProcess);
		saProcess.lpSecurityDescriptor = NULL;
		saProcess.bInheritHandle = TRUE;

		// The handle identifying the new thread
		// object should NOT be inheritable.
		saThread.nLength = sizeof(saThread);
		saThread.lpSecurityDescriptor = NULL;
		saThread.bInheritHandle = FALSE;

		// Spawn Process B.
		_tcscpy_s(szPath, _countof(szPath), TEXT("ProcessB"));
		CreateProcess(NULL, szPath, &saProcess, &saThread,
			FALSE, 0, NULL, NULL, &si, &piProcessB);

		// The pi structure contains two handles
		// relative to Process A:
		// hProcess, which identifies Process B's process
		// object and is inheritable; and hThread, which identifies
		// Process B's primary thread object and is NOT inheritable.
		// Prepare to spawn Process C from Process A.
		// Since NULL is passed for the psaProcess and psaThread
		// parameters, the handles to Process C's process and
		// primary thread objects default to "noninheritable."
		// If Process A were to spawn another process, this new
		// process would NOT inherit handles to Process C's process
		// and thread objects.
		// Because TRUE is passed for the bInheritHandles parameter,
		// Process C will inherit the handle that identifies Process
		// B's process object but will not inherit a handle to
		// Process B's primary thread object.
		_tcscpy_s(szPath, _countof(szPath), TEXT("ProcessC"));
		CreateProcess(NULL, szPath, NULL, NULL,
			TRUE, 0, NULL, NULL, &si, &piProcessC);
		return(0);
}


三、参数 fdwCreate

fdwCreate指定一些如何创建进程的标识符。同时也可以指定子进程的优先级类型。不过一般的话,都是直接将该值置为0.


四、参数 pvEnvironment

pvEnvironment指向子进程将要用到的环境变量的内存地址块。如果没有的话,就可以直接置为NULL。


五、参数 pszCurDir

pszCurDir参数可以让CreateProcess函数设置子进程的当前驱动器和目录。如果传入时是NULL,则子进程的当前驱动器和目录和父进程一样。如果传入时不为NULL,则必须是一个以'\0'结束的合法的当前驱动器和目录。


六、参数 psiStartInfo

psiStartInfo是一个指向 STARTUPINFO或 STARTUPINFOEX结构体的指针, 一般都不用怎么设置,一般只要这样初始化第一个值就可以了。如:STARTUPINFO si = { sizeof(si) };


七、参数 ppiProcInfo

ppiProcInfo 指向一个 PROCESS_INFORMATION 结构体,CreateProcess函数会对它进行初始化。

typedef struct _PROCESS_INFORMATION {

HANDLE hProcess;

HANDLE hThread;

DWORD dwProcessId;

DWORD dwThreadId;

}  PROCESS_INFORMATION;

正如上面提到的,父进程创建子进程时,会创建一个子进程对象(process kernel object)和一个基线程对象(primary thread kernel object)。hProcess 和 hThread 分别记录子进程对象的句柄和父进程对象的句柄。dwProcessId 和 dwThreadId 分别记录这个两个对象的ID号。特别需要注意的是:当CreateProcess函数创建一个个子进程对象(process kernel object)和一个基线程对(primary thread kernel object),系统就将这两个内核对象的初始引用值置为1。子进程会再打开这两个对象,此时它们的引用值就增加为 2 。也就是说如果要释放这两内核对象,则必须在父子进程中都要执行对应的CloseHandle函数。实例如下:

PROCESS_INFORMATION pi;
DWORD dwExitCode;
// Spawn the child process.
BOOL fSuccess = CreateProcess(..., &pi);
if (fSuccess) {
// Close the thread handle as soon as it is no longer needed!
CloseHandle(pi.hThread);
// Suspend our execution until the child has terminated.
WaitForSingleObject(pi.hProcess, INFINITE);
// The child process terminated; get its exit code.
GetExitCodeProcess(pi.hProcess, &dwExitCode);
// Close the process handle as soon as it is no longer needed.
CloseHandle(pi.hProcess);
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值