none
WinAPI 的 GetWindowThreadProcessId 函式與 Process ID 的問題 RRS feed

  • 問題

  • 大家好,我的問題如下:

    最近有一個別人開發的 VB6 程式,要我加上單一執行個體的功能,
    在 C# 裡我是用 Mutex 物件 + Process ID 來完成,
    現在我想用在 VB6 上,但是因為 VB6 沒有跟 Mutex 有關的函式或物件,
    所以我想呼叫 Windows API 來完成。

    首先我跟用 CreateToolhelp32Snapshot 來拿到所有 Process 的 List,
    然後用 Process32First 跟 Process32Next 來取得每個 Process 的 ID 之後,
    檢查有沒有一個 Mutex 的名字是指定字串 ( 例如 MutexTest ) + Process ID 的,程式碼是這樣

       last_me_run = False
       last_me_process_id = -1
       
       '/////
       snap_shot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
       
       If snap_shot = INVALID_HANDLE_VALUE Then
          GoTo END_CHECK
       End If
       
       '/////
       process_entry_32.dwSize = Len(process_entry_32)
       rt = Process32First(snap_shot, process_entry_32)
       
       If rt = 0 Then
          Call CloseHandle(snap_shot)
          GoTo END_CHECK
       End If

       Do
          mutex_str = "Global\" & mutex_name & CStr(process_entry_32.th32ProcessID)
                
          mutex_handle = OpenMutex(SYNCHRONIZE, 0, mutex_str)
          If mutex_handle <> 0 Then
             last_me_run = True
             last_me_process_id = process_entry_32.th32ProcessID
             
             Call CloseHandle(snap_shot)
             GoTo END_CHECK
          End If
                
          '/////
          rt = Process32Next(snap_shot, process_entry_32)
          If rt = 0 Then
             Call CloseHandle(snap_shot)
             GoTo END_CHECK
          End If
       Loop

    然後如果沒找到 Mutex,則建立 Mutex,有找到 Mutex,則用 EnumWindows 來找到符合 Process ID 的視窗,

    '/////
    END_CHECK:
       If last_me_run = False Then
          current_process_id = GetCurrentProcessId()
       
          mutex_str = "Global\" & mutex_name & CStr(current_process_id)
          gMutexHandle = CreateMutex(ByVal 0&, 0, mutex_str)
       Else
          Call EnumWindows(AddressOf EnumWindowProc, last_me_process_id)
          
          End
       End If

    然後問題來了,我的 EnumWindowProc 裡,利用 GetWindowThreadProcessId
    來取得被列舉出的 Window 的 Process ID,再跟 last_me_process_id 比較相不相等來確定
    是不是屬於前一個執行個體的視窗,但是這樣列舉的結果,
    Process ID 相等的視窗竟然有 6 個!即使再用 GetParent 來過濾掉子視窗,也還是有 4 個
    相等,但是我的測試程式明明只有 1 個視窗,

    這是怎麼回事呢?有誰可以解答嗎?

    2013年11月15日 上午 12:22

所有回覆

  • VB6 有專門的屬性:

    App.PrevInstance


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2013年11月15日 下午 01:20
  • 這位仁兄回答得非常的帥氣,似乎別人都不肯好好花時間找答案,
    我看你大概也不知道 App.PrevInstance 的漏洞在哪,
    你要不要查查資料,為什麼我不用 App.PrevInstance 做 "單一執行個體" 這件事?

    2013年11月16日 上午 10:04
  • 還有,我本來就不是來問 "單一執行個體" 怎麼做這件事,
    這個問題有很多解法,我也知道幾個。

    我是來問,

    為什麼我的程式只有一個視窗,
    但是列舉所有 top-level 的視窗,
    卻有很多個視窗,符合我的 Process ID 這件事,
    你要不要再好好的看看我到底在問甚麼?

    2013年11月16日 上午 10:10
  • 我想你先把論壇提供的功能先搞清楚,免得對著簽名檔發飆到最後沒人要理你。


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    2013年11月16日 上午 10:52
  • 喔!OK,這點我該說聲抱歉。

    2013年11月16日 上午 11:24