Results 1 to 20 of 20

Thread: ShellExecute and wait

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    ShellExecute and wait

    Hi,

    I'm wondering if it's possible to make the "ShellExecute" command to wait until it finishes it's process?
    This is what I want to do: I have a file that I would like to open in it's associated application (for example like a .doc file to be opened in Word). For that I use the ShellExecute function. After the document is opened, a script that I have should be run on the document. How could all that be accomplished with ShellExecute? I just have to wait for ShellExecute to fully open the document and the rest I know how to do (call the script etc.). Or maybe there is an alternative to open the file, without using ShellExecute?

    Thanks in advance.

  2. #2
    Fanatic Member schoolbusdriver's Avatar
    Join Date
    Jan 2006
    Location
    O'er yonder
    Posts
    1,020

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    Re: ShellExecute and wait

    Thx a lot, but still the script, that should be run when the file is opened, doesn't catch up. The script uses menu functions that are in the program (like for example: File -> Print...) and therefore I think the program must wait until the file is completely opened. The link you provided seems to just wait until it recognizes the process, but after that it continues executing my script and the script then generates an error because the application isn't fully opened. So probably what I have to do is to wait for the window to open (With FindWindow API function). But now I wonder, must I supply the exact name of the window that opens, or is there some other API function that can just find a window that is opened with that application?

    Thanks in advance.

  4. #4
    Fanatic Member schoolbusdriver's Avatar
    Join Date
    Jan 2006
    Location
    O'er yonder
    Posts
    1,020

    Re: ShellExecute and wait

    That could be slightly tricky. I doubt FindWindow would be of any use, as the problem lies with the loading time of the file the script is processing. Do you have full control over when to run the script ? ie WRT vbaccelerator's code, could you do something like "ShellAndWaitForTermination", -> "Sleep(n)" (to make sure the document is loaded), -> "Script". ?

    Also does the script auto close the app when it's done ?

    EDIT:- As regards FindWindow, even if the app displays the document name in the caption, your script may fail depending on whether the app changes its caption before or after the doc is read from the HDD.
    Last edited by schoolbusdriver; Aug 1st, 2006 at 09:04 AM.

  5. #5

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    Re: ShellExecute and wait

    Hi,

    Thanks for your reply. I can start the script whenever I want and the script doesn't close the application after it's done.
    The problem is that on some machines the program might run faster or slower, so waiting a specified time would maybe not be enough on some other machine, don't you think?

    This is indeed tricky...I also can't have this application as a reference to my project (like for example Word) so that I could use it as an object in the code What do you think is the best thing to do?

  6. #6

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    Re: ShellExecute and wait

    I tried with the FindWindow function and it works. But the problem now might be if the user has several applications open, so FindWindow maybe gives me the wrong one. Any way to find the handle of the latest opened application?

    Thanks in advance.

  7. #7

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    Re: ShellExecute and wait

    I take it back. It doesn't work
    I had a MsgBox that was run earlier than I thought, and that delayed the program and made it work. So even if I use the FindWindow API, it finds the window before it has even loaded :S

    I know thought why the script can't run. It complains about the GetObject method that it uses:

    Dim app
    Set app = GetObject(, "MGCPCB.Application")
    Call Execute_GerberOut

    Is it somehow possible to loop as long as GetObject doesn't work?
    Thanks in advance!

    Btw, it gives me the following error:
    Run-time error 429: Active-X component can't create object
    Last edited by Striver; Aug 1st, 2006 at 10:31 AM.

  8. #8
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: ShellExecute and wait

    Maybe you want to look into using the WaitForInputIdle API function.

  9. #9

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    Re: ShellExecute and wait

    Hehe, the interesting thing is that I just came across it
    But I only found how to use it in .NET and Visual Basic 2005, while I'm developing in VB 6. Also, assuming now that I somehow use WaitForInputIdle(). Then I would have to find the handle for the window as before right? And use that handle for the WaitForInputIdle function? Or can I get the handle from ShellExecute?
    Could you also maybe provide some code example or a link on how to use WaitForInputIdle?

    Thanks.

  10. #10

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    Re: ShellExecute and wait

    This is how I use WaitForInputIdle() now:

    i = FindWindow(vbNullString, "Expedition PCB")
    Do While i = 0
    i = FindWindow(vbNullString, "Expedition PCB")
    DoEvents
    Loop
    Call WaitForInputIdle(i, INFINITE)
    Module3.Execute

    Module3.Execute is the code that is run in the script (I copied the script code to a module). It once again complains about the GetObject line and it doesn't wait for the window to load :S

    [Edit]: Now I changed the WaitForInputIdle line to:

    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, ShellExecute(0, "open", sFile, "", "", 1))
    Call WaitForInputIdle(hProcess, INFINITE)

    It still doesn't wait
    Last edited by Striver; Aug 1st, 2006 at 11:07 AM.

  11. #11
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: ShellExecute and wait

    The second call looks more correct. WaitForInputIdle requires the handle of the process not a handle to a window. An application can however be "input idle" before it's main window has fully loaded. This could for example happen if it's waiting for a timer event or something simular.

  12. #12

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    Re: ShellExecute and wait

    So, what is the best thing to do? To have a constant delay? I tried to set a delay for a minute or so (that's approximately how much it takes for it to load) and it worked fine then (the other script could run because the window was fully loaded). But as I mentioned before, on some other machines that is very unsecure.

    Any other ideas or suggestions? I was wondering if somehow one could loop until the GetObject function returns an object? The script doesn't start because it crashes on that step (when it tries to get the application). The problem now is that GetOjbect immediately generates an error, and it does so even if I have an "On Error..." statement after GetObject, so I somehow can't take care of that error...

  13. #13
    I'm about to be a PowerPoster! Joacim Andersson's Avatar
    Join Date
    Jan 1999
    Location
    Sweden
    Posts
    14,649

    Re: ShellExecute and wait

    Ehh... Of course an error is raised if you have an On Error statement after the line that causes the error. If there is no object available GetObject raises a trappable error in which case you can use CreateObject instead. Which means that you don't have to launch the application first.

  14. #14

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    Re: ShellExecute and wait

    Aha ok. I thought that one had to catch error with "On Error.." after the statements that cause them. How could I catch the GetObject error and create a new application instead?
    Thanks in advance.

  15. #15
    PowerPoster
    Join Date
    May 2006
    Posts
    2,988

    Re: ShellExecute and wait

    have you tried enum windows and then a timer to check if it is still open?

  16. #16

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    Re: ShellExecute and wait

    Hmm no...what's that?
    I've introduced a delay before (for a minute or so) and then it worked perfectly. But I don't know what you mean, please explain more if you can

  17. #17
    PowerPoster
    Join Date
    May 2006
    Posts
    2,988

    Re: ShellExecute and wait

    see the attached example, also uses a simple timer to check whether the program is open or closed. Just stripped it down from a shell app i use, where i check whether multiple programs are opened to show icons or not. .. you can just change the variables into arrays if you want to check more than one program at the same time (or i can put the arrays back). Dont know if this is what you are looking for or not, but here it is anyway ..
    Last edited by rory; Aug 16th, 2006 at 08:49 AM.

  18. #18
    Frenzied Member pnish's Avatar
    Join Date
    Aug 2002
    Location
    Tassie, Oz
    Posts
    1,918

    Re: ShellExecute and wait

    I didn't look at rory's example, but here's some code to do what you want
    VB Code:
    1. Option Explicit
    2. '
    3. '   Windows API/Public Declarations for executing (shell) a process synchronously
    4. '
    5. Private Type STARTUPINFO
    6.     cb As Long
    7.     lpReserved As String
    8.     lpDesktop As String
    9.     lpTitle As String
    10.     dwX As Long
    11.     dwY As Long
    12.     dwXSize As Long
    13.     dwYSize As Long
    14.     dwXCountChars As Long
    15.     dwYCountChars As Long
    16.     dwFillAttribute As Long
    17.     dwFlags As Long
    18.     wShowWindow As Integer
    19.     cbReserved2 As Integer
    20.     lpReserved2 As Long
    21.     hStdInput As Long
    22.     hStdOutput As Long
    23.     hStdError As Long
    24. End Type
    25.  
    26. Private Type PROCESS_INFORMATION
    27.     hProcess As Long
    28.     hThread As Long
    29.     dwProcessID As Long
    30.     dwThreadID As Long
    31. End Type
    32.  
    33. Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
    34. 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
    35. Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    36.  
    37. Private Const NORMAL_PRIORITY_CLASS = &H20&
    38. Private Const INFINITE = -1&
    39.  
    40. Public Sub ExecCmdSynch(ByVal cmd As String)
    41.     '
    42.     '   Shell to a process and wait for it to finish executing
    43.     '
    44.     Dim ret As Long
    45.     Dim proc As PROCESS_INFORMATION
    46.     Dim start As STARTUPINFO
    47.    
    48.     ' Initialize the STARTUPINFO structure:
    49.     start.cb = Len(start)
    50.    
    51.     ' Start the shelled application:
    52.     ret = CreateProcessA(0&, cmd, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)
    53.    
    54.     ' Wait for the shelled application to finish:
    55.     ret = WaitForSingleObject(proc.hProcess, INFINITE)
    56.     ret = CloseHandle(proc.hProcess)
    57.    
    58. End Sub
    59.  
    60. Private Sub Form_Load()
    61.     '
    62.     ' Call it like this.....
    63.     '
    64.     Dim exe As String
    65.     Dim params As String
    66.    
    67.     params = "c:\test.txt"
    68.     exe = Trim$("C:\Windows\Notepad.exe" & " " & params)
    69.    
    70.     ExecCmdSynch exe
    71.  
    72. End Sub
    Pete

    No trees were harmed in the making of this post, however a large number of electrons were greatly inconvenienced.

  19. #19
    PowerPoster
    Join Date
    May 2006
    Posts
    2,988

    Re: ShellExecute and wait

    Yeah but that hangs the app until the exe is closed, which what i posted doesnt do..

  20. #20

    Thread Starter
    Lively Member
    Join Date
    Jul 2006
    Posts
    126

    Re: ShellExecute and wait

    Thx a lot...I'll try it out.

    But isn't it possible to somehow catch the error for GetObject and then go to an errorhandler and wait there for maybe 1 sec, and then again return to GetObject, and do this as long as GetObject generates an error? That could be a plausible solution. I had something like:

    On Error GoTo ErrorHandler

    Set app = GetObject(...)


    ErrorHandler:

    'Here I loop for a couple of seconds
    Resume


    But this doesn't work :S
    Any idea on how to write something like this?

    [Edit]: I didn't see that you guys wrote after Rory's code example. Rory is correct, I don't want the program to wait untill the application closes because there is a script that I want to run when the application is fully loaded.

    [Edit]: Seems to work now
    I have following code:

    On Error GoTo Handler
    intSection = 1
    Set objApp = GetObject(, "MGCPCB.Application")
    intSection = 0

    Handler:
    If intSection = 1 Then
    Sleep 500 ' wait 1/2 seconds
    Resume 'resume code at the GetObject line
    Else
    MsgBox "Great!"
    End If

    Seems to work good
    Last edited by Striver; Aug 2nd, 2006 at 05:23 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width