App.Previnstance
返回的值爲True
或False
,具體取決於此實例啓動時程序的先前是否正在運行。是否可以編寫App.PrevInstance替換以提供實時信息
隨後如果先前的實例終止的App.PrevInstance
的值不改變。
是否有可能寫就能夠確定在任何時候的函數,如果以前 情況是存在?
我想,爲了這個,你需要的日期/時間開始的進程可用。 由於這些信息似乎無法從任務管理器獲得,我不知道Windows是否存儲它?
App.Previnstance
返回的值爲True
或False
,具體取決於此實例啓動時程序的先前是否正在運行。是否可以編寫App.PrevInstance替換以提供實時信息
隨後如果先前的實例終止的App.PrevInstance
的值不改變。
是否有可能寫就能夠確定在任何時候的函數,如果以前 情況是存在?
我想,爲了這個,你需要的日期/時間開始的進程可用。 由於這些信息似乎無法從任務管理器獲得,我不知道Windows是否存儲它?
你和看到的問題App.PrevInstance
可能是因爲您使用調試器(即VB 6 IDE)下運行的應用測試。但我不完全確定。它可能只執行一次檢查並緩存該值,這使得它隨着環境狀態的變化而變得「陳舊」。正如你已經注意到的,App.PrevInstance
屬性有很多限制。它的另一個常見問題是它的脆弱性。更改可執行文件的名稱是使其失敗的簡單方法。這並不總是理想的行爲。
所以這是一個替代的解決方案來代替它是一個好主意。像wqw在評論中所說的,最好的解決方案是在應用程序啓動時使用GUID創建一個互斥體名稱的互斥體。這應該是第一次成功,但隨後會失敗,因爲互斥體已被註冊(通過您的應用程序的前一個實例)。這個失敗是你的線索,你的應用程序的前一個實例正在運行。要在VB 6中執行此操作,您需要導入並調用一些Win32函數,如CreateMutex
,CloseHandle
和ReleaseMutex
。有a sample of how to use mutexes on MSDN,但這不會幫你編寫VB 6代碼,除非你已經非常熟悉Win32 API。我鏈接到一個教程,其中包含必要的代碼,在VB 6中my answer here。
如果您對App.PrevInstance
的行爲感到滿意,並且您只是希望它在每次調用它時執行檢查(而不是使用過時的緩存值),那麼您可以將其替換爲對您的調用自己的功能基本上是一樣的:遍歷所有當前正在運行的進程,並查找與可執行文件名稱匹配的內容。不幸的是,這不一定比涉及使用互斥體的「更好」解決方案少。您仍然需要導入許多Win32函數,包括EnumProcesses
。在舊的knowledge base article中有對此的說明 - 顯然,您想專注於「Windows NT」部分並忽略「Windows 95/98」的內容。
我想爲此你需要日期/時間過程開始可用。由於這些信息似乎無法從任務管理器獲得,我不知道Windows是否存儲它?
你實際上並不需要這些信息。事實上,我不確定你想要採取什麼樣的方法。這個過程何時開始並不重要,它關係到它是否正在運行。這是兩個完全不同的東西。
然而,只是爲了好玩,視窗確實事實上店此信息。任務管理器不顯示它,但Process Explorer呢。您可以通過編程方式調用GetProcessTimes
函數或querying WMI(具體而言,Win32_Process
類的CreationDate
屬性)來檢索它。
感謝wqw的評論我擡頭看CreateMutex
這正是我所需要的。
我發現下面here
'Code by Adam Verwijs
Const ERROR_ALREADY_EXISTS = 183&
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As String) As Long
Private Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Sub Form_Load()
Dim hMutex As Long
'Try to create a new Mutex
hMutex = CreateMutex(ByVal 0&, 1, App.Title)
'Did the mutex already exist?
If (Err.LastDllError = ERROR_ALREADY_EXISTS) Then
'Clean up
ReleaseMutex hMutex
CloseHandle hMutex
'More than one instance detected
MsgBox "More than one instance"
End
Else
'form load code
End If
End Sub
編輯代碼,以表明同一個非零互斥返回: 如果創建1個按鈕一個新的VB6項目,堅持下面的代碼中,使得該項目,然後運行多個實例,你會看到,所有具有相同的非零互斥體,至少在我的電腦(Windows Vista家庭基本)
Option Explicit
Const ERROR_ALREADY_EXISTS = 183&
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As String) As Long
Private Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Sub Command1_Click()
Dim hMutex As Long
'Try to create a new Mutex
hMutex = CreateMutex(ByVal 0&, 1, App.Title)
MsgBox hMutex
'Did the mutex already exist?
If (Err.LastDllError = ERROR_ALREADY_EXISTS) Then
'Clean up
ReleaseMutex hMutex
CloseHandle hMutex
'More than one instance detected
MsgBox "More than one instance"
End If
End Sub
編輯2016年4月17日請勿使用此代碼! 我已經使用它,直到最近才發現問題,但現在已經發現,它不能跨多個用戶登錄到計算機上。使用wqw的答案this other thread instead
在您的「已存在清理」中,您正在使用NULL句柄。沒有什麼可以發佈或關閉的。有趣的是,「大多數時間工作」的不正確代碼繼續傳播以誤導另一代人。根據文檔,你應該在查看LastDllError之前檢查NULL句柄返回。發生任何其他錯誤時,您也會成功。這種邏輯在多方面是錯誤的。 – Bob77
@ Bob77有一點知識是危險的!我已將它編輯出來,但保留了API文檔中的代碼。 – kjack
除了檢查'LastDllError'之外,你應該檢查'hMutex'是否爲0('NULL')。我會使用一個GUID或其他保證是唯一的互斥體ID,而不僅僅是你的應用程序的標題/名稱。這可能會與其他某個對象發生衝突。想象一下,如果你寫了一個叫做「記事本」的東西!是的,就像鮑勃說的,如果'CreateMutex'失敗了,沒有什麼可以發佈或清理的。清理代碼應該放在應用程序的終止序列中,以便在* first *實例關閉時執行。 (雖然Windows會照顧到你的。) –
最便宜的方法是使用具有GUID的'CreateMutex'作爲互斥體名稱。如果該功能失敗,則該應用程序的另一個實例已在運行。 – wqw
@wqw我聽說過一個互斥體,但從來不知道它是什麼。希望我早點知道!基於這個評論和谷歌我已經發布了一些適合我的東西 – kjack