是否可以编写App.PrevInstance替换来提供实时信息

时间:2013-05-25 11:18:44

标签: vb6

App.Previnstance返回值TrueFalse,具体取决于此实例启动时程序的前一个程序是否正在运行。

如果先前的实例终止,App.PrevInstance的值不会改变。

是否可以编写一个能够在任何时刻确定之前的函数 实例存在?

我想为此您需要开始提供日期/时间流程。 由于这些信息似乎无法从任务管理器获得,我想知道Windows是否存储它?

2 个答案:

答案 0 :(得分:2)

您使用App.PrevInstance 看到的问题可能是因为您正在使用在调试器下运行的应用程序(即VB 6 IDE)进行测试。但我不完全确定。它可能只执行一次检查并缓存该值,这使得它随着环境状态的变化而变得“陈旧”。正如您已经注意到的那样,App.PrevInstance属性有很多限制。它的另一个常见问题是它的脆弱性。更改可执行文件的名称是一种使其失败的简单方法。这并不总是理想的行为。

因此,用替代解决方案替换它是个好主意。就像wqw在评论中所说,最好的解决方案是在应用程序启动时使用GUID为互斥锁的名称创建一个互斥锁。这应该是第一次成功,但随后会失败,因为互斥锁已经注册(由您的应用程序的先前实例)。该故障是您的应用程序的先前实例正在运行的线索。要在VB 6中执行此操作,您需要导入并调用一些Win32函数,例如CreateMutexCloseHandleReleaseMutex。有a sample of how to use mutexes on MSDN,但除非你已经非常熟悉Win32 API,否则这对编写VB 6代码没有多大帮助。我已经链接到一个教程,其中包含my answer here中VB 6中的必要代码。

如果您对App.PrevInstance的行为感到满意,并且您只是希望每次调用它时执行检查(而不是使用过时的缓存值),那么您只需将其替换为调用您自己的函数,该函数基本上执行相同的操作:遍历所有当前正在运行的进程,并查找与可执行文件名称的匹配项。不幸的是,这不一定比涉及使用互斥锁的“更好”解决方案更少。您仍然需要导入许多Win32函数,包括EnumProcesses。旧版knowledge base article中有相关说明 - 显然你想专注于“Windows NT”部分并忽略“Windows 95/98”的内容。

  

我想为此您需要开始提供日期/时间流程。由于这些信息似乎无法从任务管理器获得,我想知道Windows是否存储它?

您实际上并不需要此信息。事实上,我不确定你想要的是什么方法。流程启动时无关紧要,无论当前是否正在运行。这是完全不同的两件事。

但是,只是为了好玩,Windows 实际上存储了这些信息。任务管理器不会显示它,但Process Explorer会显示它。您可以通过调用GetProcessTimes函数或querying WMI(特别是Win32_Process类的CreationDate属性)以编程方式检索它。

答案 1 :(得分:2)

感谢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 home basic)

   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-04-17请勿使用此代码! 直到最近我才使用它而没有注意到问题,但现在发现它不能在多个用户登录计算机上工作。在this other thread instead

上使用wqw的答案