Solved

VB6: Sleep, DoEvent, Loop, looking for best way of...

Posted on 2011-03-03
9
1,316 Views
Last Modified: 2012-05-11
Hello

I asked this question before, since nobody respond to it,
I decide to ask it again to see if i can get a better results.

What i want to do is something simple, i am working in a VB6 project,
My goal is to execute a command code to a program, but before that
i want my project to wait for that program to be load, then apply code.

Ive been using the Sleep method, and actually is been working very well,
but i was wondering if i could do it better with DoEvent or something better.

Private Sub Form_Load()
Shell "Program-to-be-execute.exe"

Sleep 3 'wait like three seconds or so

Then after the program load up, is time to apply my code here.
I even add a second code to detect if the windows program is ready or not
'f return not ready, then another three seconds are applyed to my project.

End Sub

Thanks in advance

============
prior related question: http://www.experts-exchange.com/Q_26841079.html
aikimark -- zone advisor
0
Comment
Question by:C0ding
9 Comments
 
LVL 37

Expert Comment

by:TommySzalapski
ID: 35033552
It depends on what the other program is. If that program has a visible API that calls events (or if you wrote the other program) then it can be done.
In the general case though, if you can get a 'not ready' returned, then that's pretty good.

You could spin lock
While Not Ready
Wend

I'd at least shorten the wait time to a half second or so. Three seconds is so long (in the computer world)
0
 
LVL 76

Assisted Solution

by:GrahamSkan
GrahamSkan earned 166 total points
ID: 35034778
You could use a Timer control. It does not hog the CPU while waiting. However you would have to structure the code differently.


Private Sub Form_Load()
    Shell "Program-to-be-execute.exe"
    Timer1.Interval = 3000 '= 3 seconds
    Timer1.Enabled = True
End Sub

Sub Timer1_Timer()
    'do (or call) code that expects the shelled program to be running
    Timer1.Enabled = False
End Sub

Alternatively you can use ShellExecute. Here the code will wait until the program has opened  - or not if there are problems. You can test the result. Here is Microsoft's article:

http://support.microsoft.com/kb/170918
0
 
LVL 5

Accepted Solution

by:
BrianVSoft earned 167 total points
ID: 35035099
I think the "Sleep" function is fine, it doesn't slow down other applications..
I think you need "Sleep 3000" for 3 seconds however..
You can use the "FindWindow" function to test if the 2nd App is "up".. All you need to know is the Window/Form Title of the 2nd App  eg. "MY APP 2"
Eg.
Shell "Program-to-be-execute.exe"
Do
  Sleep 200 ' fifth of a second.
  Count = Count + 1
   If FindWindow("ThunderRT6FormDC", "MY APP 2") > 0 Then Exit Do
Loop While Count < 50 ' Give up after 10 seconds.

You need to declare..
  Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Any, ByVal lpWindowName As Any) As Long
PS. The "ThunderRT6FormDC" is the CLASS of VB6 type EXEs
0
 
LVL 14

Assisted Solution

by:VBClassicGuy
VBClassicGuy earned 167 total points
ID: 35036358
Try This:

Private Const INFINITE = -1&
Private Const PROCESS_ALL_ACCESS = &H1F0FFF
Private Const WAIT_FAILED = -1&
Private Const WAIT_TIMEOUT = &H102&

Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function WaitForInputIdle Lib "user32" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long
 
...  

Public Function ShellReady(PrgName As String, TimeOut As Long) As Long
    Dim pid As Long
    Dim lngProcess As Long
    Dim lngResult As Long
   
    pid = Shell(Chr(34) & PrgName & Chr(34), vbNormalFocus)
    lngProcess = OpenProcess(PROCESS_ALL_ACCESS, 0&, CLng(pid))
    If lngProcess <> 0 Then
        lngResult = WaitForInputIdle(lngProcess, TimeOut)
    Else
        lngResult = WAIT_FAILED
    End If

    ShellReady = lngResult
   
End Function

-----------------------------------------------

See WaitForInputIdle():
http://msdn.microsoft.com/en-us/library/ms687022(VS.85).aspx

You can pass in INFINITE, or you can give it a TimeOut value in milliseconds.

If TimeOut is INFINITE, the function does not return until the process is idle.

You can check the return value to see if it is ready (0), timed out (WAIT_TIMEOUT),
or an error occurred (WAIT_FAILED)
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 5

Expert Comment

by:BrianVSoft
ID: 35036648
This code is a 'paste' from Exp.Exchange legend "IdleMind"
It may add to your solution..
(search Exp.Exchange for "WaitForInputIdle" )
PS.. How does one extract a LINK to an Exp.Exchange question that you have browsed to??
Private Const INFINITE = -1& 
Private Const PROCESS_ALL_ACCESS = &H1F0FFF

Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Private Declare Function WaitForInputIdle Lib "user32" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long 
 
...  
    Dim FileName As String
    Dim params As String
    FileName = "C:\program.exe"
    params = "some params here"

    Dim pid As Long
    Dim lngProcess As Long
    pid = Shell(Chr(34) & FileName & Chr(34) & " " & params, vbNormalFocus)
    lngProcess = OpenProcess(PROCESS_ALL_ACCESS, 0&, CLng(pid))
    If lngProcess <> 0 Then
        WaitForInputIdle lngProcess, INFINITE
        TerminateProcess lngProcess, 0&
    End If

Open in new window

0
 

Expert Comment

by:GrateProgrammer
ID: 35037107
Try this code to see if the application is running.
'code for Form1
Private Sub cmdCheck_Click()
'check if application is running
If IsTaskRunning(sAppName) Then
MsgBox "Application '" & sAppName & "' is running!"
Else
MsgBox "Application '" & sAppName & "' is not running!"
End If

End Sub

Private Sub cmdClose_Click()
'close application
Call EndTask(sAppName)

End Sub

Private Sub cmdStart_Click()
'start an application
Shell sAppPath, vbNormalFocus

End Sub

Private Sub Form_Load()

  sAppName = "Microsoft Access"
  sAppPath = "C:\Program Files\access97\Office\MSACCESS.EXE"

End Sub


'Code for Module1


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 sAppName As String, sAppPath As String

 Public Function IsTaskRunning(sWindowName As String) As Boolean
Dim hwnd As Long, hWndOffline As Long
   On Error GoTo IsTaskRunning_Eh
'get handle of the application
'if handle is 0 the application is currently not running
hwnd = FindWindow(0&, sWindowName)
If hwnd = 0 Then

IsTaskRunning = False

Exit Function
Else

IsTaskRunning = True
End If
IsTaskRunning_Exit:

Exit Function
IsTaskRunning_Eh:
Call ShowError(sWindowName, "IsTaskRunning")
 End Function
 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
 Public Function ShowError(sText As String, sProcName As String)   'this function displays an error that occurred
   Dim sMsg As String
sMsg = "Error # " & Str(Err.Number) & " was generated by " & Err.Source & vbCrLf & Err.Description
MsgBox sMsg, vbCritical, sText & Space(1) & sProcName
Exit Function
 End Function

Open in new window

0
 
LVL 14

Expert Comment

by:VBClassicGuy
ID: 35037420
Yes, Idle_Mind is indeed a legend, and a briliant programmer. The code I presented here was taken from his post, and slightly modified. I wish there was a way in EE to, if your answer is accepted and is taken from another member's answer somewherer else, to share points with that member, even if he has not contributed to the thread. That's hard to explain, but I think you know what I mean.
0
 

Author Comment

by:C0ding
ID: 35083777

Thanks aikimark, i am kinda new here, and did not know that,
Next time i'll make sure i use that feature.

Note:
I'm sorry but i have not been able to come arround here since the day
when the site was under maintenance or something like that, cuz i did
but i keep seeing the "please try again later" or contact customer support.
and thats why i was away. SORRY.

0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now