2

App.Previnstance returns a value of True or False depending on whether a previous of the program is running when this instance starts.

Subsequently if the previous instance is terminated the value of App.PrevInstance does not change.

Is it possible to write a function that would be able to determine at any moment if previous instances are in existence?

I guess that for this you would need the date/time processes started to be available. As this information does not seem to be available from the task manager I wonder if windows stores it at all?

4

2 回答 2

2

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

因此,用替代解决方案替换它是一个好主意。就像 wqw 在评论中所说,最好的解决方案是在应用程序启动时使用 GUID 作为互斥锁的名称创建互斥锁。这应该第一次成功,但随后会失败,因为互斥锁已经注册(通过您的应用程序的先前实例)。该失败是您的应用程序的先前实例正在运行的线索。要在 VB 6 中执行此操作,您需要导入和调用一些 Win32 函数,例如CreateMutexCloseHandleReleaseMutex. 在 MSDN 上有一个如何使用互斥锁的示例,但这对您编写 VB 6 代码没有多大帮助,除非您已经相当熟悉 Win32 API。我已经链接到一个教程,其中包含 VB 6 中的必要代码我的回答在这里

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

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

您实际上并不需要这些信息。实际上,我不确定您想到的哪种方法需要它。进程何时启动并不重要,重要的是它当前是否正在运行。这是两个完全不同的东西。

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

于 2013-05-25T13:14:38.647 回答
2

感谢 wqw 的评论,我查了一下CreateMutex,这正是我所需要的。

我在这里找到了下面的代码

'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 不要使用此代码!!!直到最近我一直使用它而没有注意到问题,但现在发现它不适用于在一台计算机上登录的多个用户。改用 wqw 在这个其他线程上的答案

于 2013-05-25T14:04:18.727 回答