如何顺序实现:A打开B,A关闭,B中进行文件复制后,B启动A?

dxqylzg 2003-10-11 10:12:51
为了实现软件的自动升级,我是这样做的:
程序A中:
Unload Me
If right(App.path, 1) <> "\" Then
Shell (App.path & "\" & "B.exe") '启动b.exe
Else
Shell (App.path & "B.exe")
End If
End '关闭A.exe
程序B中:
Dim FS
Set FS = CreateObject("Scripting.FileSystemObject")
FS.copyfile App.Path & "\A.exe", App.Path & "\A.bak" '备份A.exe
Kill App.Path & "\A.exe
FS.copyfile App.Path & "\C.exe", App.Path & "\A.exe" '用新文件c.exe替换A.exe
Kill App.Path & "\C.exe"
Shell App.Path & "\A.exe" '启动A.exe
End '关闭b.exe

以上代码程序A中可以顺利执行,程序B中会出现错误(A没有被释放不允许被覆盖),我不得其解,请高手指点谜津!
...全文
94 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
dxqylzg 2003-10-12
  • 打赏
  • 举报
回复
to rainstormmaster(rainstormmaster):
去掉 unload me 后,A关闭时提示非法操作,跳过后,还是“拒绝的权限”不能重建A
不知何故?
rainstormmaster 2003-10-12
  • 打赏
  • 举报
回复
程序A中:
'Unload Me 这句去了吗
If right(App.path, 1) <> "\" Then
Shell (App.path & "\" & "B.exe") '启动b.exe
Else
Shell (App.path & "B.exe")
End If
End '关闭A.exe


dxqylzg 2003-10-12
  • 打赏
  • 举报
回复
to seakingx(抗日统一联盟:亚龙湾) :
延时我已试过,不行。
我想这个问题应该理解为:子进程(B)如何关闭父进程(A)。望各位帮助!
dxqylzg 2003-10-12
  • 打赏
  • 举报
回复
谢谢各位的热心帮忙!

to qiqunet(暗黑神话),rainstormmaster(rainstormmaster):你们的方法我已试过,还是不行,A进程没有关闭,拒绝A。EXE的重建。
to daviddivad(你真行,居然比我还快! Scorpio):
你的方法我不会用,能给个详细的过程吗?
另:还有其它的方法实现我需要的这个功能吗?
陈年椰子 2003-10-12
  • 打赏
  • 举报
回复
我的想法: 需要用延时

在打开B后, 要有一定时间的延时 , 等待完全A关闭

不知道我的想法是否正确
dxqylzg 2003-10-12
  • 打赏
  • 举报
回复
谢谢各位的支持!问题我已解决!方法如下`:
'b程序中:
Option Explicit
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub Main()
Call EndTask(“A”)
Call Sleep(5000) '延时5秒
If Dir(App.Path & "\C.exe") <> "" Then
DoEvents
FileCopy App.Path & "\A.exe", App.Path & "\A.bak"
Kill App.Path & "\A.exe"
FileCopy App.Path & "\C.exe", App.Path & "\A.exe"
Kill App.Path & "\C.exe"
Shell App.Path & "\A.exe"
End If
End
End Sub

'B模块中:
Option Explicit

'API's Function Declarations
Private Declare Function IsWindow Lib "user32" (ByVal hwnd As Long) As Long

Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
ByVal hwnd As Long, _
ByVal nIndex As Long) As Long

Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long

Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
ByVal lpClassName As Any, _
ByVal lpWindowName As String) As Long

'API Constants
Public Const GWL_STYLE = -16
Public Const WS_DISABLED = &H8000000
Public Const WM_CANCELMODE = &H1F
Public Const WM_CLOSE = &H10

Public Function EndTask(sWindowName As String) As Integer
Dim X As Long, ReturnVal As Long, TargetHwnd As Long

'find handle of the application
TargetHwnd = FindWindow(0&, sWindowName)
If TargetHwnd = 0 Then Exit Function

If IsWindow(TargetHwnd) = False Then
GoTo EndTaskFail
Else
'close application
If Not (GetWindowLong(TargetHwnd, GWL_STYLE) And WS_DISABLED) Then
X = PostMessage(TargetHwnd, WM_CLOSE, 0, 0&)
DoEvents
End If
End If

GoTo EndTaskSucceed

EndTaskFail:
ReturnVal = False
MsgBox "EndTask: cannot terminate " & sWindowName & " task"
GoTo EndTaskEndSub

EndTaskSucceed:
ReturnVal = True

EndTaskEndSub:
EndTask% = ReturnVal
End Function

'A的程序代码:
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Private Sub Form_Unload(Cancel As Integer)
dim filename as string
filename = App.Path & "\B.exe"
ShellExecute 0, vbNullString, filename, "", "", vbNormalFocus
End
End Sub

qiqunet 2003-10-12
  • 打赏
  • 举报
回复
findwindow()好象是查找顶级窗体的,更换这一句看看?
aa = FindWindow(0, "A.exe")
换为
aa = FindWindow("ThunderRT5Main", "工程1")
qiqunet 2003-10-12
  • 打赏
  • 举报
回复
CloseHandle() 函数的局限:除非对内核对象的所有引用都已关闭,否则该对象不会实际删除

dxqylzg 2003-10-12
  • 打赏
  • 举报
回复
qiqunet(暗黑神话):
谢谢!CloseHandle() 和 SendMessage()都关闭不了A。EXE 不知何故?
再次感谢你的支持!谢谢你!祝你好运!
qiqunet 2003-10-12
  • 打赏
  • 举报
回复

我们的开发环境很有趣,呵呵
win98+vb6.0
winXP+VB5
qiqunet 2003-10-12
  • 打赏
  • 举报
回复


我用的是winXP + VB5
不知是不是同开发环境有关
但在上述环境中A用shell函数打开B,B的执行是失败的
但改成API函数ShellExecute()就成功了


你再自己调试一下吧,留意一下Findwindow()函数是否找到了A.exe,CloseHandle()函数是否将A.exe关闭了(可通过查询它们的返回值知道结果)。
我也没有什么办法了,帮忙也只能帮到这了。


dxqylzg 2003-10-12
  • 打赏
  • 举报
回复
qiqunet(暗黑神话) :
你是编译后调试的吗?
严格按照:
A的form的caption值应为“A.exe”,而B的form的caption值不能为“A.exe”
我将两个程序分别编译后,执行还是不行。我的环境是win98+vb6.0
我发现运行A后,再运行B,A竟然没有被关闭?

qiqunet 2003-10-12
  • 打赏
  • 举报
回复
没理由,我调试通过了的,看了你的回复我又将上面的程序调试过了一遍,还是没问题

'注意,A的form的caption值应为“A.exe”,而B的form的caption值不能为“A.exe”
'问题出在用shell函数时,B是A的子进程,B不能删除A,问题出在A
'我用的是两个工程,而不是两个线程
dxqylzg 2003-10-12
  • 打赏
  • 举报
回复
qiqunet(暗黑神话) :
用你的办法还是不行,不能关闭A进程。
Private Sub Form_Load()
Dim aa As Long
aa = FindWindow(0, "A.exe")
CloseHandle aa
ChDir App.Path
FileCopy "A.exe", "A.bak"
Kill "A.exe" ’-------------------出错:文件访问错误
FileCopy "c.exe", "A.exe"
End Sub

qiqunet 2003-10-12
  • 打赏
  • 举报
回复
'A的程序代码:
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Private Sub Form_Unload(Cancel As Integer)
filename = App.Path & "\B.exe"
ShellExecute 0, vbNullString, filename, "", "", vbNormalFocus
End
End Sub


'B的程序代码:
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Sub Form_Load()
Dim aa As Long
aa = FindWindow(0, "A.exe")
CloseHandle aa
ChDir App.Path
FileCopy "A.exe", "A.bak"
Kill "A.exe"
FileCopy "c.exe", "A.exe"
End Sub

'注意,A的form的caption值应为“A.exe”,而B的form的caption值不能为“A.exe”
'问题出在用shell函数时,B是A的子进程,B不能删除A
qiqunet 2003-10-11
  • 打赏
  • 举报
回复
程序B中:
Dim FS
Set FS = CreateObject("Scripting.FileSystemObject")
FS.copyfile App.Path & "\A.exe", App.Path & "\A.bak" '备份A.exe
Kill App.Path & "\A.exe
FS.copyfile App.Path & "\C.exe", App.Path & "\A.exe" '用新文件c.exe替换A.exe
Kill App.Path & "\C.exe"
Shell App.Path & "\A.exe" '启动A.exe
End '关闭b.exe
-------------------------------------------------

上面的这段代码是在那里执行的?如果是在form_load()里执行是要出问题的,因为在A还没卸载完全的情况下要覆盖A是不行的,建议使用API函数findwindow()在B里查找A,找到后再用CloseHandle()关闭A、然后用普通的VB内建函数备份、删除、重建A
daviddivad 2003-10-11
  • 打赏
  • 举报
回复

TerminateProcess(l,byval 0&)
l为原先传入的值

【VB声明】
Private Declare Function TerminateProcess Lib "kernel32" Alias "TerminateProcess" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long

【说明】
结束一个进程
在VB里使用
可以使用,但尽量不用

【返回值】
Long,非零表示成功,零表示失败。会设置GetLastError

【参数表】
hProcess ------- Long,指定要中断的一个进程的句柄

uExitCode ------ Long,进程的一个退出代码

daviddivad 2003-10-11
  • 打赏
  • 举报
回复
B启动时可带参数,例如
dim l as long
l = GetCurrentProcess()
b.exe l

在B中检查这个进程是否存在,如果存在结束该进程(A进程)
TerminateProcess
qiqunet 2003-10-11
  • 打赏
  • 举报
回复
程序没有被卸载,
Unload Me这一句放在最后最好换成End

没看清楚,原程序已有End

同意楼上 :D
rainstormmaster 2003-10-11
  • 打赏
  • 举报
回复
估计是fso对象没有被释放的问题

复制文件建议使用vb提供的FileCopy函数,即
程序B中:
FileCopy App.Path & "\A.exe", App.Path & "\A.bak" '备份A.exe
Kill App.Path & "\A.exe
FileCopyApp.Path & "\C.exe", App.Path & "\A.exe" '用新文件c.exe替换A.exe
Kill App.Path & "\C.exe"
Shell App.Path & "\A.exe" '启动A.exe
End '关闭b.exe
加载更多回复(2)

7,789

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧