情况分两种
不带参数启动子进程
MS提供了调试方法
/// 不带参数启动的子进程自动附加调试方法, MS已经提供
/// http://msdn.microsoft.com/en-us/library/a329t4ed(v=vs.90).aspx
/// <<How to: Launch the Debugger Automatically>>
当主进程CreateProcess 符合名字的EXE子进程时, 子进程就会被我们的调试器接住.
带参数启动子进程
这种情况, MS提供的方法不适用. 调试器不识别传来的参数, 调试器会弹出报错提示, 说 "参数.exe" 找不到
我想到的解决方法如下:
* 用OD实例1 启动主进程, 单步到CreateProcess执行前, 记录下子进程名称和命令行参数
* 用OD实例2 按照主进程建立子进程的名称和命令行参数,启动子进程.
* 在OD实例1中, 跳过主进程中CreateProcess的代码, 注意堆栈平衡, 使主进程能继续跑下去.
这样就可以用2个OD实例,连续调试主进程和子进程. 即使主进程和子进程有交互, 也不影响.
主进程自己启动子进程,穿进的参数仅为 "命令行参数"
用OD打开进程的命令行参数 为 "子程序全路径 + 命令行参数"
为了完全模拟主进程CreateProcess的结果, 需要在OD实例2中, 将命令行参数指针,手工改改,指到具体的命令行参数上.
被调试的程序一般都不是我们写的, 为了模拟出和主进程一样的参数给子进程用, 需要找到子进程用命令行参数的地方,手工将参数指针改掉.
例如:
主程序测试代码
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
/// 主程序是多字节版本
#define CREATE_PROCESS_BY_CMD_LINE
#define SUB_PROC_NAME "showcmd.exe"
#define CMD_LINE_PARAM "abc 111 222 333 444 555"
void main()
{
BOOL bRc = TRUE;
PROCESS_INFORMATION psInfo;
STARTUPINFO sInfo;
LPVOID lpMsgBuf = NULL;
memset((char *)&sInfo, 0, sizeof(STARTUPINFO));
sInfo.cb = sizeof(STARTUPINFO);
sInfo.dwFlags = STARTF_USESTDHANDLES;
sInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
/*
BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);
*/
#ifdef CREATE_PROCESS_BY_CMD_LINE
/// CreateProcess 启动带参数的子进程
bRc = CreateProcess(SUB_PROC_NAME,
CMD_LINE_PARAM,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&sInfo,
&psInfo);
#else
/// CreateProcess 启动不带参数的子进程
/// 不带参数启动的子进程自动附加调试方法, MS已经提供
/// http://msdn.microsoft.com/en-us/library/a329t4ed(v=vs.90).aspx
/// <<How to: Launch the Debugger Automatically>>
bRc = CreateProcess(SUB_PROC_NAME,
"",
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&sInfo,
&psInfo);
#endif
::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL);
if (NULL != lpMsgBuf)
{
printf("%s",lpMsgBuf);
LocalFree(lpMsgBuf);
lpMsgBuf = NULL;
}
_tprintf(_T("END, press any key to quit\r\n"));
getwchar();
}