//获取当前进程中所有线程,并存入ThreadInfo
EnumThreadInfo(ThreadInfo);
if (!ThreadInfo.empty())
{
vector<THREADENTRY32>::iterator iter = ThreadInfo.begin();
HANDLE CurrTh = GetCurrentThread();
for (iter = ThreadInfo.begin(); iter != ThreadInfo.end(); iter++)
{
HANDLE th = lpfnOpenThread(THREAD_SUSPEND_RESUME, FALSE, iter->th32ThreadID);
if (th == NULL)
{
ShowError("获取所有线程的句柄时失败!");
}
CONTEXT thtext = {0};
if (th != CurrTh)
{
DWORD err = SuspendThread(th);
if (err == 0xFFFFFFFF)
{
ShowError("挂起线程时失败!");
}
//执行到这句程序崩溃,错误代码为5.
if (GetThreadContext(th, &thtext))
{
IntelStackWalk(&thtext);
}
else
{
ShowError("获取所有线程的信息时失败!");
}
err = ResumeThread(th);
if (err == 0xFFFFFFFF)
{
ShowError("运行挂起的线程时失败!");
}
}
}
}
else
{
_tprintf("未找到任何线程。。");
}
以上是在win7下运行,
在XP下程序直接挂起并不返回了。这是怎么回事啊?为什么GetThreadContext时失败?
EnumThreadInfo(ThreadInfo);
if (!ThreadInfo.empty())
{
vector<THREADENTRY32>::iterator iter = ThreadInfo.begin();
HANDLE CurrTh = GetCurrentThread();
for (iter = ThreadInfo.begin(); iter != ThreadInfo.end(); iter++)
{
HANDLE th = lpfnOpenThread(THREAD_SUSPEND_RESUME, FALSE, iter->th32ThreadID);
if (th == NULL)
{
ShowError("获取所有线程的句柄时失败!");
}
CONTEXT thtext = {0};
if (th != CurrTh)
{
DWORD err = SuspendThread(th);
if (err == 0xFFFFFFFF)
{
ShowError("挂起线程时失败!");
}
//执行到这句程序崩溃,错误代码为5.
if (GetThreadContext(th, &thtext))
{
IntelStackWalk(&thtext);
}
else
{
ShowError("获取所有线程的信息时失败!");
}
err = ResumeThread(th);
if (err == 0xFFFFFFFF)
{
ShowError("运行挂起的线程时失败!");
}
}
}
}
else
{
_tprintf("未找到任何线程。。");
}
以上是在win7下运行,
在XP下程序直接挂起并不返回了。这是怎么回事啊?为什么GetThreadContext时失败?
没有变化,GetThreadContext依然失败,错误代码5
HANDLE th = lpfnOpenThread(THREAD_SUSPEND_RESUME|THREAD_QUERY_INFORMATION, FALSE, iter->th32ThreadID);
是OpenThread函数。
还是不行,错误代码5.。我的这段代码在一个异常处理函数中执行的,这个异常函数使用SetUnhandledExceptionFilter函数设置的。我跟过,如果我开了两个线程,在某一个线程崩溃时遍历当前进程中线程还是能找到两个线程的,任务管理器也是在崩溃时显示有两个线程,但就是执行GetThreadContext函数时报错,我本意是想在程序崩溃时保存当前进程中所有线程的堆栈信息。请再帮我看看还有那地方有问题。郁闷啊。
BOOL EnumThreadInfo(vector<THREADENTRY32> &ThreadInfo)
{
ThreadInfo.clear();
// 定义线程信息结构
THREADENTRY32 te32 = {0} ;
te32.dwSize = sizeof(THREADENTRY32);
//创建系统线程快照
HANDLE hThreadSnap = CreateToolhelp32Snapshot ( TH32CS_SNAPTHREAD, 0 ) ;
if ( hThreadSnap == INVALID_HANDLE_VALUE )
return FALSE ;
// 循环枚举当前进程中的线程信息
DWORD dwOwnerPID = GetCurrentProcessId();
if ( Thread32First ( hThreadSnap, &te32 ) )
{
do{
if (te32.th32OwnerProcessID == dwOwnerPID)
{
ThreadInfo.push_back(te32);
}
}while ( Thread32Next ( hThreadSnap, &te32 ) ) ;
}
else
{
CloseHandle ( hThreadSnap ) ;
return FALSE;
}
CloseHandle ( hThreadSnap ) ;
return TRUE ;
}
否则当前线程,或者界面线程会挂起。
挂起当前线程,你的这段代码,会挂起。
挂起界面线程,你的界面会死掉。
从NT起,到XP ,对于每个窗口程序,界面线程至少有两个,其中一个是界面线程的守护线程。
请问如何判断界面线程?我在openthread之前只有线程的ID,并且上面的程序中已经过滤了当前线程,当前线程不会挂起。就算界面线程被我挂起了,界面死了,但是其他线程还在跑,就会把界面线程解挂啊~~
不处理界面消息,如何解挂,如果一个挂起的线程,使用锁和其他线程通讯,并且已经获得锁,就会造成和他公用锁的线程死锁。
if (th != CurrTh)
这个是不能排除当前线程的,任何正在运行的线程,都是当前线程。
当前线程句柄,是伪句柄,不是真正的句柄,要获取句柄;
用DuplicateHandle 复制句柄。而且,你打开线程,在判断之前,没有执行判断,线程就已经挂起了。
PS:
判断界面线程,如果没有做特殊处理,窗口创建的线程就是界面线程,可能有两个,在界面创建和界面第1~n次显示的时候,获当前线程ID和句柄,直到找到两个不同线程为止(句柄值不是0 和-1)。这两个线程不能挂起。