OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <windows.h> | |
6 | |
7 #include <stdio.h> | |
8 #include <tchar.h> | |
9 #include <tlhelp32.h> | |
10 | |
11 #include <algorithm> | |
12 #include <iostream> | |
13 #include <iterator> | |
14 #include <map> | |
15 #include <sstream> | |
16 #include <string> | |
17 | |
18 // List all thread names in a process specified. | |
19 BOOL ListProcessThreadNames(DWORD dwOwnerPID); | |
20 | |
21 // The GetThreadDescription API is available since Windows 10, version 1607. | |
22 // The reason why this API is binded in this way rather than just using the | |
23 // Windows SDK, is to make it consistent with the bind of SetThreadDescription | |
24 // in Chrome. Binding SetThreadDescription API in Chrome can only be done via | |
stanisc
2017/02/23 19:19:44
You could just say that this API isn't yet availab
chengx
2017/02/23 20:45:06
Done.
| |
25 // the system dll, rather than SDK. | |
26 typedef HRESULT(WINAPI* GETTHREADDESCRIPTION)(HANDLE hThread, | |
27 PWSTR* threadDescription); | |
28 | |
29 int main(void) { | |
30 unsigned int processId; | |
31 std::string user_input; | |
32 while (true) { | |
33 std::cout | |
34 << "\nPlease enter the process Id, or \"quit\" to end the program : "; | |
35 std::getline(std::cin, user_input); | |
36 std::cout << std::endl; | |
37 if (user_input == "quit") | |
38 break; | |
39 std::stringstream ss(user_input); | |
40 if (ss >> processId) { | |
41 ListProcessThreadNames(processId); | |
42 } else { | |
43 std::cout << "input is invalid" << std::endl; | |
44 } | |
45 std::cout << std::endl; | |
46 } | |
47 return 0; | |
48 } | |
49 | |
50 BOOL ListProcessThreadNames(DWORD dwOwnerPID) { | |
51 auto get_thread_description_func = | |
52 reinterpret_cast<GETTHREADDESCRIPTION>(::GetProcAddress( | |
53 ::GetModuleHandle(L"Kernel32.dll"), "GetThreadDescription")); | |
54 | |
55 if (!get_thread_description_func) { | |
56 std::cout << "GetThreadDescription API is not available in current OS" | |
57 << std::endl; | |
58 return (FALSE); | |
59 } | |
60 | |
61 HANDLE threadSnap = INVALID_HANDLE_VALUE; | |
stanisc
2017/02/23 19:19:44
How about thread_snapshot?
chengx
2017/02/23 20:45:06
Done.
| |
62 // Take a snapshot of all running threads. | |
63 threadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); | |
64 if (threadSnap == INVALID_HANDLE_VALUE) | |
65 return (FALSE); | |
66 | |
67 THREADENTRY32 te32; | |
68 te32.dwSize = sizeof(THREADENTRY32); | |
69 | |
70 // Retrieve information about the first thread, and exit if unsuccessful. | |
71 if (!Thread32First(threadSnap, &te32)) { | |
72 std::cout << "Thread32First() call failed" << std::endl; | |
73 CloseHandle(threadSnap); | |
74 return (FALSE); | |
75 } | |
76 | |
77 // Walk the thread list of the system, and display ID and name about each | |
78 // thread associated with the process specified. | |
79 std::cout << "thread_ID thread_name" << std::endl; | |
80 std::multimap<std::wstring, DWORD> name_id_map; | |
81 do { | |
82 if (te32.th32OwnerProcessID == dwOwnerPID) { | |
stanisc
2017/02/23 19:19:44
Use chrome code naming convention for this as well
chengx
2017/02/23 20:45:06
Done.
| |
83 HANDLE threadHandle = | |
84 OpenThread(THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID); | |
85 if (threadHandle) { | |
86 PWSTR data; | |
87 HRESULT hr = get_thread_description_func(threadHandle, &data); | |
88 if (SUCCEEDED(hr)) { | |
89 std::wstring data_w(data); | |
stanisc
2017/02/23 19:19:44
Could you use a more descriptive name such as thre
chengx
2017/02/23 20:45:06
Done.
| |
90 name_id_map.insert(std::make_pair(data_w, te32.th32ThreadID)); | |
91 } else { | |
92 std::cout << "GetThreadDescription API call failed" << std::endl; | |
93 } | |
94 CloseHandle(threadHandle); | |
95 } | |
96 } | |
97 } while (Thread32Next(threadSnap, &te32)); | |
98 | |
99 // Clean up the snapshot object. | |
100 CloseHandle(threadSnap); | |
101 | |
102 // Show all thread ID/name pairs. | |
103 for (auto it = name_id_map.begin(); it != name_id_map.end(); ++it) { | |
stanisc
2017/02/23 19:19:44
Nit: you could use C++ 11 foreach loop here - for
chengx
2017/02/23 20:45:06
Done.
| |
104 std::cout << it->second << "\t"; | |
105 std::wcout << it->first << std::endl; | |
106 } | |
107 | |
108 return (TRUE); | |
109 } | |
OLD | NEW |