Solved IE.Quit Takes Quite Long Time to Execute (1 Viewer)

Pac-Man

Active member
Local time
Today, 10:57
Joined
Apr 14, 2020
Messages
416
Hello,

I am using Team-Moeller Better Access Chart for fulfilling my needs related to charts and I must admit it is a great effort by the Team-Moeller which made my life easier. When I want to save and use the chart as picture, it takes too long to complete. On digging up, I found that the IE.Quit command take long time to execute. If I comment this line, task taker normal time but which each chart there is a process ieexplorer.exe is left unclosed in the task manager. I don't know how to handle this. I have few thoughts in my mind:
  1. If there could be a way to let the ie.quit execute but the this wouldn't halt the code here. It should do it in parallel process and let next lines of code execute at the same time e.g. opening report. But I don't know how or even whether it's possible or not.
  2. Use collection or scripting dictionary to store these opened tasks and close them in idle time or on close.
  3. Use sledgehammer method to close all IE instances but this will close other opened instances too.
  4. Instead of closing all instances, record process id of opened IE instance while generating the chart and then terminate the process instead of ie.quit. This method seems me better but I don't know how to achieve it.
I came here to share the Better Access Charts and to get help on above issue.

Best Regards
 

Attachments

  • Better-Access-Charts.accdb
    1.7 MB · Views: 34
Last edited:

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 00:57
Joined
Feb 28, 2001
Messages
27,186
If there could be a way to let the ie.quit execute but the this wouldn't halt the code here. It should do it in parallel process and let next lines of code execute at the same time e.g. opening report. But I don't know how or even whether it's possible or not.

Mechanically, what is happening here cannot be completely parallel. You are creating instances of IE, which is a separate task (Windows may also call this a "process") that exists in a separate set of memory than the set Access occupies. (Also called a "working set" when paged memory is involved.) This is significant in that the instance of IE has its own separate resources. But to control IE as an application object, Access has to establish control channels and I/O channels are part of the resources owned by IE. These control channels exist between IE and Access so that they can pass commands and data between them. This is a type of inter-process communication that explains how Access manipulates an application object.

At some point you want to issue the IE.Quit, which is perfectly reasonable to ask. But here is what is going on behind the scenes. EVERY I/O channel used by IE has to be closed (called I/O rundown)... INCLUDING the channels shared with Access.

Here is where a couple of technicalities some into play. First, Access is essentially synchronous with respect to executing code. If you issue the IE.Quit command (from Access), Access cannot execute any code until IE releases those command I/O channels. Which it does in an orderly fashion. (Translation: can't rush the process.)

Second, IE is a "black box" i.e. not open-source. We do not know, and in any case cannot change, the code flow of IE. Which means that when you trigger the shut-down, you have to wait as long as it takes for IE to do any other actions required to eventually reach the point where it releases its channels with Access. If your control channels close earlier than other channels (which is an unpredictable condition), you don't have to wait for those other channels.

I'll tell you that I THINK (remember, IE is a black box) there is a loop in which each channel is commanded in turn to close itself and this loop will close every I/O channel by increasing degrees of force. If it is a file channel, the file is closed, which might involve directory entries. If it is a non-file channel, the driver is notified of the channel's status change request in order to release memory resources. Depending on how many web actions are involved, this could be quite a few channels. And most of them will be networked connections. Sound networking programming principles forbid you to just "drop the channel." You are expected to issue an orderly "release channel" command for every networked channel and WAIT for the channel's partner to acknowledge the drop.

After the last channel closure happens, Access can go on about its business because IE actually IS operating in parallel to release all shared and private memory resources so it can finally shut itself down. Or at least, if you have multiple CPU cores it can operate in parallel. But your process initiated the Quit so it has to wait for the protocol replies that show the IE.Quit has reached a "safe" condition. And as noted earlier, that might be a long-winded operation.

Use collection or scripting dictionary to store these opened tasks and close them in idle time or on close.

Nope. Due to the I/O channels between Access and the opened tasks, you have to do your own cleanup immediately. Otherwise you will have uncloseable channels that will eventually prevent YOUR process / session from closing down.

Use sledgehammer method to close all IE instances but this will close other opened instances too.
Your sledgehammer will likely require you to wait just as long for the scripts as it would for letting Access trigger it, because there is a load of stuff to be done behind the scenes and Windows will protect you from leaving something "dangling." Like those left-over instances of IE you mentioned earlier. Your scripts are for the most part just as linear as Access code.

Instead of closing all instances, record process id of opened IE instance while generating the chart and then terminate the process instead of ie.quit. This method seems me better but I don't know how to achieve it.

There is such a thing as a Win32 API that would allow you to specify a process by its ID and terminate it. Then you would be dependent on the speed of the API code (another black box).

 

Pac-Man

Active member
Local time
Today, 10:57
Joined
Apr 14, 2020
Messages
416
Thanks a lot @The_Doc_Man for such a detailed reply. As 1, 2 are out of options, I am left with option 3 and 4. Sledgehammer will be my last resort if 4 couldn't be applied. Can you share some code or guidelines by which I can get process id of IE that is just created and then terminate the process at the end by just using id instead of Name in where condition of the sledgehammer code? I have seen the link you shared but I don't know how to use it.
 

isladogs

MVP / VIP
Local time
Today, 06:57
Joined
Jan 14, 2017
Messages
18,221
@Pac-Man
In case yu aren't aware, Thomas Moeller (AKA BAC-Man) did an excellent presentation for the Access Europe User Group on his Better Access Charts (BAC) last year. You can find the video at

By popular demand, he was invited back and the follow up session will be on Wed 6 March. Details will be available in the near future at

This time, he will be giving an updated version of his charts for use in the new Edge browser control
 
Last edited:

Pac-Man

Active member
Local time
Today, 10:57
Joined
Apr 14, 2020
Messages
416
Hi @isladogs,

First of all thanks for reply. The video isn't playing and giving error "An error occurred. Please try again later. (Playback ID: sBxjSyYeGaxa6QWh)". Can you recheck the link and post updated one?

As that of edge browser control, all of the users of my project are below office 2019 which means new edge browser control is not available nor is supported by Better Access Charts as it now uses higher version of the charts.js than the one supported by IE based browser control.

I don't know if there is also this issue in edge browser control to take much time at quitting or not. I am facing it in IE based browser control and looking for the solution.

Best Regards
 

isladogs

MVP / VIP
Local time
Today, 06:57
Joined
Jan 14, 2017
Messages
18,221
Sorry - link now fixed
If you haven't yet done so, look at the links on my web article for that video:

I've not experienced any issues in my experiments with Better Access Charts but I haven't looked at them recently.
I know you cannot use the latest version of charts.js with the IE control

However the newer version of the charts.js will be used by Thomas in the updated demo that will be available to accompany the next AEU presentation.
I haven't tested it yet so cannot answer your question
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 00:57
Joined
Feb 28, 2001
Messages
27,186
Here is a possible sledgehammer approach.


NOTE that this is extreme in that if you use it, ALL instances of IE would be affected at once. Use Task Manager to get the exact spelling and punctuation of the programs you want to kill because this method works by name. Thus the name has to be correct or the results won't be so correct. There is also the issue that doing so would affect any and all Access-based application objects that had previously been opened to IE. In essence, you would expect to see errors coming back from any attempt to use IE after swinging the "sledgehammer."
 

Pac-Man

Active member
Local time
Today, 10:57
Joined
Apr 14, 2020
Messages
416
Thanks for reply @The_Doc_Man. I don't want to kill all processes of IE that's why I put sledgehammer approach the last resort. I want to specific id of the instance when it is initiated/created then kill the specific instance. If that is possible, how can it be done, please?
 

Edgar_

Active member
Local time
Today, 00:57
Joined
Jul 8, 2023
Messages
430
I made this, which is what I use to kill all instances of a process.

Code:
Sub ProcessCleanse(processName As String)
    Dim wmi As Object
    Set wmi = GetObject("winmgmts:\\.\root\cimv2")
  
    Dim tasks As Object
    Set tasks = wmi.execquery("Select * From Win32_Process")
  
    Dim item As Object
    For Each item In tasks
        If item.Properties_("Description").Value = processName Then
            item.Terminate
            Exit Sub
        End If
    Next item
End Sub

To use it, just type:
ProcessCleanse "something.exe"

There is a property called "ProcessId" that you can target above before item.Terminate, like
If item.Properties_("ProcessId").Value = TheID Then
 
Last edited:

Edgar_

Active member
Local time
Today, 00:57
Joined
Jul 8, 2023
Messages
430
Choose the property that you think would have the identifier you're looking for, here's a list of the properties and their values for an IE instance opened in my computer:

Caption----iexplore.exe
CommandLine----"C:\Program Files\Internet Explorer\IEXPLORE.EXE"
CreationClassName----Win32_Process
CreationDate----20240114193210.582834-360
CSCreationClassName----Win32_ComputerSystem
CSName----SATELLITE
Description----iexplore.exe
ExecutablePath----C:\Program Files\Internet Explorer\IEXPLORE.EXE
ExecutionState----
Handle----2692
HandleCount----560
InstallDate----
KernelModeTime----1562500
MaximumWorkingSetSize----1380
MinimumWorkingSetSize----200
Name----iexplore.exe
OSCreationClassName----Win32_OperatingSystem
OSName----Microsoft Windows 8.1|C:\WINDOWS|\Device\Harddisk0\Partition4
OtherOperationCount----2590
OtherTransferCount----93453
PageFaults----8390
PageFileUsage----9432
ParentProcessId----2068
PeakPageFileUsage----10500
PeakVirtualSize----2233589858304
PeakWorkingSetSize----29404
Priority----8
PrivatePageCount----9658368
ProcessId----2692
QuotaNonPagedPoolUsage----39
QuotaPagedPoolUsage----384
QuotaPeakNonPagedPoolUsage----72
QuotaPeakPagedPoolUsage----396
ReadOperationCount----344
ReadTransferCount----1441786
SessionId----1
Status----
TerminationDate----
ThreadCount----9
UserModeTime----468750
VirtualSize----2233581174784
WindowsVersion----6.3.9600
WorkingSetSize----29351936
WriteOperationCount----155
WriteTransferCount----584562


Caption----iexplore.exe
CommandLine----"C:\Program Files (x86)\Internet Explorer\IEXPLORE.EXE" SCODEF:2692 CREDAT:144385 /prefetch:2
CreationClassName----Win32_Process
CreationDate----20240114193210.629657-360
CSCreationClassName----Win32_ComputerSystem
CSName----SATELLITE
Description----iexplore.exe
ExecutablePath----C:\Program Files (x86)\Internet Explorer\IEXPLORE.EXE
ExecutionState----
Handle----7592
HandleCount----601
InstallDate----
KernelModeTime----1718750
MaximumWorkingSetSize----1380
MinimumWorkingSetSize----200
Name----iexplore.exe
OSCreationClassName----Win32_OperatingSystem
OSName----Microsoft Windows 8.1|C:\WINDOWS|\Device\Harddisk0\Partition4
OtherOperationCount----2105
OtherTransferCount----96236
PageFaults----14136
PageFileUsage----27156
ParentProcessId----2692
PeakPageFileUsage----31272
PeakVirtualSize----327569408
PeakWorkingSetSize----50260
Priority----8
PrivatePageCount----27807744
ProcessId----7592
QuotaNonPagedPoolUsage----42
QuotaPagedPoolUsage----433
QuotaPeakNonPagedPoolUsage----56
QuotaPeakPagedPoolUsage----480
ReadOperationCount----167
ReadTransferCount----1394120
SessionId----1
Status----
TerminationDate----
ThreadCount----18
UserModeTime----2968750
VirtualSize----303312896
WindowsVersion----6.3.9600
WorkingSetSize----48414720
WriteOperationCount----10
WriteTransferCount----8672

This and much more can be found by debugging this:
Code:
Sub getAllProperties()
    Dim wmi As Object
    Set wmi = GetObject("winmgmts:\\.\root\cimv2")

    Dim tasks As Object
    Set tasks = wmi.execquery("Select * From Win32_Process")

    Dim item As Object
    Dim prop As Object
    For Each item In tasks
        If item.properties_("Description").Value = "iexplore.exe" Then
            For Each prop In item.properties_
                Debug.Print prop.Name & "----" & prop.Value
            Next prop
        End If
    Next item
End Sub

You could write a Stop after the first For Each line and see what you have available to do what you need with precision. Oh will you look at that, there's a CreationDate and all kinds of treasures there.

EDIT: Even though I opened only one instance, it returned the properties for two instances. One must be the main app and the other a tab, maybe... Anyway, have fun.
 
Last edited:

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 00:57
Joined
Feb 28, 2001
Messages
27,186
@Edgar_ - I will confirm your guess to this degree... The process ID of the first listed process is also the parent process ID of the second listed process. So in Windows internal terms, parent/child process. Though I'm a little bit confused on one factor. Since I've not tried this before, I am a little bit unsure about some sizing issues.

The child process shows "PeakVirtualSize----327569408" i.e. 327 Mb. But the parent says "PeakVirtualSize----2233589858304" which is 2.23 Tb and not within the normal addressing range of Win32. On the other hand, "OSCreationClassName----Win32_OperatingSystem" seems to suggest that it really IS Win32. I wonder what that same code would say on a 64-bit system. And the query DID select for only Win32 processes.

So my question for you, Edgar, is: On what bitness of physical machine did you run that test?
 

Edgar_

Active member
Local time
Today, 00:57
Joined
Jul 8, 2023
Messages
430
64-bit Operating System, x64-based processor

If I'm not mistaken, "Select * From Win32_Process" is returning 64 bit processes as well.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 00:57
Joined
Feb 28, 2001
Messages
27,186
Thanks. I'm going to have to diddle with that feature a little. It contains information I recognize based on other O/S experience. I find it interesting that certain fields don't return a value, such as status and execution state. The more I see of this kind of stuff, the more I'm sure that Dave Cutler had a huge hand in this design. A few decades back, when Microsoft and Digital Equipment Corp. had a teaming agreement, MS got a LOT more from DEC than DEC ever got from MS. But the DEC "Galaxy" virtual machine manager DID have the ability to brag that on the right version of hardware you could simultaneously run three different operating systems on the same machine - Windows, UNIX, and OpenVMS.
 

Pac-Man

Active member
Local time
Today, 10:57
Joined
Apr 14, 2020
Messages
416
Hi again,

Just here to update about my issue and post the solution if anyone else want that. I found out if objIE.Quit is executed after some time then it is executed instantly without any delay. Moreover, using dictionary object, these started instances can be stored and can be closed at the time of shutdown of the project all together and are closed instantly as quite a long time might have been passed since initiation.

Best Regards
 

Users who are viewing this thread

Top Bottom