【请教大侠】如何让程序不重复运行?
vb吧
全部回复
仅看楼主
level 7
peeppp 楼主
If App.PrevInstance = True Then end '防止程序重复运行
这句是可以防止程序多次运行的
但我现在同时想加上:如果程序在进程中,双击这个EXE时,程序显示出来(程序默认是隐藏的me.hide),还不会再运行一个进程,应该怎么写?使用 me.show后程序是显示了,但同时进程就多一个
If App.PrevInstance = True Then Me.Show
2020年09月28日 07点09分 1
level 13
App.PrevInstance独开有缺点,exe复制一份到其他目录就可以打开运行多个,解决方案:
1.CreateMutex、CreateSemaphore等创建互斥体实现单开,然后EnumWindow枚举窗口,比较类名或窗口名,确认是该窗口的则显示(还可以用SetProp等函数)
2.CreateFileMapping文件映射实现(第一次运行时写入窗体句柄,第二次运行时读取句柄显示窗口),这个推荐
当然还有很多方法,这个得你自己去尝试
2020年09月28日 08点09分 2
不用考虑多复制EXE造成的问题,只需要解决同一个EXE不重复运行,双击只显示窗体的功能就好了
2020年09月28日 09点09分
level 6
不可用App.PrevInstance,用窗口,给你主窗口设置一个特殊caption作为flag,运行后查找这个窗口,找到了就showWindow该窗口,再退出自己。
2020年09月28日 08点09分 4
麻烦给个代码,谢谢,不知道怎么搞
2020年09月28日 09点09分
@peeppp 把标题设成固定,findwindow该标题,然后showwindow,如果标题不固定,就加个frame控件,设置一个标题,查找这个frame,如果要充分保证单开就创建全局唯一对象,像mutex什么的。
2020年09月28日 10点09分
@zzmzzff 能麻烦直接给个代码吗?不明白
2020年09月29日 08点09分
吧务
level 13
最简单的方法是:
2020年09月28日 16点09分 7
程序一进入就去检查某文件夹中是否有【????.TXT】文件,如果没有,就是首次运行【本.EXE】程序,并自动建立【????.TXT】文件;如果有【????.TXT】文件,就说明已经有【本.EXE】程序在运行了。
2020年09月28日 16点09分
非正常退出【本.EXE】程序,就会在某文件夹中残留【????.TXT】文件。可以另外编制一个程序【解.EXE】来专门删除这个文件,以便【本.EXE】程序正常首次运行。
2020年09月28日 16点09分
【本.EXE】程序正常退出时,要删除【????.TXT】文件。
2020年09月28日 16点09分
这样还不如用App.PrevInstance呢,而且也没回答楼主的问题:如果已经有一个本程序的进程在运行,如何切换到这个进程的窗口
2020年09月29日 01点09分
level 12
form_load事件在c盘某文件里记录自己的窗口句柄。
程序启动,窗口没创建之前,判断这个窗口句柄是否有效,如果有效,显示,退出。如果无效,创建窗口,继续向文件写入当前窗口句柄,这样不管程序是否正常退出都没问题,
不过有很小的可能,在你程序退出后win为其他窗口分配与文件内相同的句柄,这样会导致你的程序打不开。文可能性非常小
2020年09月29日 05点09分 8
能麻烦给个具体代码吗?谢谢
2020年09月29日 08点09分
许多程序没有窗口怎么去判断【窗口的句柄】。
2020年09月29日 16点09分
@Luosen56 一般情况下VB6 99%的程序都带窗口,真要是没窗口直接二楼的互诉体,就没这种苦恼。不过细看了一下没搞懂楼主要求,是要结束前面的进程,还是要让前面的进程显示然后结束本次启动进程
2020年09月29日 17点09分
@👨🏿‍🦱 按我原来的想法是,保留原来的进程,自动结束后面的进程(因为结束了之前的进程,窗体上显示的内容会变成默认的值,如果能保留原来的进程,值不会变),现在找到的代码,如下面这层楼,是发现原来的进程,直接干掉,保留了新的进程,虽然跟我的想法有出入,但好歹算是可用。
2020年09月30日 03点09分
level 7
peeppp 楼主
找到了一个代码
https://zhidao.baidu.com/question/25789597.html
就是用来检测进程的,有就强退那个进程,测试可以用,但感觉有点大材小用了,我感觉应该有更简洁的代码可以实现我的效果吧
2020年09月29日 08点09分 9
检测进程是正确的,只是比较麻烦一点。
2020年09月29日 16点09分
level 12
新建一个标准模块,代码如下
Option Explicit
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long
Private Declare Function SendMessageA Lib "user32" (ByVal Handle As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function IsWindow Lib "user32" (ByVal Handle As Long) As Boolean
Private Declare Sub SetForegroundWindow Lib "user32" (ByVal Handle As Long)
Public Function IniRead(ByVal IniPath As String, ByVal Field As String, ByVal key As String, Optional ByVal DefaultKeyValue As Variant) As String
Dim s As String * 255, s2 As String * 255
GetPrivateProfileString Field, key, DefaultKeyValue, s, 255, IniPath
If s = s2 Then
IniRead = CStr(DefaultKeyValue)
Else
IniRead = Trim(Replace(s, Chr(0), ""))
End If
End Function
Public Function IniWrite(IniPath As String, Field As String, key As String, KeyValue As String) As String
WritePrivateProfileString Field, key, KeyValue, IniPath
End Function
Public Sub Main()
Dim Hwnd As Long
Hwnd = IniRead("d:\vbMainConfig.ini", "hwnd", "hwnd", "0")
If IsWindow(Hwnd) Then
SendMessageA Hwnd, 274, 61728, 0
SetForegroundWindow Hwnd
Else
Form1.Show
End If
End Sub
程序主窗体的 load事件
Private Sub Form_Load()
IniWrite "d:\vbMainConfig.ini", "Hwnd", "Hwnd", CStr(Me.Hwnd)
End Sub
最后,工程-属性-通用-启动对象 设为 Sub Main 编译后运行看看效果
2020年09月30日 04点09分 10
谢谢热情回复,能简单解释下这个原理吗?
2020年10月09日 09点10分
@peeppp 原理在8楼,这是个逻辑问题。程序启动创建窗口时把句柄保存在某文件里(d:/vbmainconfig.ini),每次点开程序都先读取里面的句柄判断之前打开的程序是否还存在
2020年10月09日 10点10分
@peeppp 如果存在就让它现身然后自己默默退出。如果句柄无效说明之前打开的已经不存在了,那就自己现身,然后继续把句柄保存到文件里,让下一次点开程序时判断
2020年10月09日 10点10分
@peeppp 这帖吧太夸张,这回复也能删,算了
2020年10月09日 10点10分
吧务
level 4
句柄 hook钩子---了解一下。
2020年10月09日 10点10分 11
level 13
'放一个Label控件,工程名为工程1,Form1的LinkTopic为Form1,LinkMode为1
方法1:
Option Explicit
Private Sub Form_Initialize()
If App.PrevInstance Then
Call DDESendMessage("Activate")
End
End If
End Sub
'DDE发送消息
Private Sub DDESendMessage(ByVal strMsg As String)
label1.LinkTopic = "工程1|Form1"
label1.LinkMode = vbLinkManual
Call label1.LinkExecute(strMsg)
End Sub
Private Sub Form_LinkExecute(CmdStr As String, Cancel As Integer)
Me.WindowState = 0
Cancel = False
End Sub
方法2:
Option Explicit
Private Sub Form_Initialize()
If App.PrevInstance Then
Label1.LinkTopic = "工程1|Form1"
Label1.LinkMode = vbLinkManual
End
End If
End Sub
Private Sub Form_LinkOpen(Cancel As Integer)
Me.WindowState = 0
End Sub
以前写的DDE激活,也能满足你的要求
2020年10月10日 09点10分 12
谢谢热情回复,顺便请教下,这个原理是什么?
2020年10月11日 08点10分
1