ShellWait

Status
Niet open voor verdere reacties.

Labordus

Gebruiker
Lid geworden
1 nov 2017
Berichten
13
In mijn ACESS-applicatie gebruik ik -met enig succes- de functie ShellWait. Het is een functie die vrij beschikbaar is gesteld en vrij gebruikt mag worden. De bedoeling ervan is, dat je een externe applicatie aanroept en dat de aanroepende applicatie wacht tot die klaar is.
Dat werkt prima behalve als die externe applicatie Internet Explorer is. Dan gaat de code in de aanroepende applicatie gewoon verder.
Ik wil graag vanuit mijn Access-applicatie via Internet naar mijn bank om afschriften op te halen e.d. Bij terugkomst moeten die dan op een bepaalde manier verwerkt worden. Nou kan ik het wachten forceren door op een bepaalde plek een Msgebox te plaatsen, maar dat is hier even wat minder elegant. Vandaar de wens de ShellWait-functie hier in te zetten. Maar dat werkt dus niet, zo schijnt het.
Is daar een aanwijsbare reden en een oplossing voor?

Wellicht ten overvloede geef ik hier de betreffende code.
Option Compare Database

'This code was originally written by Terry Kreft.
'It is not to be altered or distributed,
'except as part of an application.
'You are free to use it in any application,
'provided the copyright notice is left unchanged.
'
'Code Courtesy of
'Terry Kreft
Private Const STARTF_USESHOWWINDOW& = &H1
Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const INFINITE = -1&

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

Public Sub ShellWait(Pathname As String, Optional windowStyle As Long)
Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO
Dim ret As Long
' Initialize the STARTUPINFO structure:
With start
.cb = Len(start)
If Not IsMissing(windowStyle) Then
.dwFlags = STARTF_USESHOWWINDOW
.wShowWindow = windowStyle
End If
End With
' Start the shelled application:
ret& = CreateProcessA(0&, Pathname, 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
 
Doe ons een lol en zet de code nog even tussen CODE tags dan is hij wat leesbaarder.
 
Vraag is niet opgelost
ShellWait


Het had wat voeten in aarde......
Maar ik neem aan dat dit is wat er bedoeld werd?

Code:
Option Compare Database

'This code was originally written by Terry Kreft.
'It is not to be altered or distributed,
'except as part of an application.
'You are free to use it in any application,
'provided the copyright notice is left unchanged.
'
'Code Courtesy of
'Terry Kreft
Private Const STARTF_USESHOWWINDOW& = &H1
Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const INFINITE = -1&

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

Public Sub ShellWait(Pathname As String, Optional windowStyle As Long)
Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO
Dim ret As Long
' Initialize the STARTUPINFO structure:
With start
.cb = Len(start)
If Not IsMissing(windowStyle) Then
.dwFlags = STARTF_USESHOWWINDOW
.wShowWindow = windowStyle
End If
End With
' Start the shelled application:
ret& = CreateProcessA(0&, Pathname, 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
 
Laatst bewerkt:
Natuurlijk bleef ik ook zelf experimenteren en onderzoeken en het probleem is opgelost, hoewel ik de oplossing niet goed (of eigenlijk: helemaal) niet begrijp.
Het probleem bleek opgelost te kunnen worden door niet met het volledige pad naar Iexplorer.exe te verwijzen, maar alleen de applicatienaam zelf op te nemen in de aanroep.
Ik snap niet hoe of waarom dat verschil maakt.
Het tweede is, dat ik in codevoorbeelden altijd maar een enkel aanhalingsteken zie om padnamen, waar spaties in voorkomen, terwijl ik altijd drie aanhalingstekens moet geven.
Als iemand me vooral met het eerst genoemde een beetje uit de mist kan helpen zou ik dat erg prettig vinden.
 
Ik vermoed dat IExplorer in een systeempad zit, net als Word en Excel trouwens. Als je die laatsten via een CreateObject opent, hoef je ook alleen maar de programma-analyse mee te geven. Je codevoorbeeld was in die zin ook niet compleet omdat je alleen de functie hebt geplaatst, niet het gebruik ervan. En dan is zo’n probleem voor ons totaal niet te duiden of op te lossen.
 
Nee, dat snap ik nu! Ik ben nooit op die gedachte gekomen, omdat ik er -veel te stellig- vanuit ging dat het wel ergens in die functie zou zitten.

Dat overkomt me dus niet meer (denk ik).
Niettemin dank voor de reactie.
 
En toch heb ik opnieuw hulp nodog op dit onderwerp.
Ik dacht dat de kwestie was opgelost, maar vandaag werkt het helemaal niet meer.
De situatie is als volgt.
Ik gebruik de volgende aanroep naar de functie ShellWait.
Code:
Function test()

     Command = "C:\Program Files (x86)\Microsoft Office\Office14\Excel.exe"
        modShellWait.ShellWait Command, 1


'/     Command = "iexplore.exe" + Space(1) + "http://www." + mijnBankNaam + ".nl"
     Command = "C:\Program Files (x86)\Internet Explorer\iexplore.exe" + Space(1) + "http://www." + mijnBankNaam  + ".nl"
        modShellWait.ShellWait Command, 1

End Function

In deze vorm werkt het precies zoals bedoeld.
Als je de command-string omdraait en eerst de aanroep naar Internet Explorer plaatst dan wacht de een niet op de ander en starten ze vrijwel gelijktijdig.
Als je bij de Internet Explorer-aanroep het pad weglaat start die helemaal niet meer. WaitForSingleObject genereert dan de code -1. (Bij Excel werkt dat dan weer wel).
Ik ben hier nu een beetje de weg kwijt en zou enige verdere hulp erg op prijsstellen.
 
Ik snap niet helemaal waarom je Excel niet zo opent:
Code:
    Set oExcel = GetObject(, "Excel.Application")

Bij mij werkt dit prima:
Code:
    Command = "iexplore.exe" & Space(1) etc
 
Dank je wel voor de ondersteuning.
Maar mag ik aannemen, dat de WaitForSingleObject in de ShellWaitcode bij jou ook de waarde -1 oplevert en dat de wachtfunctie dus niet werkt?
En ik gebruik hier de GetObject-methode niet, omdat ik niet kan bedenken hoe ik daarmee die wachtfunctie voor de rest van de code kan implementeren. Want daar gaat het me steeds om. Het uitvoeren van de code, die volgt na de aanroep van IE moet wachten tot IE weer afgesloten is.
 
Het lijkt er een beetje op dat ik met mijn laatste reactie Octafish op een of andere manier voor het hoofd gestoten heb. Als dat zo is spijt me dat en was dat geenszins de bedoeling. Ik hoopte eigenlijk op een richtingwijzer hoe ik met het aanmaken van een object coor Excel ook zo'n wait-functie kon implementeren. Maar misschien kan dat wel helemaal niet.
 
Het lijkt er een beetje op dat ik met mijn laatste reactie Octafish op een of andere manier voor het hoofd gestoten heb.
Valt wel mee, ik heb een harde kop :). Ik was gewoon nog niet toegekomen aan het verder oplossen van je probleem. Ik snap je proces ook nog niet helemaal; je hebt een database waar je wat dingen in opslaat, neem ik aan. Vervolgens heb je bankgegevens die je ophaalt vanuit een webquery o.i.d. of wellicht een export vanuit de bankapplicatie. Tot zover snap ik het nog. Maar waarom je dan Excel er tussendoor gooit, ontgaat mij dus. Ik zou zeggen: als je de bankgegevens hebt opgeslagen, kun je ze verder verwerken in de database.
 
Mooi. (Maar was die harde kop hier inderdaad nodig?)
Inderdaad gaat het erom dat ik via Internet Explorer een of meer CSV-bestanden ophaal. Die moeten dan ingelezen en in SQL-statements worden omgezet om in de database terecht te komen. Het deel van de procedure, waarmee die conversie geregeld wordt, mag pas uitgevoerd worden nadat de betroffen bestanden zijn overgehaald en IE afgesloten is. Vandaar die ShellWait-functie. Excel figureerde hier eigenlijk alleen maar om te onderzoeken hoe ik die ShellWait kon laten werken.
Overigens ben ik nu zover dat ik IE als object aan kan maken. Ik ben er alleen nog niet uit hoe je nu de verdere uitvoering van de code kunt laten wachten op het afsluiten van IE. Ik heb wat geprobeerd met Loops, maar heb nog niet uitgevonden hoe je kunt uitlezen dat IE is afgesloten.
Maakt dit het duidelijk(er)?
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan