必威体育Betway必威体育官网
当前位置:首页 > IT技术

CreateProcess 创建带命令行参数的进程时,报错或者提示内存位置无效的可能的一个原因

时间:2019-06-16 14:43:11来源:IT技术作者:seo实验室小编阅读:89次「手机版」
 

createprocess

可能的一个原因:命令行参数使用了常量。

例如:

CreateProcess(NULL, "notepad",NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&si,&pi);

解释:

pszApplicationName和pszCommandLine分别表示进程使用的可执行文件名和向其传递的命令行字符串,注意pszCommandLine是PTSTR,这意味着你必须为其传递指向非常量字符串的地址。CreateProcess内部会更改向其传递的命令行字符串,但在CreateProcess返回之前,它会将该字符串恢复原样。这一点是非常重要的,因为如果你向CreateProcess传递的命令行字符串位于进程的只读存储区,就会发生Access Violation错误。

微软在其C++编译器选项中提供了/GF开关,/GF打开时,程序中所有用到的常量字符串将只维护单一副本,且位于只读存储部分。在调用 CreateProcess时,开发人员应该打开/GF开关并使用缓冲区。我们希望微软在未来版本的Windows中会改进CreateProcess,使其接受常量字符串作为命令行参数,并在其内部分配/释放临时缓冲区而不是让API调用者来做。另外,假如你使用常量ANSI字符串作为 CreateProcess参数,并不会发生Access Violation错误,我们在前面的章节已经提到过,许多WinAPI函数的ANSI版本会将ANSI参数转换为UNIDOE编码后调用其 Unicode版本,CreateProcess会把ANSI字符串转换为Unicode编码后放在临时缓冲区,并调用Unicode版的 CreateProcess,因此不会触发Access Violation。

你如果想要一个动态长度命令行参数,可以参考下面的代码

STARTUPINFO si = { sizeof(si) };

PROCESS_INFORMATION pi;

LPTSTR pszCmd = new TCHAR[strCmd.length()+1];

memset(pszCmd,0,sizeof(TCHAR)*(strCmd.length()+1));

_tcscpy(pszCmd,strCmd.c_str());

CreateProcess(NULL, pszCmd,NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&si,&pi);

WaitForSingleObject(pi.hProcess,INFINITE);

CloseHandle(pi.hProcess);

额外说一点,我在做上述测试时发现,调用CreateProcess来调用cmd.exe,我的程序没报错,但是系统却报cmd.exe应用程序错误(无法正常启动0xc0000142)。但是我手动启动cmd.exe,又可以正常启动。

通过查询一篇文章发现:STARTUPINFO si = { sizeof(si) };很关键。

当你直接写STARTUPINFO si;此时si里面一些内容可能是随机的。如果你没有清空其内容,STARTUPINFO(EX)的内容会是调用线程堆栈上的一些数据。将这些垃圾数据传递给CreateProcess可能导致无法预料的结果,为了让CreateProcess正常工作,你必须将STARTUPINFO(EX)中没有用到的域清0。

个人水平有限,如有错误请联系我更改。活到老,学到老!

相关阅读

用CreateProcessAsUser 创建最低权限进程

高 管理权限(进程可以将文件安装到“Program Files”文件夹,并写入敏感注册表区域,如 HKEY_LOCAL_MACHINE。)中 用户权限(进程可在用户

使用CreateProcessAsUser的范例代码

-------- CreateProcessEx.h文件 -------- #ifndef _CREATE_PROCESS_EX_H_ #define _CREATE_PROCESS_EX_H_ #include <windo

分享到:

栏目导航

推荐阅读

热门阅读