factoredunbeliever
asked on
Problem with recursive ShellExecuteEx on Wiindows XP but not under 2000
Hi All
OK This is a wierd one for you. My App crashes when I call ShellExecuteEx under Windows XP, This only happens after one of the Patches has been applied (Not sure which one yet, we are trying to find this out at the moment, although it is a patch prior to Service Pack 1)
Anyway, here goes, I have an out of process EXE (ActiveX exe) server running as an addin to MS Word. The User opens a document by clicking a link or whatever, and I ShellEx the document and wait for confirmation from the Word events that the document has indeed been opened. This all works fine.
So basically,
On a form, user clicks link which shellex a document (Sits in idle loop until global boolean is set) (NOTE: project is SINGLE THREADED, i.e. global accessible anywhere)
A Class which is an addin for word monitors word events for the document open event to confirm, updates boolean
Form Does some work now that can exit loop.
Closes Document
This works perfectly (even on XP)
Do it twice... Kaboom....
So let us say we do the following, we want to open do 3 files in a loop,
1. Open First File fine (with shellex)
2. Process File
3. Close File
2. Open Second File (with Shell ex) Crash... No message nothing. I only experience this on XP...
I am at my wits end here with this one... So if someone knows the answer please help.
OK This is a wierd one for you. My App crashes when I call ShellExecuteEx under Windows XP, This only happens after one of the Patches has been applied (Not sure which one yet, we are trying to find this out at the moment, although it is a patch prior to Service Pack 1)
Anyway, here goes, I have an out of process EXE (ActiveX exe) server running as an addin to MS Word. The User opens a document by clicking a link or whatever, and I ShellEx the document and wait for confirmation from the Word events that the document has indeed been opened. This all works fine.
So basically,
On a form, user clicks link which shellex a document (Sits in idle loop until global boolean is set) (NOTE: project is SINGLE THREADED, i.e. global accessible anywhere)
A Class which is an addin for word monitors word events for the document open event to confirm, updates boolean
Form Does some work now that can exit loop.
Closes Document
This works perfectly (even on XP)
Do it twice... Kaboom....
So let us say we do the following, we want to open do 3 files in a loop,
1. Open First File fine (with shellex)
2. Process File
3. Close File
2. Open Second File (with Shell ex) Crash... No message nothing. I only experience this on XP...
I am at my wits end here with this one... So if someone knows the answer please help.
'ADD THE FOLLOWING TO A .BAS MODULE
'
Public Declare Function FindExecutable Lib "shell32.dll" Alias _
"FindExecutableA" (ByVal lpFile As String, ByVal lpDirectory As _
String, ByVal lpResult As String) As Long
Public Declare Function ShellExecute _
Lib "shell32.dll" Alias _
"ShellExecuteA" (ByVal _
hwnd As Long, ByVal lpOperation As _
String, ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nShowCmd As Long) As Long
Public Const SW_SHOWNORMAL = 1
Function LaunchMSDOC(Frm As Form, myDOC As String)
Dim TName As String, DumbFile As String
Dim BrowserExec As String * 255
Dim RetVal As Long
Dim FileN As Integer
' First, create a known, temporary DOC file
BrowserExec = Space(255)
TName = "C:\tempdocuments.doc" 'temp document file to find association
FileN = FreeFile
Open TName For Output As #FileN ' Create temp DOC file
Write #FileN, "MS WORD TEMP .DOC FILE"
Close #FileN ' Close file
' Then find the application associated w
' ith it
RetVal = FindExecutable(TName, DumbFile, BrowserExec)
BrowserExec = Trim(BrowserExec)
'If an application is found, launch it!
If RetVal <= 32 Or IsEmpty(BrowserExec) Then ' Error
MsgBox "Could Not find associated Browser", vbExclamation, _
"Browser Not Found"
Else
RetVal = ShellExecute(Frm.hwnd, "open", BrowserExec, _
myDOC, DumbFile, SW_SHOWNORMAL)
End If
' End If
Kill TName ' delete temp .DOC FILE
End Function
'execute 3 files
doevents
Call LaunchMSDOC(Form1, "c:\temp1.doc")
Call LaunchMSDOC(Form1, "c:\temp2.doc")
Call LaunchMSDOC(Form1, "c:\temp3.doc")
'
Public Declare Function FindExecutable Lib "shell32.dll" Alias _
"FindExecutableA" (ByVal lpFile As String, ByVal lpDirectory As _
String, ByVal lpResult As String) As Long
Public Declare Function ShellExecute _
Lib "shell32.dll" Alias _
"ShellExecuteA" (ByVal _
hwnd As Long, ByVal lpOperation As _
String, ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nShowCmd As Long) As Long
Public Const SW_SHOWNORMAL = 1
Function LaunchMSDOC(Frm As Form, myDOC As String)
Dim TName As String, DumbFile As String
Dim BrowserExec As String * 255
Dim RetVal As Long
Dim FileN As Integer
' First, create a known, temporary DOC file
BrowserExec = Space(255)
TName = "C:\tempdocuments.doc" 'temp document file to find association
FileN = FreeFile
Open TName For Output As #FileN ' Create temp DOC file
Write #FileN, "MS WORD TEMP .DOC FILE"
Close #FileN ' Close file
' Then find the application associated w
' ith it
RetVal = FindExecutable(TName, DumbFile, BrowserExec)
BrowserExec = Trim(BrowserExec)
'If an application is found, launch it!
If RetVal <= 32 Or IsEmpty(BrowserExec) Then ' Error
MsgBox "Could Not find associated Browser", vbExclamation, _
"Browser Not Found"
Else
RetVal = ShellExecute(Frm.hwnd, "open", BrowserExec, _
myDOC, DumbFile, SW_SHOWNORMAL)
End If
' End If
Kill TName ' delete temp .DOC FILE
End Function
'execute 3 files
doevents
Call LaunchMSDOC(Form1, "c:\temp1.doc")
Call LaunchMSDOC(Form1, "c:\temp2.doc")
Call LaunchMSDOC(Form1, "c:\temp3.doc")
The reason your not getting an error message is because you are using
ON ERROR RESUME NEXT
Remove that line and run your code...your should us IF ERR instead to trap all your errors instead of using ON ERROR RESUME NEXT
remove ON ERROR RESUME NEXT and see what error it gives you.
ON ERROR RESUME NEXT
Remove that line and run your code...your should us IF ERR instead to trap all your errors instead of using ON ERROR RESUME NEXT
remove ON ERROR RESUME NEXT and see what error it gives you.
Let me correct myself
example:
On Error GoTo iserror:
'c:\nothing.txt does not exists return me an error number
Shell "c:\nothing.txt", vbNormalFocus
iserror:
MsgBox Err
example:
On Error GoTo iserror:
'c:\nothing.txt does not exists return me an error number
Shell "c:\nothing.txt", vbNormalFocus
iserror:
MsgBox Err
ASKER
To elg1044
On error resume next
and If err.number = x
are inline error handling and the errors do get passed through
As to your first response using FindExecutable, this procedure has already been completed earlier on startup
For your own improvement
On Error Resume next and On error goto Failure catch the same exceptions in the error object the only difference is that the on error goto sends you to a label. On error resume next with an if statement is just as effective and in many case far more useful.
i.e.
on error resume next
x = 10 / 0
if err.number= 0 then
msgbox "GOOD"
else
msgbox err.description
end if
is the same as
on error goto Failuire
x = 10 / 0
msgbox "Good"
exit function 'or what ever
Failure:
msgbox err.description
I just happen to prefer inline error handling.
As to the reason for the problem, I have subsequently discovered that some Antivirus under XP think my executable as it is also a MS Addin is a virus, and the anti virus terminates the application using endprocess, hence the reason there is no error and the debugger is also killed.
The only version of anti virus that I have found so far that does this is AVG 7.0, but with more testing I believe I will find more.
There I have answered my own question.
Moderators, cancel this question and delete it.
On error resume next
and If err.number = x
are inline error handling and the errors do get passed through
As to your first response using FindExecutable, this procedure has already been completed earlier on startup
For your own improvement
On Error Resume next and On error goto Failure catch the same exceptions in the error object the only difference is that the on error goto sends you to a label. On error resume next with an if statement is just as effective and in many case far more useful.
i.e.
on error resume next
x = 10 / 0
if err.number= 0 then
msgbox "GOOD"
else
msgbox err.description
end if
is the same as
on error goto Failuire
x = 10 / 0
msgbox "Good"
exit function 'or what ever
Failure:
msgbox err.description
I just happen to prefer inline error handling.
As to the reason for the problem, I have subsequently discovered that some Antivirus under XP think my executable as it is also a MS Addin is a virus, and the anti virus terminates the application using endprocess, hence the reason there is no error and the debugger is also killed.
The only version of anti virus that I have found so far that does this is AVG 7.0, but with more testing I believe I will find more.
There I have answered my own question.
Moderators, cancel this question and delete it.
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
ASKER
Another function loops the code below...
'----Main Open code----
If mvarFSO.FileExists(sFileNa
mOfficeFunctions.OfficeThr
On Error Resume Next
VBShellEx sFileName, 0
If Err.Number <> 0 Then
MsgBox "Error with ShellEx" & vbNewLine & _
Err.Number & vbNewLine & _
Err.Description & _
Err.LastDllError, vbOKOnly + vbSystemModal
Exit sub
End If
Retry:
lCount = 0
bError = False
While mOfficeFunctions.OfficeThr
DoEvents
VBSleepEx 200, True
lCount = lCount + 1
If lCount = 150 Then
bError = True
Else
bError = False
End If
Wend
If bError Then
'-----Just stuff to ensure not wait forever...
OK the VBShellEx is as follows....
Public Function VBShellEx(ByVal sFileName As String, ByVal OwnerHwnd As Long) As Boolean
Dim lHwndOwner As Long
If OwnerHwnd = 0 Then
lHwndOwner = GetDesktopWindow
Else
lHwndOwner = OwnerHwnd
End If
On Error Resume Next
Dim lResult As Long
Dim sQuoted As String
Dim sShort As String
Dim sStr As String
Dim sei As SHELLEXECUTEINFO
sShort = sFileName
If IsNT Then
sShort = Trim$(VBGetShortPathName(s
sQuoted = sShort
Else
sShort = sFileName
sQuoted = QuoteFile(sShort) '----All others quoted file names "c:\program files\blah.doc" etc (Handles spaces
End If
With sei
.cbSize = LenB(sei)
.fMask = SEE_MASK_FLAG_DDEWAIT Or SEE_MASK_FLAG_NO_UI Or SEE_MASK_NOZONECHECKS
.hwnd = lHwndOwner
.lpVerb = "Open"
.lpFile = sQuoted
.nShow = 1
End With
lResult = ShellExecuteEx(sei) '----Causes App crash on second call... Only on XP... No message box or any clue... Even kills debugger (c++ attached to process)... Really cool...
If lResult <= 32 Then
'----Crap Shouldn't Happen though
VBShellEx = false
else
VBShellEx = True
End If
End Function
'----Word Event handler simply put
mOfficeFunctions.OfficeThr