Link to home
Start Free TrialLog in
Avatar of C0ding
C0ding

asked on

DoEvent or Loop

Hello Experts,

First of all, i would like to add this before posting my question...
I remember three years ago here on EE, Visual Basic 6 used to be visible
everytime i used to ask any question about this language, but now all i see
is something pointhing to Visual Basic Classic in which i only see things like
VB Controls, and few more, etc. but nothing mentioning Visual Basic 6...
is this okay? or i am lost? thanks.

Now here is my question,
I would like to add an event to my project instead of delay like i am doing now.
this is what i am working, i have a project that lunch, lets say notepad.exe as an example,
what my project does is rename the caption of that program window.

The only problem i see is this, the program window that my project luch, it takes some
time to luch, some times it takes 3 seconds, some other times it take even 5 seconds...
so what i have in my project is the sleep event, and i would like to change with DoEvent
instead of sleeping, cuz the DoEvent is going to wait for that process to appear and then
rename or do what ever other command i add into my project.

Now am i right about this? if so, how could i acomplish this DoEvent to my project?
the way i am doing it now is on the Load event.

Private Sub Form_Load()
Shell "C:\WINDOWS\notepad.exe"
Sleep 3

'The rest of my code goes here
End Sub

Thanks in advance




Avatar of karthika_cts
karthika_cts

Have you tried like this?

Private Sub Form_Load()
DoEvents: DoEvents: DoEvents
Shell "C:\WINDOWS\notepad.exe"
DoEvents: DoEvents: DoEvents

'The rest of my code goes here
MsgBox "Notepad"

End Sub
Avatar of C0ding

ASKER


Okay, but lets say the program being executed from my project takes 6 second,
8 seconds, 10 seconds, 2 seconds, or what ever time, this tip will help for this?

Avatar of C0ding

ASKER


All i want in my project is that if the program being executed takes what ever x-time,
my project will be willing to wait for it until the program lunch so my project send the event.
SOLUTION
Avatar of HooKooDooKu
HooKooDooKu

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Just implement and "Shell and Wait" routine. I have mine in a separate module named Lib_Shell.bas. Call the routine, and it won't return until the shelled process is complete. Here is the code:

Option Explicit

Private Const SYNCHRONIZE = &H100000
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 WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Sub ShellAndWait(ByVal cmd As String)
   Dim lPid As Long
   Dim lHnd As Long

   lPid = Shell(cmd, vbNormalFocus)
   If lPid <> 0 Then
      lHnd = OpenProcess(SYNCHRONIZE, 0, lPid)
      If lHnd <> 0 Then
         Do
            DoEvents 'keep application responsive
            Sleep 50 'keep CPU usage from ramping to 100%
         Loop Until WaitForSingleObject(lHnd, 0) <> WAIT_TIMEOUT
         CloseHandle (lHnd)
      End If
   End If
   
End Sub


And I know what you mean about finding the VB6 area. It used to be OK, with mainly VB6 questions in the VB Classic zone, but there was a long discussion on EE about where to place VBA questions. The result was they piled them into VB Classic, and I can hardly find any VB6 questions to answer any more. And since that's what I specialize in and get most of my points from, I may have to drop out of EE if the VB6 questions start getting too sparse or hard to find.
*Do you want to know when Notepad has EXITED, or simply when its main WINDOW is available?

For the former, use code like VBClassicGuy suggests.

For the latter, use code like this to determine when the main window is open and "ready":
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 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

        ' ... program is ready ...

    End If

Open in new window

That's great code for knowing when an external app is ready, Idle_Mind, thanks for posting that. One question, if the external app never opens (the path/filename was wrong or something), how would you "timeout" and get out of the routine?
See WaitForInputIdle():
http://msdn.microsoft.com/en-us/library/ms687022(VS.85).aspx

Instead of passing in INFINITE, you can give it a timeout value in milliseconds:

    "The time-out interval, in milliseconds. If dwMilliseconds 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):
Thanks for the info. Again, great routine!
Avatar of C0ding

ASKER


Thank you HooKooDooKu for all your explanation, i appreciate it.

Hi VBClassicGuy, thanks for sharing your example code,
Now let me tell you a bit of what i have, i have a simple Form1 which is my project,
Then all i wanted to do, is to call an unknown.exe program which in this case i used
notepad.exe as an example, the idea of my project is to rename the caption of that
program which i already have the code all setup for that event proposes.

Now what i really need is to replace my Sleep event for something better that can
wait for that program to be loaded which in some times my timing fail to catch his
event, so thats why i decide to change Sleep for something better like DoEvent or
something that can allow my application to do the right timing until is ready to send
his task in other words the renaming event code to that program caption.

How can i accomplish this the right way using the example you provided it here?
Ok i get the point of the Lib_Shell.bas ...then how can i call the routine?

Thanks in advance

In my post back here:
https://www.experts-exchange.com/questions/26841079/DoEvent-or-Loop.html#34961071

Insert your code to change the caption at line #20 where it says " ... program is ready ...".
Yeah, you don't want my code, as it will tel you when notepad is exited. Use Idle_mind's code to tell you when notepad is loaded and ready to accept input.
Avatar of C0ding

ASKER


Hi Idle,

Sorry to ask the same question over and over,
so if thats the code to be use and the right one...
how can i accomplish that code? i mean how do i call it?

I tried but i do get an error message:

Run-time error '76':

Path not found

I simply gave you a snippet demonstrating its use...

...we'd have to see YOUR code that attempts to use it for any chance at giving meaningful help.
Avatar of C0ding

ASKER


Ok sorry, i fix it...

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 WaitForInputIdle Lib "user32" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long
 



Private Sub Command1_Click()
Dim FileName As String
Dim params As String
FileName = "C:\WINDOWS\notepad.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
 '... program is ready ...
End If
End Sub

Open in new window


Ok, now where it says " '... program is ready ..."
there is where my code will have to be set right?

Yes...but you need to change line #14 so that "params" is either blank or contains a valid filename to open.
Avatar of C0ding

ASKER


Ok, in this case if our example is notepad, could it be "notepad.exe" ? or just "notepad"?
other thing going on with my code, is that, when i was using the sleep even in a timer...
i was doing this cuz right after my project change the caption of this program, the program
itself change back to its original name, then i got to get arround this by adding it to a timer.
If notepad is in the path variable it will be found.

What is the actual program you are trying to change?

If it changes its own caption then either it is detecting the change and putting it back or it is updating its own caption (probably using a Timer itself).
Avatar of C0ding

ASKER


Yes, but it does it only once, then after that with the help of the timer if it find that
name again the timer change it once again, and that it, after that my program simple
close, unload, end by his own. and the program name, is an emulator for n64 games.
my intentions is to add the name of each game i am playing, intead of the name of the
program, which i already did, ive been doing it for years cuz i like it this way.

IMHO, if you're changing the caption of a program that always changes it back, you shouldn't be doing it anyway. It is kinda a waste of time and CPU usage to constantly be changing a caption on a "foreign" program using a timer in your code.
Avatar of C0ding

ASKER


No, actually nop, it does it only once, after that it stays like that.
then my program close. which is no more waste of time or cpu.
Avatar of C0ding

ASKER


Thanks Idle, i be right back.
Now i will be testing this code to see what i do get.
Oh, OK. Good luck!
Avatar of C0ding

ASKER


I have two problems now...

1.) I call the execute file in this following matter:
Shell "Folder\Program.exe C:\Folder\GameDir\Game.z64", vbNormalFocus
Then with the new parameters giving by idle, i have to exclude the ", vbNormalFocus"
otherwise i get errors.

2.) Then if i lieve it like this:
FileName = "Folder\Program.exe C:\Folder\GameDir\Game.z64"
i get another error which is this one:

Run-time error '5':

Invalid procedure call or argument


The error point to this line of code:
pid = Shell(Chr(34) & FileName & Chr(34) & " " & params, vbNormalFocus)

Avatar of C0ding

ASKER


Could somebody give me the DoEvent instead of the code from idle?
I see now why of his nick name, but thanks anyway Idle_Mind
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of C0ding

ASKER


Thanks Idle, i finally got it working




Yay!  =)