How can i know Shell function execution is completed...

To,
Experts
When i use "Shell" function as i mention below.
e.g.
Dim RetVal
RetVal =
Shell("C:\WINDOWS\CALC.EXE",1)  
Msgbox "Execution is completed"

I put message box below the shell function, i mean i want to display that message only when the execution is totally completed.Currently without execution is totally completed it shows this messagebox.

Please send me your reply as soon as possible.

Thanks,
buddy
buddypAsked:
Who is Participating?
 
mcriderConnect With a Mentor Commented:
You can use the following code to see if program you started is running, Put it in a module:

Global ProgHandle As Long

Declare Function GetExitCodeProcess Lib "kernel32" _
    (ByVal hProcess As Long, lpExitCode As Long) As Long

Declare Function OpenProcess Lib "kernel32" _
    (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
    ByVal dwProcessId As Long) As Long

Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long

Declare Function SysSetFocus Lib "user32" Alias "SetFocus" _
    (ByVal hwnd As Long) As Long
Function IsActive(hprog) As Long
    Dim hProc, RetVal As Long
    hProc = OpenProcess(0, False, hprog)
    If hProc <> 0 Then GetExitCodeProcess hProc, RetVal
    IsActive = (RetVal = 259)
    CloseHandle hProc
End Function

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

When you shell the program, do it like this, (remember ProgHandle is a global definition):

ProgHandle = Shell("notepad.exe", vbNormalFocus)

You can then make the following call to see if the shelled process is still running:

    If IsActive(ProgHandle) Then
        'THE SHELLED PROGRAM IS ACTIVE
        'DO WHATEVER YOUR GOING TO DO
    Else
        'THE SHELLED PROGRAM IS NOT ACTIVE
        'DO WHATEVER YOUR GOING TO DO
    End If

Cheers!
0
 
Erick37Commented:
"Start another program from your application and wait for it to end before processing your next instruction."

http://www.thescarms.com/vbasic/Wait.htm
0
 
buddypAuthor Commented:
To,
mcrider
I have one question.I want to put message box "Execution completed".It is then only pop up when shell function is totally completes its execution.
For that where should i put my message box in your below mention code.
I mean i have to put message box after "End if" statement.Or where i put it is right ?

Please tell me as soon as possible.
This is your code :

    If IsActive(ProgHandle) Then
        'THE SHELLED PROGRAM IS ACTIVE
        'DO WHATEVER YOUR GOING TO DO
    Else
        'THE SHELLED PROGRAM IS NOT ACTIVE
        'DO WHATEVER YOUR GOING TO DO
       
--->       MsgBox "Execution completed"
    End If
--->


To,
erick37
You give me site address but on that site the code is not properly executed.It gives error.So check it out and tell me.

Thanks,
buddy
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
mcriderCommented:
You can do it like this:

'---------------------------------------
   Do
      If IsActive(ProgHandle) Then
         DoEvents
      Else
         MsgBox "Execution completed"
         Exit Do
      End If
   Loop
'---------------------------------------

Remember, your program will still be active, and events like button clicks will still be processed...


HERES ANOTHER WAT TO WAIT FOR A SHELLED PROCESS.
--------------------------------------------------



If you want your program to "Freeze" until the shelled program is completed, you can add this code to your program:

'-----------------------------------------------------------
Public Const INFINITE = -1&

Private Declare Function OpenProcess Lib "kernel32" (ByVal _
    dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
    ByVal dwProcessID As Long) As Long

   Private Type STARTUPINFO
      cb As Long
      lpReserved As String
      lpDesktop As String
      lpTitle As String
      dwX As Long
      dwY As Long
      dwXSize As Long
      dwYSize As Long
      dwXCountChars As Long
      dwYCountChars As Long
      dwFillAttribute As Long
      dwFlags As Long
      wShowWindow As Integer
      cbReserved2 As Integer
      lpReserved2 As Long
      hStdInput As Long
      hStdOutput As Long
      hStdError As Long
   End Type

   Private Type PROCESS_INFORMATION
      hProcess As Long
      hThread As Long
      dwProcessID As Long
      dwThreadID As Long
   End Type

   Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
      hHandle As Long, ByVal dwMilliseconds As Long) As Long

   Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
      lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _
      lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
      ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
      ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, _
      lpStartupInfo As STARTUPINFO, lpProcessInformation As _
      PROCESS_INFORMATION) As Long

   Private Declare Function CloseHandle Lib "kernel32" _
      (ByVal hObject As Long) As Long

   Private Declare Function GetExitCodeProcess Lib "kernel32" _
      (ByVal hProcess As Long, lpExitCode As Long) As Long

   Private Const NORMAL_PRIORITY_CLASS = &H20&
 
  Public Function ExecCmd(cmdline$)
      Dim proc As PROCESS_INFORMATION
      Dim start As STARTUPINFO

      ' Initialize the STARTUPINFO structure:
      start.cb = Len(start)

      ' Start the shelled application:
      ret& = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, _
         NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)


      ' Wait for the shelled application to finish:
         ret& = WaitForSingleObject(proc.hProcess, INFINITE)
         Call GetExitCodeProcess(proc.hProcess, ret&)
         Call CloseHandle(proc.hThread)
         Call CloseHandle(proc.hProcess)
         ExecCmd = ret&
    End Function
'-----------------------------------------------------------

You can then use the following anywhere in your ProgA program:

   ExecCmd("C:\WINDOWS\CALC.EXE")

instead of:

   Shell("C:\WINDOWS\CALC.EXE",1)


Cheers!



0
 
Erick37Commented:
From
www.thescarms.com

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Copy the following code to a .bas module:

Public Const SYNCHRONIZE = &H100000
Public Const INFINITE = &HFFFF
Public Const WAIT_OBJECT_0 = 0
Public Const WAIT_TIMEOUT = &H102

Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
           ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _
           ByVal dwMilliseconds As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


'Form Code: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Dim lPid As Long
Dim lHnd As Long
Dim lRet As Long

lPid = Shell("calc.exe", vbNormalFocus)
If lPid <> 0 Then
    'Get a handle to the shelled process.
    lHnd = OpenProcess(SYNCHRONIZE, 0, lPid)
    'If successful, wait for the application to end and close the handle.
    If lHnd <> 0 Then
        lRet = WaitForSingleObject(lHnd, INFINITE)
        Call CloseHandle(lHnd)
    End If
    MsgBox "Just terminated.", vbInformation, "Shelled Application"
End If
0
 
Erick37Commented:
Public Const INFINITE = (-1)
0
 
buddypAuthor Commented:
To,
mcrider
You are very close to my requirement.But i have still one question.
When i use your code in new vb form & module then it is working fine.

But when i use it in my vb project then gives me compile error like: "variable not define on "ret&".

When i define that variable as:
Dim ret&

And run my program then it passes value of "ret& = 0" in below mention line.

ExecCmd = ret&

While value of "ret& = 1" when i run your program in separate vb project.

So i want to make sure that is it anyhow problematic to my program ?
And also what is value "0" indicates and what is value "1" indicates ?

Thanks,
buddy
0
 
mcriderCommented:
You must have OPTION EXPLICIT in your program...  Replace the ExecCmd function I gave you with this one:


Cheers!


Public Function ExecCmd(cmdline As String)
    Dim ret As Long
    Dim proc As PROCESS_INFORMATION
    Dim start As STARTUPINFO

    ' Initialize the STARTUPINFO structure:
    start.cb = Len(start)

    ' Start the shelled application:
    ret = CreateProcessA(0&, cmdline, 0&, 0&, 1&, _
       NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)

    ' Wait for the shelled application to finish:
       ret = WaitForSingleObject(proc.hProcess, INFINITE)
       Call GetExitCodeProcess(proc.hProcess, ret)
       Call CloseHandle(proc.hThread)
       Call CloseHandle(proc.hProcess)
       ExecCmd = ret
  End Function

0
 
buddypAuthor Commented:
To,
mcrider
I would like to know in which case it assign value = 0 and in which case it assign value = 1.

That's it.So please clear my doubt.

Thanks for your co-operation.

Thanks,
buddy
0
 
mcriderCommented:
Ret is going to be the notation of the DOS Return Code... Please see:

HOWTO: 32-Bit App Can Determine When a Shelled Process Ends
http://support.microsoft.com/support/kb/articles/Q129/7/96.asp 
 

Cheers!
0
 
bhavesh55Commented:
To,
mcrider
That's fine.But my doubt is when i use your this function in my project then value of ret in your last line is
"0" and when i use it in separate vb project then it is "1".

I would like to know in which case  value is "1" and in which case value is "0".

Except that everything is fine.

I am eagerly waiting for your reply.

Thanks,
buddy
0
 
mcriderCommented:
I'm not sure what you're talking about... You program stops until the shell finishes executing, right?

Cheers!
0
 
buddypAuthor Commented:
No man.Everthing is working fine.

But in last line it passes value of ret=1.Right.

What it means ?Suppose it passes ret =0 then what it means ?Thats what i want to know.

Thanks,
buddy
0
 
Erick37Commented:
You do not use the return code anyway if you call:

Call ExecCmd("C:\WINDOWS\CALC.EXE")
0
 
mcriderCommented:
It really doesn't mean anything...  It's just the return code from WaitForSingleObject API call.

See the following documentation:

http://msdn.microsoft.com/library/psdk/winbase/synchro_4ldg.htm 

Cheers!
0
 
buddypAuthor Commented:
To,
mcrider
how can i give you point ?

Here that box is not available.

Thanks for your time and help.

Thanks,
buddy
0
 
mcriderCommented:
If you want to, you can open a new question with the title "FOR MCRIDER ONLY" and I will answer it...

Cheers!
0
All Courses

From novice to tech pro — start learning today.