项目总结——关于调试api和vc中的createprocess

http://blog.163.com/tom19900920@126/blog/static/23498687201211355458952/

 

今天是值得纪念的一天,纠结了我半年的问题,今天终于完全解决了额,呵呵。两个字开心,打心眼里笑了。其中需要记录的值得所有人看下的问题,如下。

  1.调试api:用了调试api的人,也许都在惊讶其强悍的功能吧,但不知道是否有人试过,按照网上的教程,自己写个程序,程序的内容是:创建一个进程,进程干的事情很简单,执行一个exe,然后删除这个exe。其实就是有点坏心思的代码。呵呵。用DeleteFile删除试下。最后会返回TRUE,然后整个程序一闪而过。去看那个exe文件,确实是被删除了。但是我想说的是,其实DeleteFile删除是失败了的,因为这个函数有延迟删除的作用,也就是当系统中没有这个文件的句柄时,才会真正删除。有兴趣的人可以去试下,其实我想说的是,问题就是出在调试api中,每进行一次WaitForDebugEvent后,就会增加一个句柄,而且这个句柄就是指向这个exe文件的文件句柄(de.u.CreateProcessInfo.hFile)。在每进行下一次的时候必须CloseHandle一下。现在就ok了,如果想看效果就用vc调试一下吧。整体代码如下

while(WaitForDebugEvent(&de,INFINITE)!=0)//waitfordebugevent函数,当发生调试事件时,返回非零 {   printf("\n异常码:%d",de.dwDebugEventCode);   switch(de.dwDebugEventCode)   {   case EXCEPTION_DEBUG_EVENT:    {     if (exceptioncount==0)//因为在进程开始运行时,会发出此异常     {      exceptioncount++;      IsContinue=TRUE;      printf("\n程序开始运行了");     }     else     {      IsContinue=DealException(&de,exceptioncode);//对异常进行处理     }    }break;   case EXIT_PROCESS_DEBUG_EVENT:    {     printf("\n进程发出结束请求了,结束码:%d",de.u.ExitProcess.dwExitCode);     IsNeedToWait=FALSE;//因为进程正常结束了,所以下面不需要用waitforsignalobject等待了     IsContinue=FALSE;    }break;   case CREATE_PROCESS_DEBUG_EVENT://创建进程    {     printf("\n创建进程");    }break;   case CREATE_THREAD_DEBUG_EVENT:    {     printf("\n创建线程");

   }break;   case  EXIT_THREAD_DEBUG_EVENT:    {     printf("\n结束线程");    }break;   case LOAD_DLL_DEBUG_EVENT:    {     printf("\n加载动态链接库");    }break;   case OUTPUT_DEBUG_STRING_EVENT:    {     printf("\n有测试输出");    }break;   case RIP_EVENT:    {     printf("\nsystem debugging error");    }break;   case UNLOAD_DLL_DEBUG_EVENT:    {     printf("\n卸载动态链接库");    }break;   }   ContinueDebugEvent(processinformation.dwProcessId,processinformation.dwThreadId,DBG_CONTINUE);     if (IsContinue==FALSE)   {    printf("\n程序快要退出了");    break;   }   CloseHandle(de.u.CreateProcessInfo.hFile); }

现在反过来再想一下,其实也是,因为为了实现对一个程序的完全控制,有时候是需要更改程序的指令的,以实现完全控制的效果,简单用现有的几个调试api,是不能完成很多特别的功能,因此,提供文件句柄是对的,但是这就不得不说下,为什么微软把文件句柄放在CreateProcessInfo呢?根据msdn的解释,当发生进程创建,线程创建的调试事件时,就可以从CreateProcessInfo中获取对应的线程,进程句柄。但是却没有说这些句柄怎么来的,怎么回事,根据测试,发现,进程句柄线程句柄应该是DuplicateHandle来的,而文件句柄则是每次都open一下(也许不是用的createfile)。但是微软却一直没有强调,或者说明在每次调试的时候,这个文件句柄都需要关闭(有与线程,进程句柄是DuplicateHandle的,所以不需要关闭)。而且更可恨的是,在中国的各个网上,却竟然没有一处提过要关闭调试循环结构中的文件句柄。而且都是千篇一律的同一个来自msdn的循环体。额。。对于关心技术的我而言,这现象,不知道该怎么解释了额

2:最后顺带提下,在vc开发环境中,用createprocess,由于本次在项目开发中,老是因为句柄没关闭完,导致文件删除异常,因此,一边通过任务管理器中的进程句柄数,一边调试,以观察程序每步运行的句柄创建情况,最后惊奇的发现,调用CreateProcess,竟然返回了4个句柄,而另外一处返回了3个句柄,按照这个函数的返回参数理解,其实正常情况下,只应该返回两个句柄的。最后多方查看,网上寻个千百度。默然误解,想到先看看效果,突然发现,竟然一切都没有按照预料的那样,句柄数呈倍数增加,而是稳定在一个范围,最后和同学讨论才得出结论,程序应该没有问题了,调试过程中出现的CreateProcess返回的句柄数不正确,可能来自两个原因,第一。我们是用vc调试的,为了实现单步调试,它是在当前进程中额外创建了线程的,当调用CreateProcess时,它也有备份了一部分句柄。第二。因为现在程序的句柄仍然只是稳定在一个范围,所以,当调用CreateProcess的时候,系统是额外创建了一些句柄的,由于我调试的原因,断住了程序,因此会在任务管理器中看到非正常的句柄数

  现在总体来说,整个程序能很稳定的运行了,两个字,高兴,于是留下此文章,好让大家能有资源可以找到,也为自己以后可以再看看哈

posted @ 2013-01-04 14:53  cityhunter2008  阅读(386)  评论(0)    收藏  举报