Re: ShellExecute and wait
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.
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.
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?
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.
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
Re: ShellExecute and wait
Maybe you want to look into using the WaitForInputIdle API function.
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.
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 :(
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.
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...
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.
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.
Re: ShellExecute and wait
have you tried enum windows and then a timer to check if it is still open?
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 :)
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 ..
Re: ShellExecute and wait
I didn't look at rory's example, but here's some code to do what you want
VB Code:
Option Explicit
'
' Windows API/Public Declarations for executing (shell) a process synchronously
'
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 Const NORMAL_PRIORITY_CLASS = &H20&
Private Const INFINITE = -1&
Public Sub ExecCmdSynch(ByVal cmd As String)
'
' Shell to a process and wait for it to finish executing
'
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&, cmd, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)
' Wait for the shelled application to finish:
ret = WaitForSingleObject(proc.hProcess, INFINITE)
ret = CloseHandle(proc.hProcess)
End Sub
Private Sub Form_Load()
'
' Call it like this.....
'
Dim exe As String
Dim params As String
params = "c:\test.txt"
exe = Trim$("C:\Windows\Notepad.exe" & " " & params)
ExecCmdSynch exe
End Sub
Re: ShellExecute and wait
Yeah but that hangs the app until the exe is closed, which what i posted doesnt do..
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 :)