VBA & FEMAP waiting for another application to complete an OLE action
VBA & FEMAP waiting for another application to complete an OLE action
(OP)
I developed a little tool in Excel to do some load combining in FEMAP via its OLE/COM functionality. The tool operates fine, but there is one problem that I seem unable to catch. In the VBA code I create an object (FEMAP application) and thereafter I call a function femap.feFileWriteNastran which generates the Nastran DAT file for analysis. However, during this file export process an error is encountered as a result of a material which is purposely left as is. The result of the error is a message box that basically informs the user that an error was encountered in the writing process (this upon completion of writing the DAT file). The problem is that the message box essentially terminates or stops the execution of the rest of the code until the user clicks "Ok" on the message box. Otherwise, another message box in Excel appears stating that the applications is "waiting for another application to complete an OLE action".
I've tried several approaches to remedy this problem, but I have been unable to catch this error or resolve it any way. If anyone has any solutions or ideas to resolve this, it would be much appreciated
I've tried several approaches to remedy this problem, but I have been unable to catch this error or resolve it any way. If anyone has any solutions or ideas to resolve this, it would be much appreciated





RE: VBA & FEMAP waiting for another application to complete an OLE action
Have you set your Error Trapping options within VBA to Break on Unhandled Errors? If you have done this, you may need to try and use the DoEvents command, or switch to an API call with the WAITINDEFINITE flag set.
HTH
Todd
RE: VBA & FEMAP waiting for another application to complete an OLE action
Basically, the error (which is more like a warning) occurs in FEMAP. This warning creates a dialog box with the following message "Errors have Occurred. Check Message Window". Unless the user clicks "Ok" the "Waiting for another application to complete an OLE action" dialog box in Excel pops up. It's quite troublesome, and often freezes up the computer if left idle.
I have tried to hook FEMAP window in an attempt to process the messages before having them sent to the window and do a EndDialog(hwnd, 0) sort of thing, but I have been unable to get this to work.
RE: VBA & FEMAP waiting for another application to complete an OLE action
The best way to handle this then is probably with an API call to WaitForInputIdle. But, to use input idle, you need to make another API call to CreateProcess to launch your FEMAP program. Here is what I use to tell my application to wait indefinitely for a process to finish before executing another line of code:
In the General section of a module:
CODE
Public Const STARTF_USEPOSITION = &H4
Public Const STARTF_USESIZE = &H2
Public Const STARTF_USESHOWWINDOW = &H1
Public Const SW_RESTORE = 9
Public Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId As Long
End Type
Public 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
Public Declare Function CreateProcess Lib "kernel32" _
Alias "CreateProcessA" _
(ByVal lpApplicationName As String, _
ByVal lpCommandLine As String, _
lpProcessAttributes As Any, _
lpThreadAttributes As Any, _
ByVal bInheritHandles As Long, _
ByVal dwCreationFlags As Long, _
lpEnvironment As Any, _
ByVal lpCurrentDirectory As String, _
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION) As Long
Public Declare Function OpenProcess Lib "kernel32.dll" _
(ByVal dwAccess As Long, _
ByVal fInherit As Integer, _
ByVal hObject As Long) As Long
Public Declare Function TerminateProcess Lib "kernel32" _
(ByVal hProcess As Long, _
ByVal uExitCode As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As Long) As Long
Public Declare Function WaitForInputIdle Lib "user32" _
(ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long
Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Public Const SYNCHRONIZE = 1048576
Public Const NORMAL_PRIORITY_CLASS = &H20&
Public Const INFINITE = -1&
Public Const MAX_PATH = 260
Public Const BM_CLICK = &HF5
Public pInfo As PROCESS_INFORMATION
Public sInfo As STARTUPINFO
Public sNull As String
Public lSuccess As Long
Public lRetValue As Long
Public hAcadWin As Long
Public strApptoRun As String
Public strStartDir As String
Public strAcadDrive As String
Public strAcadDir As String
Public pAE As PROCESS_INFORMATION
Then in the same module, create a routine to launch FEMAP which will define the complete path and filename of the executable, in the chunk below, strApptoRun = "C:\Program Files\AutoCAD\Acad.exe":
CODE
..
With sInfo
.dwFlags = STARTF_USESIZE
.dwX = (Screen.Width / Screen.TwipsPerPixelX) / 2
.dwY = ((Screen.Width / Screen.TwipsPerPixelX) / 2) - 8
.dwXSize = (Screen.Width / Screen.TwipsPerPixelX) / 2
.dwYSize = (Screen.Height / Screen.TwipsPerPixelY) / 2
End With
lSuccess = CreateProcess(lpApplicationName:=sNull, _
lpCommandLine:=strApptoRun, _
lpProcessAttributes:=ByVal 0&, _
lpThreadAttributes:=ByVal 0&, _
bInheritHandles:=1&, _
dwCreationFlags:=NORMAL_PRIORITY_CLASS, _
lpEnvironment:=ByVal 0&, _
lpCurrentDirectory:=strStartDir, _
lpStartupInfo:=sInfo, _
lpProcessInformation:=pInfo)
(Then I still use the GetObject call to set a reference to my now running session of AutoCAD).
The really important part of making this work, is the call to the API WaitForInputIdle. The way this works, is in your code whenever you make a call to your FEMAP program, such as a file open right below that line, you use this call:
CODE
WaitForInputIdle pInfo.hProcess, INFINITE
The WaitForInputIdle stops all further processing until FEMAP is idle.
HTH
Todd
RE: VBA & FEMAP waiting for another application to complete an OLE action
First of all thank you so much for your suggestions. This bug is really unusual. I just implemented the code you posted but unfortunately it still hangs. However, I believe I found the root of the problem. Everything works with Excel (native app) after it creates the FEMAP process. I suspect the problem lies in the modal dialog that FEMAP displays, modal in that the dialog.show doesn't return until the user hit's OK. This is problematic since this will also halt the native app. In fact, the code never even reaches the line WaitForInputIdle:
rc = femap.feFileWriteNastran(0, path) 'hangs here
WaitForInputIdle pInfo.hProcess, INFINITE
This is getting rather interesting. I'm guessing there must be a way to preprocess the create modal dialog event before it is displayed. Perhaps subclass the WinProc of FEMAP in VBA and try to filter out the #32770 class type?
RE: VBA & FEMAP waiting for another application to complete an OLE action
RE: VBA & FEMAP waiting for another application to complete an OLE action
RE: VBA & FEMAP waiting for another application to complete an OLE action
Bummer, could you move your code to FEMAP and just read from Excel... Just a thought.
Todd
RE: VBA & FEMAP waiting for another application to complete an OLE action