最近使用CreateProcess创建rundll32.exe进程,发现并没有正常加载DLL,后来才发现是命令行参数传错了,CreateProcess并不是我想象的那样,网上找了一下,发现还有许多东西不是想的那么简单。下面的文字翻译自《INFO: Understanding CreateProcess and Command-line Arguments》
创建32位进程时CreateProcess的行为
案例1
如果传递了ApplicationName参数,且CommandLine参数是NULL,那么ApplicationName参数同时也会被当做CommandLine参数。但这并不意味着你可以在ApplicationName参数中添加额外的命令行参数。比如下面的代码就无法成功创建进程:
CreateProcess("c:\\MyApp.exe Param1 Param2", NULL, ... ); |
案例2
如果传递了CommandLine参数,且ApplicationName参数是NULL,那么CreateProcess会尝试从CommandLine中提取ApplicationName。
案例3
当ApplicationName和CommandLine两个参数同时都使用的时候,就会体现出CreateProcess的灵活性了(也是容易混淆的地方)。这时候允许你指明要执行的程序以及要传给程序的完整的命令行参数。你也许会认为传递给创建的程序的命令行参数是ApplicationName和CommandLine的组合,但实际上不是这样的。实际情况是,由CreateProcess创建的进程可以接收一个指定的参数填充到argv[0],下面的例子就会产生这种不正常现象:
CreateProcess( "c:\\MyApp.exe", "Param1 Param2 Param3", ...); |
MyApp的命令参数将会是这样的:
argv[0] == "Param1" argv[1] == "Param2" argv[2] == "Param3" |
此外,在《Windows核心编程》中提到,CreateProcess函数的lpCommandLine参数类型为LPTSTR,这意味着CreateProcess期望你将传递一个非常量字符串的地址,从内部来讲,CreateProcess实际上要修改你传递给它的命令行字符串,不过,在CreateProcess返回之前,它将该字符串恢复为它的原始形式。所以如果传递的是常量字符串,那么可能会引发违规访问的异常。
所以,CreateProcess正确的写法应该这样:
TCHAR szPath[MAX_PATH] = {L"C:\\Windows\\System32\\rundll32.exe"}; TCHAR szCmdLine[MAX_PATH] = { L"C:\\Windows\\System32\\rundll32.exe" L" D:\\Test.dll,TestFunc" // 注意前面的空格 }; STARTUPINFO si = {sizeof(si)}; PROCESS_INFORMATION pi = {0}; BOOL bRet = FALSE; bRet = CreateProcess( szPath, szCmdLine, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); |
参考:
《Windows核心编程》
《INFO: Understanding CreateProcess and Command-line Arguments》
本博客很少转载他人文章,如未特别标明,均为原创,转载请注明出处:
本文出自程序人生 >> CreateProcess的命令行参数
作者:代码疯子