Automation Issues

J

jason.vanbrackel

I have a VB6 Application that shells out some activity to another VB6
application in a separate thread. This second application relies
heavily upon the Microsoft Access 10.0 Object Library. I have also
used the Microsoft Access 11.0 Object Library. This second application
grabs recordsets from the Access mdb by using the below set of
commands.

Set qdfX = objAccess.CurrentDb.CreateQueryDef("", strSQLX)
Set rstX = qdfX.OpenRecordset()

I did not write this and I personally find this method of grabbing data
from Access to be a rather poor design choice, but it is entrenched
within the application, and it is unlikely that I can change it at this
point.

I believe the use of the automation in this manner may be causing the
application to freeze on some machines. It causes it and its parent
application to freeze as well. The rest of the machine continues to
run normally, and I have to kill the processes in Task Manager.

The second app is started from the first application with the code
below

ExecCmdLineEx """" & gstrDataManagerPath & "\" & DATA_MANAGER_EXE & """
-e[i2] -a[1]", SW_SHOWMINNOACTIVE, ABOVE_NORMAL_PRIORITY_CLASS

----ExecCmdLineEx Module----

Option Explicit

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
String, _
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
String, _
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 INFINITE = -1&

'Show Window Constants
Private Const SW_HIDE = 0
Private Const SW_SHOWNORMAL = 1
Private Const SW_SHOWMINIMIZED = 2
Private Const SW_MAXIMIZE = 3
Private Const SW_SHOWMAXIMIZED = 3
Private Const SW_SHOWNOACTIVATE = 4
Private Const SW_SHOW = 5
Private Const SW_MINIMIZE = 6
Private Const SW_SHOWMINNOACTIVE = 7
Private Const SW_SHOWNA = 8
Private Const SW_RESTORE = 9
Private Const SW_SHOWDEFAULT = 10
'End Show Window Constants

'Priority Class Constants
Private Const REALTIME_PRIORITY_CLASS = &H100&
Private Const HIGH_PRIORITY_CLASS = &H80&
Private Const ABOVE_NORMAL_PRIORITY_CLASS = &H8000&
Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const BELOW_NORMAL_PRIORITY_CLASS = &H4000&
Private Const IDLE_PRIORITY_CLASS = &H40&
'End Priority Class Constants

Public Function ExecCmdLineEx( _
szCommandLine, _
Optional nCmdShow As Variant, _
Optional dwPriorityCreationFlags As
Variant _
) As Long

Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO
Dim lngReturnCode As Long

Const STARTF_USESHOWWINDOW = &H1

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

'If this is missing then wShowWindow is ignored
.dwFlags = STARTF_USESHOWWINDOW
If (IsNull(nCmdShow)) Then
.wShowWindow = SW_SHOW
Else
.wShowWindow = nCmdShow
End If

End With

' Start the shelled application:

If IsNull(dwPriorityCreationFlags) Then
lngReturnCode = CreateProcessA(vbNullString, _
szCommandLine, _
0&, _
0&, _
1&, _
NORMAL_PRIORITY_CLASS, _
0&, _
vbNullString, _
start, _
proc _
)
Else
lngReturnCode = CreateProcessA(vbNullString, _
szCommandLine, _
0&, _
0&, _
1&, _
dwPriorityCreationFlags, _
0&, _
vbNullString, _
start, _
proc _
)
End If

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

ExecCmdLineEx = lngReturnCode

End Function

Any Ideas?
 
D

dbahooker

yeah my idea is:

a) wake up to the 90s and dont use DAO for anything
b) wake up to the 90s and dont use MDB for anything
c) wake up to the 90s and dont use Vb6 for anything.

Access Data Projects are AWESOME!!
 
J

J French

On 17 May 2006 07:14:51 -0700, (e-mail address removed) wrote:

' Wait for the shelled application to finish:
lngReturnCode = WaitForSingleObject(proc.hProcess, INFINITE)

Don't do an infinite wait
- don't wait, use DoEvents to keep your first App alive

'Wait
Do
WaitMessage ' JF
Me.Print ".";
Count = Count + 1
If Count > 100 Then
Count = 0
Me.Cls
End If
DoEvents
Loop While WaitForSingleObject(pinfo.hProcess, 0)
 
A

Anthony Jones

J French said:
On 17 May 2006 07:14:51 -0700, (e-mail address removed) wrote:



Don't do an infinite wait
- don't wait, use DoEvents to keep your first App alive

'Wait
Do
WaitMessage ' JF
Me.Print ".";
Count = Count + 1
If Count > 100 Then
Count = 0
Me.Cls
End If
DoEvents
Loop While WaitForSingleObject(pinfo.hProcess, 0)

This will make this code highly computable while it actually does nothing.
It makes the app responsive to user events which may be a good thing.
OTH the rest of the code in the app needs to take care not to interfere with
this unfinished business or use information from this activity until it's
finished.

Those dots on the screen will becoming thick and fast too.

A small time out of say 500ms might be worth introducing.

If the created process is hung then this look never exits so an additional
counter might be needed to terminate the loop after certain period has
elapsed.
 
J

J French

On Sat, 20 May 2006 12:45:35 +0100, "Anthony Jones"

This will make this code highly computable while it actually does nothing.

No, it will make the App do nothing until there is a Message in the
Apps Windows Message Queue

WaitMessage releases everything to Windows until a Message comes in,
then it returns immediately

I'm assuming that :
WaitForSingleObject(pinfo.hProcess, 0)
generates a WindowsMessage, or more specifically that a closing App
generates one.
It makes the app responsive to user events which may be a good thing.

Sure is
OTH the rest of the code in the app needs to take care not to interfere with
this unfinished business or use information from this activity until it's
finished.

Better that, than have a totally frozen App that cannot even re-paint
itself
Those dots on the screen will becoming thick and fast too.

Not if they are Remmed out
- they are only there in the example to give a visual indication of
what is going on
A small time out of say 500ms might be worth introducing.

Why bother ?
If a message needs processing, then process it
If the created process is hung then this look never exits so an additional
counter might be needed to terminate the loop after certain period has
elapsed.

You are right about that, but that was not the question

If you want to do that then activate a normal VB Timer with a interval
of say 1 sec to act as a Message pump

That way the App will get at least 1 msg per sec, and the code in the
loop can decide when to cop out.

You need to have a serious look at what WaitMessage does, it is a
fascinating beast
- and extremely efficient at keeping down unnecessary processing

It can be used for all sorts of tasks, my favourite is for totally
hijacking the Windows loop
 
A

Anthony Jones

J French said:
On Sat, 20 May 2006 12:45:35 +0100, "Anthony Jones"

nothing.

No, it will make the App do nothing until there is a Message in the
Apps Windows Message Queue

WaitMessage releases everything to Windows until a Message comes in,
then it returns immediately

I'm assuming that :
WaitForSingleObject(pinfo.hProcess, 0)
generates a WindowsMessage, or more specifically that a closing App
generates one.

Oops I didn't spot that WaitMessage function. It might be useful to the OP
to provide it's declare (simple though it might be I didn't spot it and it's
not obvious its an API call):-

Private Declare Function WaitMessage Lib "user32" () As Long

However I can't see how the termination of the launched process would
generate a windows message to cause waitmessage to return.
Sure is


Better that, than have a totally frozen App that cannot even re-paint
itself

Agreed but there is more work that needs to be done and I still don't think
a DoEvents loop is the approach to take.
Not if they are Remmed out
- they are only there in the example to give a visual indication of
what is going on

They would in fact be a little random since they depend on messages
arriving.
Why bother ?
If a message needs processing, then process it

That statement was made without the WaitMessage function being spotted.
You are right about that, but that was not the question

Yes the OP wasn't interested in any of this. It's a little ambiguous but
appears the OP seems to be wondering whether launching the process in this
manner may be the reason it is freezing (the called process). A secondary
affect being that the calling process freezes.

The answer is I doubt this manner of launching the process is causing it to
freeze but it's difficult to tell.
If you want to do that then activate a normal VB Timer with a interval
of say 1 sec to act as a Message pump

That way the App will get at least 1 msg per sec, and the code in the
loop can decide when to cop out.

You need to have a serious look at what WaitMessage does, it is a
fascinating beast
- and extremely efficient at keeping down unnecessary processing

It can be used for all sorts of tasks, my favourite is for totally
hijacking the Windows loop

I think in this case a better design would be to launch the app but not loop
at all.

Use a timer to check whether the process handle has been signalled.

Modify the parent app to ensure invalid actions are not taken whilst this
secondary process is operating.

TBH I've never come across a problem that might be solved using a DoEvents
loop that couldn't be better solved without one. Especially if the
developer is happy dipping into the windows API.
 
J

J French

On Sun, 21 May 2006 08:54:09 +0100, "Anthony Jones"


Oops I didn't spot that WaitMessage function. It might be useful to the OP
to provide it's declare (simple though it might be I didn't spot it and it's
not obvious its an API call):-
Private Declare Function WaitMessage Lib "user32" () As Long

Since the original post was a jiggered form of Shell And Wait from the
KPD All API Guide, I figured that the OP would realize that
WaitMessage is an API
However I can't see how the termination of the launched process would
generate a windows message to cause waitmessage to return.

It seems it does
- when an App unloads it creates a bundle of activity within Windows
- also Windows knows very well which thread launched the App
- I just found that it is reliable
Agreed but there is more work that needs to be done and I still don't think
a DoEvents loop is the approach to take.

Why not ?
a) it is not hammering the processor
b) it is not 'blocking' the App

Anyway an App's Window Message queue is just a loop using a variation
of WaitMessage

// Start the message loop.

while (GetMessage(&msg, (HWND) NULL, 0, 0))

{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
They would in fact be a little random since they depend on messages
arriving.

Less random than you would expect
- they go bananas when you move the mouse, but otherwise there are
very few of them
That statement was made without the WaitMessage function being spotted.
Yes the OP wasn't interested in any of this. It's a little ambiguous but
appears the OP seems to be wondering whether launching the process in this
manner may be the reason it is freezing (the called process). A secondary
affect being that the calling process freezes.

<quote>
I believe the use of the automation in this manner may be causing the
application to freeze on some machines. It causes it and its parent
application to freeze as well.
</quote>

The code is deliberately freezing the Calling App until the Called App
returns
- it has nothing to do with the Called App, once that is running the
calling App has no influence
The answer is I doubt this manner of launching the process is causing it to
freeze but it's difficult to tell.

It is definitely freezing the Caller
- which is pretty darn silly for a 3+ minute process
I think in this case a better design would be to launch the app but not loop
at all.

There are two types of Looping
a) inefficient looping
-using pure DoEvents that raises CPU usage to 100%
b) efficient looping that responds immediately to Windows
Use a timer to check whether the process handle has been signalled.

That is a possibility
- in this case I would use an AX Exe and run the process off its
internal thread
- or use a normal Exe and set up a communications system

Sometimes Waiting is sensible
- especially if there is not much you can do until the thing comes
back with a result
Modify the parent app to ensure invalid actions are not taken whilst this
secondary process is operating.

Dead easy, a Modal Form with an Abort button
TBH I've never come across a problem that might be solved using a DoEvents
loop that couldn't be better solved without one. Especially if the
developer is happy dipping into the windows API.

I am trying to explain to you that

While Something
WaitMessage
DoEvents
Wend

Is NOT a DoEvents Loop
- it is the equivalent of popping up a Modal Form ( and you can be
sure that is how Modal Forms work )

As I said before, you would be wise to look into the implications of
WaitMessage
- a lot of VB programmers don't understand it
 
J

J French

On Sun, 21 May 2006 08:54:09 +0100, "Anthony Jones"


Oops I didn't spot that WaitMessage function. It might be useful to the OP
to provide it's declare (simple though it might be I didn't spot it and it's
not obvious its an API call):-
Private Declare Function WaitMessage Lib "user32" () As Long

Since the original post was a jiggered form of Shell And Wait from the
KPD All API Guide, I figured that the OP would realize that
WaitMessage is an API
However I can't see how the termination of the launched process would
generate a windows message to cause waitmessage to return.

It seems it does
- when an App unloads it creates a bundle of activity within Windows
- also Windows knows very well which thread launched the App
- I just found that it is reliable
Agreed but there is more work that needs to be done and I still don't think
a DoEvents loop is the approach to take.

Why not ?
a) it is not hammering the processor
b) it is not 'blocking' the App

Anyway an App's Window Message queue is just a loop using a variation
of WaitMessage

// Start the message loop.

while (GetMessage(&msg, (HWND) NULL, 0, 0))

{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
They would in fact be a little random since they depend on messages
arriving.

Less random than you would expect
- they go bananas when you move the mouse, but otherwise there are
very few of them
That statement was made without the WaitMessage function being spotted.
Yes the OP wasn't interested in any of this. It's a little ambiguous but
appears the OP seems to be wondering whether launching the process in this
manner may be the reason it is freezing (the called process). A secondary
affect being that the calling process freezes.

<quote>
I believe the use of the automation in this manner may be causing the
application to freeze on some machines. It causes it and its parent
application to freeze as well.
</quote>

The code is deliberately freezing the Calling App until the Called App
returns
- it has nothing to do with the Called App, once that is running the
calling App has no influence
The answer is I doubt this manner of launching the process is causing it to
freeze but it's difficult to tell.

It is definitely freezing the Caller
- which is pretty darn silly for a 3+ minute process
I think in this case a better design would be to launch the app but not loop
at all.

There are two types of Looping
a) inefficient looping
-using pure DoEvents that raises CPU usage to 100%
b) efficient looping that responds immediately to Windows
Use a timer to check whether the process handle has been signalled.

That is a possibility
- in this case I would use an AX Exe and run the process off its
internal thread
- or use a normal Exe and set up a communications system

Sometimes Waiting is sensible
- especially if there is not much you can do until the thing comes
back with a result
Modify the parent app to ensure invalid actions are not taken whilst this
secondary process is operating.

Dead easy, a Modal Form with an Abort button
TBH I've never come across a problem that might be solved using a DoEvents
loop that couldn't be better solved without one. Especially if the
developer is happy dipping into the windows API.

I am trying to explain to you that

While Something
WaitMessage
DoEvents
Wend

Is NOT a DoEvents Loop
- it is the equivalent of popping up a Modal Form ( and you can be
sure that is how Modal Forms work )

As I said before, you would be wise to look into the implications of
WaitMessage
- a lot of VB programmers don't understand it
 
A

Anthony Jones

J French said:
On Sun, 21 May 2006 08:54:09 +0100, "Anthony Jones"





Since the original post was a jiggered form of Shell And Wait from the
KPD All API Guide, I figured that the OP would realize that
WaitMessage is an API


It seems it does
- when an App unloads it creates a bundle of activity within Windows
- also Windows knows very well which thread launched the App
- I just found that it is reliable

Hmm.. seems a bit wolly. You may be right. As a process tears itself down
it may remember what thread launched it. It may look for a window message
pump queue thingy on that thread (does every thread in windows have on
these? I don't think so). It may decide to put a message in that queue to
the effect that 'a process you created is now finished'.

It would be nice know for sure that that is what is happening. At the
moment I think it's more likely that is works simply because some messages
will be passing through anyway.

Why not ?
a) it is not hammering the processor
b) it is not 'blocking' the App

How many of these loops would you want in your app? What if the process you
launched never dies, does this loop stay inplace.

Anyway an App's Window Message queue is just a loop using a variation
of WaitMessage

// Start the message loop.

while (GetMessage(&msg, (HWND) NULL, 0, 0))

{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

Yeah but one of these is already there do we want to create others also?
<quote>
I believe the use of the automation in this manner may be causing the
application to freeze on some machines. It causes it and its parent
application to freeze as well.
</quote>

The code is deliberately freezing the Calling App until the Called App
returns
- it has nothing to do with the Called App, once that is running the
calling App has no influence


It is definitely freezing the Caller
- which is pretty darn silly for a 3+ minute process

Perhaps I've read the question wrong.
There are two types of Looping
a) inefficient looping
-using pure DoEvents that raises CPU usage to 100%
b) efficient looping that responds immediately to Windows
c) Don't bother
That is a possibility
- in this case I would use an AX Exe and run the process off its
internal thread
- or use a normal Exe and set up a communications system

Sometimes Waiting is sensible
- especially if there is not much you can do until the thing comes
back with a result

Agreed


Dead easy, a Modal Form with an Abort button

Ah now it makes sense. Your WaitMessage/DoEvents loop coupled with this
should work nicely.
I am trying to explain to you that

While Something
WaitMessage
DoEvents
Wend

Is NOT a DoEvents Loop
- it is the equivalent of popping up a Modal Form ( and you can be
sure that is how Modal Forms work )

As I said before, you would be wise to look into the implications of
WaitMessage

Doesn't look like I need to. What else is there to learn that you haven't
already explained :)
- a lot of VB programmers don't understand it

I think it's more like never heard of it. I hadn't and I've been doing VB
for more years than I care to admit. (although not a great deal of UI
work).
 
A

Anthony Jones

J French said:
On Sun, 21 May 2006 08:54:09 +0100, "Anthony Jones"





Since the original post was a jiggered form of Shell And Wait from the
KPD All API Guide, I figured that the OP would realize that
WaitMessage is an API


It seems it does
- when an App unloads it creates a bundle of activity within Windows
- also Windows knows very well which thread launched the App
- I just found that it is reliable

Hmm.. seems a bit wolly. You may be right. As a process tears itself down
it may remember what thread launched it. It may look for a window message
pump queue thingy on that thread (does every thread in windows have on
these? I don't think so). It may decide to put a message in that queue to
the effect that 'a process you created is now finished'.

It would be nice know for sure that that is what is happening. At the
moment I think it's more likely that is works simply because some messages
will be passing through anyway.

Why not ?
a) it is not hammering the processor
b) it is not 'blocking' the App

How many of these loops would you want in your app? What if the process you
launched never dies, does this loop stay inplace.

Anyway an App's Window Message queue is just a loop using a variation
of WaitMessage

// Start the message loop.

while (GetMessage(&msg, (HWND) NULL, 0, 0))

{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

Yeah but one of these is already there do we want to create others also?
<quote>
I believe the use of the automation in this manner may be causing the
application to freeze on some machines. It causes it and its parent
application to freeze as well.
</quote>

The code is deliberately freezing the Calling App until the Called App
returns
- it has nothing to do with the Called App, once that is running the
calling App has no influence


It is definitely freezing the Caller
- which is pretty darn silly for a 3+ minute process

Perhaps I've read the question wrong.
There are two types of Looping
a) inefficient looping
-using pure DoEvents that raises CPU usage to 100%
b) efficient looping that responds immediately to Windows
c) Don't bother
That is a possibility
- in this case I would use an AX Exe and run the process off its
internal thread
- or use a normal Exe and set up a communications system

Sometimes Waiting is sensible
- especially if there is not much you can do until the thing comes
back with a result

Agreed


Dead easy, a Modal Form with an Abort button

Ah now it makes sense. Your WaitMessage/DoEvents loop coupled with this
should work nicely.
I am trying to explain to you that

While Something
WaitMessage
DoEvents
Wend

Is NOT a DoEvents Loop
- it is the equivalent of popping up a Modal Form ( and you can be
sure that is how Modal Forms work )

As I said before, you would be wise to look into the implications of
WaitMessage

Doesn't look like I need to. What else is there to learn that you haven't
already explained :)
- a lot of VB programmers don't understand it

I think it's more like never heard of it. I hadn't and I've been doing VB
for more years than I care to admit. (although not a great deal of UI
work).
 
J

J French

On Sun, 21 May 2006 14:29:50 +0100, "Anthony Jones"

I see that you are a Dori Previn Fan
- I went to school with her daughter

Yada Yada is a great track - it even gets me, and I am a-musical

On the subject, Windows is a deliberate illusion

Mostly, I like to explain things to those that should know

- you will probably want to know, it took me time to understand

Right now I am inebreiated - tomorrow I shall spell ( as in spell )
- and like most of us, show the devious paths

Just look into WaitMessage or do a Google search
- it is rather interesting
 
J

J French

On Sun, 21 May 2006 14:29:50 +0100, "Anthony Jones"

I see that you are a Dori Previn Fan
- I went to school with her daughter

Yada Yada is a great track - it even gets me, and I am a-musical

On the subject, Windows is a deliberate illusion

Mostly, I like to explain things to those that should know

- you will probably want to know, it took me time to understand

Right now I am inebreiated - tomorrow I shall spell ( as in spell )
- and like most of us, show the devious paths

Just look into WaitMessage or do a Google search
- it is rather interesting
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top