请问大家
如果发现一个进程被调试,如何去强制结束它?哪怕连调试器也结束都行。网上看到些判断父进程PID的方法,但不好用,因为那个进程可能不是被调试器调入装载的,如在任务管理器中右击鼠标,选调试(有调试器的情况下),被调试的进程的父进程PID并不是调试器!另外,用ProcessExplorer工具可以暂停某个进程,暂停之后,那个进程也无法通过任务管理器去结束了,直接来说,就是无法通过TerminateProcess来结束,又该如何解决?

解决方案 »

  1.   

    1.使用Windows XP/2000自带的工具从Windows 2000开始,Windows系统就自带了一个用户态调试工具Ntsd,它能够杀掉大部分进程,因为被调试器附着的进程会随调试器一起退出,所以只要你在命令行下使用Ntsd调出某进程,然后退出Ntsd即可终止该进程,而且使用Ntsd会自动获得Debug权限,因此Ntsd能杀掉大部分的进程。操作方法:单击“开始”/程序/附件/命令提示符,输入命令:ntsd -c q -p PID(把最后那个PID,改成你要终止的进程的PID)。在进程列表中你可以查到某个进程的PID,例如我们要关闭图1中的Explorer.exe进程,输入:ntsd -c q -p 408即可。以上参数-p表示后面跟随的是进程PID, -c q表示执行退出Ntsd的调试命令,从命令行把以上参数传递过去就行了。2. 使用专门的软件来杀进程任务管理器杀不掉的进程,你可以使用专门的软件关闭。有很多软件可以杀进程,例如进程杀手、IceSword、柳叶擦眼、系统查看大师、Kill process等。
      

  2.   

    老大,不行啊。我试过了。icesword,ntsd都不行。
      

  3.   

      ntsd -c q -p PID      把最后那个PID,改成你要终止的进程的ID。如果你不知道进程的ID,任务管理器->进程选项卡->查看->选择列->勾上"PID(进程标识符)",然后就能看见了。
    因为被调试器附着的进程会随调试器一起退出,可能你要去取,你的调试器PID.
      

  4.   

    ntsd   -c   q   -p   PID
    我知道PID怎么取。如果是一般情况下,是可以结束掉,但使用这条命令的时候,VC++已经在调试那个进程中。
      

  5.   

    lz是不是先要结束VC++的调试啊?
    看来你的环境,和我很不一样啊,可否说清楚你具体在做什么?
      

  6.   

    试了:
    VC++已经在调试那个进程中 
    这时用
    ntsd   -c  q -p 1768
    返回如下:
    Microsoft(R) Windows 2000 Debugger
    Version 5.00.2184.1
    Copyright (C) Microsoft Corp. 1981-1999CommandLine:
    NTSD: cannot debug pid 1768 (error = 5)
    NTSD: exiting - press enter --->要结束pid =1768 的进程
    通过结束 MSDEV.EXE 可以实现(因为被调试器附着的进程会随调试器一起退出,可能你要去取你的调试器PID 
    ,这里的调试器是vc 既 MSDEV.EXE)直接在任务管理器中就可以结束MSDEV.EXE .
    同时试了.net 2003调试器 既devenv.exe,结束它,也就结束被它调试的进程。
      

  7.   

    mabaoyes 
    你说的要结束调试器是可以,但是,我如何得知哪个调试器在进行调试呢?必竟未必只有VC一种调试器啊,
    另外,被processExplorer暂停时也不知道怎么好.我要做的是,不让我的进程被"暂停"(调试),麻烦大家了.
      

  8.   

    提升自身进程到debug以上权限以后就能关闭调试中的进程function EnableDebugPriv: Boolean;
    var
      hToken: THandle;
      tp: TTokenPrivileges;
      rl: Cardinal;
    begin
      Result := false;  //打开进程令牌环
      OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
        hToken);  //获得进程本地唯一ID
      if LookupPrivilegeValue(nil, 'SeDebugPrivilege', tp.Privileges[0].Luid) then
      begin
        tp.PrivilegeCount           := 1;
        tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
        //调整权限
        Result := AdjustTokenPrivileges(hToken, false, tp, SizeOf(tp), nil, rl);
      end;
    end;关于 OpenProcessToken() 和 AdjustTokenPrivileges() 两个 API 的简单介绍:OpenProcessToken():获得进程访问令牌的句柄.
      function OpenProcessToken(
        ProcessHandle: THandle; //要修改访问权限的进程句柄
        DesiredAccess: DWORD; //指定你要进行的操作类型
        var TokenHandle: THandle//返回的访问令牌指针
      ): BOOL; AdjustTokenPrivileges() :调整进程的权限.
      function AdjustTokenPrivileges(
        TokenHandle: THandle;  // 访问令牌的句柄
        DisableAllPrivileges: BOOL; // 决定是进行权限修改还是除能(Disable)所有权限
        const NewState: TTokenPrivileges;  
        { 指明要修改的权限,是一个指向TOKEN_PRIVILEGES结构的指针,该结构包含一个数组,
           数据组的每个项指明了权限的类型和要进行的操作; }
        BufferLength: DWORD;  
        //结构PreviousState的长度,如果PreviousState为空,该参数应为 0
        var PreviousState: TTokenPrivileges; 
        // 指向TOKEN_PRIVILEGES结构的指针,存放修改前的访问权限的信息
        var ReturnLength: DWORD //实际PreviousState结构返回的大小
      ) : BOOL;SeSecurityPrivilege
        SeBackupPrivilege
        SeRestorePrivilege
        SeSystemtimePrivilege
        SeShutdownPrivilege
        SeRemoteShutdownPrivilege
        SeTakeOwnershipPrivilege
        SeDebugPrivilege
        SeSystemEnvironmentPrivilege
        SeSystemProfilePrivilege
        SeProfileSingleProcessPrivilege
        SeIncreaseBasePriorityPrivilege
        SeLoadDriverPrivilege
        SeCreatePagefilePrivilege
        SeIncreaseQuotaPrivilege
        SeChangeNotifyPrivilege
        SeUndockPrivilege
        SeManageVolumePrivilege
        SeImpersonatePrivilege
        SeCreateGlobalPrivilege
        SeInteractiveLogonRight
        SeNetworkLogonRight
        SeRemoteInteractiveLogonRight
        .....
    权限定义可以查表