2013-03-24 27 views
6

Bạn có thể giúp tôi tìm ID chuỗi chính (chỉ) của quy trình ID đã cho không?Làm cách nào để lấy ID luồng chính của một quy trình (được biết bằng ID của nó)?

Ngữ cảnh công việc: Quy trình đang chạy có (tại thời điểm này) không có cửa sổ nhưng một (một số) luồng.

Muốn: Đăng chỉ WM_QUIT tại chỉ chuỗi chính.

Không được mong muốn: Sử dụng TerminateProcess hoặc đăng WM_QUIT tại các tiểu trình không chính.

Trả lời

6
#ifndef MAKEULONGLONG 
#define MAKEULONGLONG(ldw, hdw) ((ULONGLONG(hdw) << 32) | ((ldw) & 0xFFFFFFFF)) 
#endif 

#ifndef MAXULONGLONG 
#define MAXULONGLONG ((ULONGLONG)~((ULONGLONG)0)) 
#endif 

bool CloseProcessMainThread(DWORD dwProcID) 
{ 
    DWORD dwMainThreadID = 0; 
    ULONGLONG ullMinCreateTime = MAXULONGLONG; 

    HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 
    if (hThreadSnap != INVALID_HANDLE_VALUE) { 
    THREADENTRY32 th32; 
    th32.dwSize = sizeof(THREADENTRY32); 
    BOOL bOK = TRUE; 
    for (bOK = Thread32First(hThreadSnap, &th32); bOK; 
     bOK = Thread32Next(hThreadSnap, &th32)) { 
     if (th32.th32OwnerProcessID == dwProcID) { 
     HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, 
            TRUE, th32.th32ThreadID); 
     if (hThread) { 
      FILETIME afTimes[4] = {0}; 
      if (GetThreadTimes(hThread, 
          &afTimes[0], &afTimes[1], &afTimes[2], &afTimes[3])) { 
      ULONGLONG ullTest = MAKEULONGLONG(afTimes[0].dwLowDateTime, 
               afTimes[0].dwHighDateTime); 
      if (ullTest && ullTest < ullMinCreateTime) { 
       ullMinCreateTime = ullTest; 
       dwMainThreadID = th32.th32ThreadID; // let it be main... :) 
      } 
      } 
      CloseHandle(hThread); 
     } 
     } 
    } 
#ifndef UNDER_CE 
    CloseHandle(hThreadSnap); 
#else 
    CloseToolhelp32Snapshot(hThreadSnap); 
#endif 
    } 

    if (dwMainThreadID) { 
    PostThreadMessage(dwMainThreadID, WM_QUIT, 0, 0); // close your eyes... 
    } 

    return (0 != dwMainThreadID); 
} 
+1

Có vẻ tốt, cảm ơn bạn! –

+6

Câu trả lời này sẽ tốt hơn nếu nó có một số giải thích về mã và cách hoạt động của mã. Đặc biệt, làm cách nào để bạn xác định chủ đề "chính" là của một quy trình cụ thể trong trường hợp quá trình đó có nhiều luồng? Có vẻ như tôi đang dựa vào thời gian tạo chuỗi. Đó không nhất thiết là một phương pháp phỏng đoán đáng tin cậy; điều quan trọng là chỉ ra rằng mọi người có thể xem xét cẩn thận những lợi thế và bất lợi của phương pháp này. Câu trả lời có chứa * chỉ * mã không phải là câu trả lời. –

2

Bạn không thể đăng tin nhắn cho một chuỗi cụ thể. Thư được đặt trong hàng đợi và chỉ được xử lý từ chuỗi chính.

Nếu bạn muốn đóng cửa sổ trình có giao diện người dùng, hãy xem using sendmessage to send wm_close to another process

+0

Cảm ơn bạn đã trả lời của bạn, tôi sẽ đánh dấu câu trả lời của bạn là có ích. –

+3

Trên thực tế, có thể có nhiều hàng đợi tin nhắn, mỗi hàng được liên kết với một chuỗi khác nhau và nếu có, bạn có thể sử dụng PostThreadMessage để gửi thư đến một chuỗi cụ thể. –

+0

@Harry: thật thú vị khi biết! Trường hợp sử dụng thực tế là gì, khi có nhiều hàng đợi? – alex

4

Một cách đơn giản hơn nhiều và chắc chắn hơn để có được những thread id của các chủ đề chính là để cho các chủ đề chính ghi của nó id thread riêng sử dụng ::GetCurrentThreadId() vào một biến toàn cầu chia sẻ, có lẽ trong WinMain của bạn hoặc một nơi nào vào lúc bắt đầu rất của 'chủ đề chính' của bạn:

MainThreadId_G = ::GetCurrentThreadId(); 

sau đó trong chủ đề khác của bạn, bạn có thể gọi: ::PostThreadMessage(MainThreadId_G, WM_QUIT, returncode, 0);

+0

Tôi chắc chắn thích câu trả lời này. Ngắn gọn, cung cấp một câu trả lời hoàn chỉnh, và một lời giải thích tốt. Tất nhiên, có thể truyền ID chủ đề chính dưới dạng tham số cho chuỗi công việc khi chúng được tạo, thay vì sử dụng biến toàn cầu. –

1

Tôi đã kiểm tra cách này được xử lý trong MFC, và có vẻ như UI thread được xác định từ constructor:

C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc\appcore.cpp: 

CWinApp::CWinApp(LPCTSTR lpszAppName) 
{ 
... 

    m_nThreadID = ::GetCurrentThreadId(); 

Và sử dụng MFC gọi AfxGetApp()->m_nThreadID bạn có thể tìm ra thread UI ID.

Tuy nhiên - cách tiếp cận này không hoạt động nếu .dll được tải không từ chủ đề chính - sau đó thậm chí cách tiếp cận của MFC sẽ không hoạt động - AfxGetApp()->m_nThreadID sẽ trả về một thứ khác không phải là chuỗi chính.

Nhưng thông thường .dll của bạn được tải từ chuỗi chính, nhưng .dll của bạn không được bật mfc cần thiết. Tôi có thể khuyên bạn nên tiếp cận như sau:

class GetMainThread 
{ 
public: 
    GetMainThread() 
    { 
     m_nThreadID = ::GetCurrentThreadId(); 
    } 

    DWORD m_nThreadID; 
}getMainThread; 


DWORD getUIThread() 
{ 
    DWORD id = 0; 

    if(AfxGetApp() != NULL) 
     id = AfxGetApp()->m_nThreadID; 
    else 
     id = getMainThread.m_nThreadID; 

    return id; 
} //getUIThread 

Nếu .dll được tải bởi chuỗi giao diện người dùng chính, bạn sẽ nhận được id chủ đề chính xác từ cuộc gọi hàm (GetMainThread class).

Remove AfxGetApp() cuộc gọi nếu bạn không cần đến chúng (Trong ứng dụng của tôi, tôi cần những)

Các vấn đề liên quan